mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-05 00:32:03 +00:00
cancel in-flight decryption requests on timeout
This commit is contained in:
parent
f0f5b54768
commit
1e9e9471b7
@ -29,17 +29,25 @@ export const useDecryptContent = () => {
|
|||||||
return await inProgressMap.current.get(cacheKey);
|
return await inProgressMap.current.get(cacheKey);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If the existing promise rejects, we'll try again below
|
// If the existing promise rejects, we'll try again below
|
||||||
console.warn('Previous decryption attempt failed, retrying');
|
if (error.name !== 'AbortError') {
|
||||||
|
console.warn('Previous decryption attempt failed, retrying');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create abort controller for this request
|
||||||
|
const abortController = new AbortController();
|
||||||
|
|
||||||
// Create a new decryption promise for this content
|
// Create a new decryption promise for this content
|
||||||
const decryptPromise = (async () => {
|
const decryptPromise = (async () => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
|
|
||||||
const response = await axios.post('/api/decrypt', { encryptedContent });
|
const response = await axios.post('/api/decrypt',
|
||||||
|
{ encryptedContent },
|
||||||
|
{ signal: abortController.signal }
|
||||||
|
);
|
||||||
|
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
throw new Error(`Failed to decrypt: ${response.statusText}`);
|
throw new Error(`Failed to decrypt: ${response.statusText}`);
|
||||||
@ -52,6 +60,11 @@ export const useDecryptContent = () => {
|
|||||||
|
|
||||||
return decryptedContent;
|
return decryptedContent;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Handle abort errors specifically
|
||||||
|
if (axios.isCancel(error)) {
|
||||||
|
throw new DOMException('Decryption aborted', 'AbortError');
|
||||||
|
}
|
||||||
|
|
||||||
setError(error.message || 'Decryption failed');
|
setError(error.message || 'Decryption failed');
|
||||||
// Re-throw to signal failure to awaiter
|
// Re-throw to signal failure to awaiter
|
||||||
throw error;
|
throw error;
|
||||||
@ -62,9 +75,19 @@ export const useDecryptContent = () => {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Store the promise in our map
|
// Store the promise and abort controller in our map
|
||||||
|
const abortablePromise = {
|
||||||
|
promise: decryptPromise,
|
||||||
|
abort: () => abortController.abort()
|
||||||
|
};
|
||||||
|
|
||||||
inProgressMap.current.set(cacheKey, decryptPromise);
|
inProgressMap.current.set(cacheKey, decryptPromise);
|
||||||
|
|
||||||
|
// Function to handle timeouts from parent callers
|
||||||
|
decryptPromise.cancel = () => {
|
||||||
|
abortController.abort();
|
||||||
|
};
|
||||||
|
|
||||||
// Return the promise
|
// Return the promise
|
||||||
try {
|
try {
|
||||||
return await decryptPromise;
|
return await decryptPromise;
|
||||||
|
@ -196,19 +196,32 @@ const useDecryption = (session, paidCourse, course, lessons, setLessons, router)
|
|||||||
processingRef.current = true;
|
processingRef.current = true;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
|
// Start the decryption process
|
||||||
|
const decryptionPromise = decryptContent(currentLesson.content);
|
||||||
|
|
||||||
// Add safety timeout to prevent infinite processing
|
// Add safety timeout to prevent infinite processing
|
||||||
const timeoutPromise = new Promise((_, reject) =>
|
let timeoutId;
|
||||||
setTimeout(() => reject(new Error('Decryption timeout')), 10000)
|
const timeoutPromise = new Promise((_, reject) => {
|
||||||
);
|
timeoutId = setTimeout(() => {
|
||||||
|
// Cancel the in-flight request when timeout occurs
|
||||||
|
if (decryptionPromise.cancel) {
|
||||||
|
decryptionPromise.cancel();
|
||||||
|
}
|
||||||
|
reject(new Error('Decryption timeout'));
|
||||||
|
}, 10000);
|
||||||
|
});
|
||||||
|
|
||||||
// Use a separate try-catch for the race
|
// Use a separate try-catch for the race
|
||||||
let decryptedContent;
|
let decryptedContent;
|
||||||
try {
|
try {
|
||||||
// Race between decryption and timeout
|
// Race between decryption and timeout
|
||||||
decryptedContent = await Promise.race([
|
decryptedContent = await Promise.race([
|
||||||
decryptContent(currentLesson.content),
|
decryptionPromise,
|
||||||
timeoutPromise
|
timeoutPromise
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Clear the timeout if decryption wins
|
||||||
|
clearTimeout(timeoutId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// If timeout or network error, schedule a retry
|
// If timeout or network error, schedule a retry
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user