import type { ServerResponse } from "node:http"; /** * Calculate backoff time with exponential jitter * @param attempt - Current attempt number (1-based) * @param baseDelayMs - Base delay in milliseconds (default: 100ms) * @param maxDelayMs - Maximum delay in milliseconds (default: 5000ms) * @returns Calculated delay in milliseconds */ export function calculateBackoffTime( attempt: number, baseDelayMs = 100, maxDelayMs = 5000, ): number { const delay = Math.min(baseDelayMs * 2 ** (attempt - 1), maxDelayMs); return delay * (0.7 + Math.random() * 0.3); } /** * Check if a response is still writable * @param response - The HTTP response object * @returns boolean indicating if the response can still be written to */ export function isResponseWritable(response: ServerResponse): boolean { return !response.writableEnded && !response.destroyed; } /** * Safely write to a response stream * @param response - The HTTP response object * @param data - Data to write * @returns boolean indicating if the write was successful */ export function safeWriteResponse( response: ServerResponse, data: string, ): boolean { if (!isResponseWritable(response)) return false; try { return response.write(data); } catch (error) { console.error("Failed to write to response:", error); return false; } } /** * Safely end a response * @param response - The HTTP response object * @param data - Optional data to write before ending */ export function safeEndResponse(response: ServerResponse, data?: string): void { if (response.writableEnded || response.destroyed) return; try { if (data) { response.end(data); } else { response.end(); } } catch (error) { console.error("Failed to end response:", error); response.destroy(); } }