Spaces:
Sleeping
Sleeping
File size: 1,728 Bytes
68f7925 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
import { AppError, URLInputErrorType } from './errors';
// リトライ可能なエラーかどうか判定
export function isRetryableError(error: unknown): boolean {
if (error instanceof AppError) {
return [
URLInputErrorType.NETWORK_ERROR,
URLInputErrorType.TIMEOUT,
].includes(error.code as URLInputErrorType);
}
return false;
}
// エラーの詳細情報を取得
export function getErrorDetails(error: unknown): {
message: string;
code?: string;
statusCode?: number;
isRetryable: boolean;
} {
if (error instanceof AppError) {
return {
message: error.message,
code: error.code,
statusCode: error.statusCode,
isRetryable: isRetryableError(error),
};
}
if (error instanceof Error) {
return {
message: error.message,
isRetryable: false,
};
}
return {
message: '予期しないエラーが発生しました',
isRetryable: false,
};
}
// 指数バックオフでリトライ
export async function retryWithBackoff<T>(
fn: () => Promise<T>,
maxRetries: number = 3,
initialDelay: number = 1000,
): Promise<T> {
let lastError: unknown;
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
lastError = error;
// リトライ不可能なエラーの場合は即座に失敗
if (!isRetryableError(error)) {
throw error;
}
// 最後の試行の場合はエラーを投げる
if (i === maxRetries - 1) {
throw error;
}
// 指数バックオフで待機
const delay = initialDelay * Math.pow(2, i);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
throw lastError;
}
|