mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 02:11:14 -05:00
Refactor code structure and remove redundant changes
This commit is contained in:
125
src-old/hooks/useRetryProgress.ts
Normal file
125
src-old/hooks/useRetryProgress.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
|
||||
interface RetryOptions {
|
||||
maxAttempts?: number;
|
||||
delayMs?: number;
|
||||
exponentialBackoff?: boolean;
|
||||
onProgress?: (attempt: number, maxAttempts: number) => void;
|
||||
}
|
||||
|
||||
export function useRetryProgress() {
|
||||
const [isRetrying, setIsRetrying] = useState(false);
|
||||
const [currentAttempt, setCurrentAttempt] = useState(0);
|
||||
const [abortController, setAbortController] = useState<AbortController | null>(null);
|
||||
|
||||
const retryWithProgress = useCallback(
|
||||
async <T,>(
|
||||
operation: () => Promise<T>,
|
||||
options: RetryOptions = {}
|
||||
): Promise<T> => {
|
||||
const {
|
||||
maxAttempts = 3,
|
||||
delayMs = 1000,
|
||||
exponentialBackoff = true,
|
||||
onProgress,
|
||||
} = options;
|
||||
|
||||
setIsRetrying(true);
|
||||
const controller = new AbortController();
|
||||
setAbortController(controller);
|
||||
|
||||
let lastError: Error | null = null;
|
||||
let toastId: string | undefined;
|
||||
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
if (controller.signal.aborted) {
|
||||
throw new Error('Operation cancelled');
|
||||
}
|
||||
|
||||
setCurrentAttempt(attempt);
|
||||
onProgress?.(attempt, maxAttempts);
|
||||
|
||||
// Show progress toast
|
||||
if (attempt > 1) {
|
||||
const delay = exponentialBackoff ? delayMs * Math.pow(2, attempt - 2) : delayMs;
|
||||
const countdown = Math.ceil(delay / 1000);
|
||||
|
||||
toast({
|
||||
title: `Retrying (${attempt}/${maxAttempts})`,
|
||||
description: `Waiting ${countdown}s before retry...`,
|
||||
duration: delay,
|
||||
});
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await operation();
|
||||
|
||||
setIsRetrying(false);
|
||||
setCurrentAttempt(0);
|
||||
setAbortController(null);
|
||||
|
||||
// Show success toast
|
||||
toast({
|
||||
title: "Success",
|
||||
description: attempt > 1
|
||||
? `Operation succeeded on attempt ${attempt}`
|
||||
: 'Operation completed successfully',
|
||||
duration: 3000,
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
lastError = error instanceof Error ? error : new Error(String(error));
|
||||
|
||||
if (attempt < maxAttempts) {
|
||||
toast({
|
||||
title: `Attempt ${attempt} Failed`,
|
||||
description: `${lastError.message}. Retrying...`,
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All attempts failed
|
||||
setIsRetrying(false);
|
||||
setCurrentAttempt(0);
|
||||
setAbortController(null);
|
||||
|
||||
toast({
|
||||
variant: 'destructive',
|
||||
title: "All Retries Failed",
|
||||
description: `Failed after ${maxAttempts} attempts: ${lastError?.message}`,
|
||||
duration: 5000,
|
||||
});
|
||||
|
||||
throw lastError;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const cancel = useCallback(() => {
|
||||
if (abortController) {
|
||||
abortController.abort();
|
||||
setAbortController(null);
|
||||
setIsRetrying(false);
|
||||
setCurrentAttempt(0);
|
||||
|
||||
toast({
|
||||
title: 'Cancelled',
|
||||
description: 'Retry operation cancelled',
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
}, [abortController]);
|
||||
|
||||
return {
|
||||
retryWithProgress,
|
||||
isRetrying,
|
||||
currentAttempt,
|
||||
cancel,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user