Spaces:
Sleeping
Sleeping
| /** | |
| * JST (Asia/Tokyo) タイムゾーンでISO 8601形式のタイムスタンプを生成 | |
| */ | |
| function getJSTTimestamp(): string { | |
| const now = new Date(); | |
| // JSTタイムゾーンで時刻を取得してISO形式に変換 | |
| return new Date(now.toLocaleString('en-US', { timeZone: 'Asia/Tokyo' })).toISOString(); | |
| } | |
| export enum SegmentationErrorCode { | |
| INITIALIZATION_FAILED = 'INITIALIZATION_FAILED', | |
| MODEL_NOT_INITIALIZED = 'MODEL_NOT_INITIALIZED', | |
| INVALID_IMAGE_DATA = 'INVALID_IMAGE_DATA', | |
| SEGMENTATION_FAILED = 'SEGMENTATION_FAILED', | |
| MASK_GENERATION_FAILED = 'MASK_GENERATION_FAILED', | |
| INVALID_MASK_DATA = 'INVALID_MASK_DATA', | |
| MEMORY_LIMIT_EXCEEDED = 'MEMORY_LIMIT_EXCEEDED', | |
| PROCESSING_TIMEOUT = 'PROCESSING_TIMEOUT', | |
| BACKGROUND_INPAINTING_FAILED = 'BACKGROUND_INPAINTING_FAILED', | |
| OBJECT_REGENERATION_FAILED = 'OBJECT_REGENERATION_FAILED', | |
| COPY_REPLACEMENT_FAILED = 'COPY_REPLACEMENT_FAILED', | |
| HEADER_COMPOSITION_FAILED = 'HEADER_COMPOSITION_FAILED', | |
| PROMPT_GENERATION_FAILED = 'PROMPT_GENERATION_FAILED', | |
| TEXT_GENERATION_FAILED = 'TEXT_GENERATION_FAILED', | |
| } | |
| export class SegmentationError extends Error { | |
| constructor( | |
| message: string, | |
| public code: SegmentationErrorCode, | |
| public details?: any, | |
| ) { | |
| super(message); | |
| this.name = 'SegmentationError'; | |
| } | |
| } | |
| export class ValidationError extends Error { | |
| constructor( | |
| message: string, | |
| public field: string, | |
| public value?: any, | |
| ) { | |
| super(message); | |
| this.name = 'ValidationError'; | |
| } | |
| } | |
| export interface ErrorResponse { | |
| error: { | |
| code: string; | |
| message: string; | |
| details?: any; | |
| }; | |
| timestamp: string; | |
| requestId?: string; | |
| } | |
| export function createErrorResponse(error: Error, requestId?: string): ErrorResponse { | |
| if (error instanceof SegmentationError) { | |
| return { | |
| error: { | |
| code: error.code, | |
| message: error.message, | |
| details: error.details, | |
| }, | |
| timestamp: getJSTTimestamp(), | |
| requestId, | |
| }; | |
| } | |
| if (error instanceof ValidationError) { | |
| return { | |
| error: { | |
| code: 'VALIDATION_ERROR', | |
| message: error.message, | |
| details: { | |
| field: error.field, | |
| value: error.value, | |
| }, | |
| }, | |
| timestamp: getJSTTimestamp(), | |
| requestId, | |
| }; | |
| } | |
| // 一般的なエラー | |
| return { | |
| error: { | |
| code: 'INTERNAL_ERROR', | |
| message: 'An unexpected error occurred', | |
| details: process.env.NODE_ENV === 'development' ? error.message : undefined, | |
| }, | |
| timestamp: getJSTTimestamp(), | |
| requestId, | |
| }; | |
| } | |
| // メモリ使用量をチェック | |
| export function checkMemoryUsage(threshold: number = 0.9): void { | |
| const usage = process.memoryUsage(); | |
| const heapUsed = usage.heapUsed; | |
| const heapTotal = usage.heapTotal; | |
| const ratio = heapUsed / heapTotal; | |
| if (ratio > threshold) { | |
| throw new SegmentationError(`Memory usage too high: ${Math.round(ratio * 100)}%`, SegmentationErrorCode.MEMORY_LIMIT_EXCEEDED, { | |
| heapUsed, | |
| heapTotal, | |
| ratio, | |
| }); | |
| } | |
| } | |
| // タイムアウト付き処理実行 | |
| export async function withTimeout<T>(promise: Promise<T>, timeoutMs: number, operation: string): Promise<T> { | |
| const timeoutPromise = new Promise<never>((_, reject) => { | |
| setTimeout(() => { | |
| reject( | |
| new SegmentationError(`Operation '${operation}' timed out after ${timeoutMs}ms`, SegmentationErrorCode.PROCESSING_TIMEOUT, { | |
| operation, | |
| timeoutMs, | |
| }), | |
| ); | |
| }, timeoutMs); | |
| }); | |
| return Promise.race([promise, timeoutPromise]); | |
| } | |
| // リトライ機能付き処理実行 | |
| export async function withRetry<T>( | |
| fn: () => Promise<T>, | |
| options: { | |
| maxRetries?: number; | |
| delay?: number; | |
| backoff?: number; | |
| onRetry?: (error: Error, attempt: number) => void; | |
| } = {}, | |
| ): Promise<T> { | |
| const { maxRetries = 3, delay = 1000, backoff = 2, onRetry } = options; | |
| let lastError: Error; | |
| for (let attempt = 1; attempt <= maxRetries; attempt++) { | |
| try { | |
| return await fn(); | |
| } catch (error) { | |
| lastError = error as Error; | |
| if (attempt === maxRetries) { | |
| throw lastError; | |
| } | |
| if (onRetry) { | |
| onRetry(lastError, attempt); | |
| } | |
| const waitTime = delay * Math.pow(backoff, attempt - 1); | |
| await new Promise((resolve) => setTimeout(resolve, waitTime)); | |
| } | |
| } | |
| throw lastError!; | |
| } | |