Spaces:
Runtime error
Runtime error
| type EnvSource = Record<string, string | undefined>; | |
| type TimeoutLogger = (message: string) => void; | |
| type ReadTimeoutOptions = { | |
| allowZero?: boolean; | |
| logger?: TimeoutLogger; | |
| }; | |
| export const DEFAULT_FETCH_TIMEOUT_MS = 600_000; | |
| export const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 600_000; | |
| export const MAX_TIMER_TIMEOUT_MS = 2_147_483_647; | |
| export const DEFAULT_SSE_HEARTBEAT_INTERVAL_MS = 15_000; | |
| export const DEFAULT_STREAM_READINESS_TIMEOUT_MS = 80_000; | |
| export const DEFAULT_FETCH_CONNECT_TIMEOUT_MS = 30_000; | |
| export const DEFAULT_FETCH_KEEPALIVE_TIMEOUT_MS = 4_000; | |
| export const DEFAULT_API_BRIDGE_PROXY_TIMEOUT_MS = 600_000; | |
| export const DEFAULT_API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS = 300_000; | |
| export const DEFAULT_API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS = 60_000; | |
| export const DEFAULT_API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS = 5_000; | |
| export const DEFAULT_API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS = 0; | |
| function hasEnvValue(env: EnvSource, name: string): boolean { | |
| const raw = env[name]; | |
| return raw != null && raw.trim() !== ""; | |
| } | |
| export type UpstreamTimeoutConfig = { | |
| fetchTimeoutMs: number; | |
| streamIdleTimeoutMs: number; | |
| sseHeartbeatIntervalMs: number; | |
| streamReadinessTimeoutMs: number; | |
| fetchHeadersTimeoutMs: number; | |
| fetchBodyTimeoutMs: number; | |
| fetchConnectTimeoutMs: number; | |
| fetchKeepAliveTimeoutMs: number; | |
| }; | |
| export type TlsClientTimeoutConfig = { | |
| timeoutMs: number; | |
| }; | |
| export type ApiBridgeTimeoutConfig = { | |
| proxyTimeoutMs: number; | |
| serverRequestTimeoutMs: number; | |
| serverHeadersTimeoutMs: number; | |
| serverKeepAliveTimeoutMs: number; | |
| serverSocketTimeoutMs: number; | |
| }; | |
| function readTimeoutMs( | |
| env: EnvSource, | |
| name: string, | |
| defaultValue: number, | |
| options: ReadTimeoutOptions = {} | |
| ): number { | |
| const raw = env[name]; | |
| if (raw == null || raw.trim() === "") return defaultValue; | |
| const parsed = Number(raw); | |
| const isValid = Number.isFinite(parsed) && (options.allowZero ? parsed >= 0 : parsed > 0); | |
| if (!isValid) { | |
| options.logger?.(`Invalid ${name}="${raw}". Using default ${defaultValue}ms.`); | |
| return defaultValue; | |
| } | |
| return Math.floor(parsed); | |
| } | |
| export function getUpstreamTimeoutConfig( | |
| env: EnvSource = process.env, | |
| logger?: TimeoutLogger | |
| ): UpstreamTimeoutConfig { | |
| const sharedRequestTimeoutMs = hasEnvValue(env, "REQUEST_TIMEOUT_MS") | |
| ? readTimeoutMs(env, "REQUEST_TIMEOUT_MS", DEFAULT_FETCH_TIMEOUT_MS, { | |
| allowZero: true, | |
| logger, | |
| }) | |
| : undefined; | |
| const fetchTimeoutMs = readTimeoutMs( | |
| env, | |
| "FETCH_TIMEOUT_MS", | |
| sharedRequestTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ); | |
| const streamIdleTimeoutMs = readTimeoutMs( | |
| env, | |
| "STREAM_IDLE_TIMEOUT_MS", | |
| sharedRequestTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ); | |
| const streamReadinessTimeoutMs = readTimeoutMs( | |
| env, | |
| "STREAM_READINESS_TIMEOUT_MS", | |
| sharedRequestTimeoutMs ?? DEFAULT_STREAM_READINESS_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ); | |
| const sseHeartbeatIntervalMs = readTimeoutMs( | |
| env, | |
| "SSE_HEARTBEAT_INTERVAL_MS", | |
| DEFAULT_SSE_HEARTBEAT_INTERVAL_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ); | |
| return { | |
| fetchTimeoutMs, | |
| streamIdleTimeoutMs, | |
| streamReadinessTimeoutMs, | |
| sseHeartbeatIntervalMs, | |
| fetchHeadersTimeoutMs: readTimeoutMs(env, "FETCH_HEADERS_TIMEOUT_MS", fetchTimeoutMs, { | |
| allowZero: true, | |
| logger, | |
| }), | |
| fetchBodyTimeoutMs: readTimeoutMs(env, "FETCH_BODY_TIMEOUT_MS", fetchTimeoutMs, { | |
| allowZero: true, | |
| logger, | |
| }), | |
| fetchConnectTimeoutMs: readTimeoutMs( | |
| env, | |
| "FETCH_CONNECT_TIMEOUT_MS", | |
| DEFAULT_FETCH_CONNECT_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ), | |
| fetchKeepAliveTimeoutMs: readTimeoutMs( | |
| env, | |
| "FETCH_KEEPALIVE_TIMEOUT_MS", | |
| DEFAULT_FETCH_KEEPALIVE_TIMEOUT_MS, | |
| { | |
| logger, | |
| } | |
| ), | |
| }; | |
| } | |
| export function getStainlessTimeoutSeconds( | |
| env: EnvSource = process.env, | |
| logger?: TimeoutLogger | |
| ): number { | |
| const { fetchTimeoutMs } = getUpstreamTimeoutConfig(env, logger); | |
| return Math.max(1, Math.ceil(fetchTimeoutMs / 1_000)); | |
| } | |
| export function getTlsClientTimeoutConfig( | |
| env: EnvSource = process.env, | |
| logger?: TimeoutLogger | |
| ): TlsClientTimeoutConfig { | |
| const upstream = getUpstreamTimeoutConfig(env, logger); | |
| return { | |
| timeoutMs: readTimeoutMs(env, "TLS_CLIENT_TIMEOUT_MS", upstream.fetchTimeoutMs, { | |
| allowZero: true, | |
| logger, | |
| }), | |
| }; | |
| } | |
| export function getApiBridgeTimeoutConfig( | |
| env: EnvSource = process.env, | |
| logger?: TimeoutLogger | |
| ): ApiBridgeTimeoutConfig { | |
| const sharedRequestTimeoutMs = hasEnvValue(env, "REQUEST_TIMEOUT_MS") | |
| ? readTimeoutMs(env, "REQUEST_TIMEOUT_MS", DEFAULT_FETCH_TIMEOUT_MS, { | |
| allowZero: true, | |
| logger, | |
| }) | |
| : undefined; | |
| const proxyTimeoutMs = readTimeoutMs( | |
| env, | |
| "API_BRIDGE_PROXY_TIMEOUT_MS", | |
| sharedRequestTimeoutMs ?? DEFAULT_API_BRIDGE_PROXY_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ); | |
| const derivedRequestTimeoutMs = | |
| proxyTimeoutMs > 0 | |
| ? Math.max(proxyTimeoutMs, DEFAULT_API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS) | |
| : DEFAULT_API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS; | |
| const serverRequestDefaultMs = | |
| sharedRequestTimeoutMs !== undefined | |
| ? sharedRequestTimeoutMs > 0 | |
| ? Math.max(sharedRequestTimeoutMs, derivedRequestTimeoutMs) | |
| : 0 | |
| : derivedRequestTimeoutMs; | |
| const serverKeepAliveTimeoutMs = readTimeoutMs( | |
| env, | |
| "API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS", | |
| DEFAULT_API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ); | |
| const serverHeadersTimeoutMs = readTimeoutMs( | |
| env, | |
| "API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS", | |
| DEFAULT_API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ); | |
| return { | |
| proxyTimeoutMs, | |
| serverRequestTimeoutMs: readTimeoutMs( | |
| env, | |
| "API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS", | |
| serverRequestDefaultMs, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ), | |
| serverHeadersTimeoutMs: | |
| serverHeadersTimeoutMs > 0 && serverKeepAliveTimeoutMs > 0 | |
| ? Math.max(serverHeadersTimeoutMs, serverKeepAliveTimeoutMs + 1_000) | |
| : serverHeadersTimeoutMs, | |
| serverKeepAliveTimeoutMs, | |
| serverSocketTimeoutMs: readTimeoutMs( | |
| env, | |
| "API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS", | |
| DEFAULT_API_BRIDGE_SERVER_SOCKET_TIMEOUT_MS, | |
| { | |
| allowZero: true, | |
| logger, | |
| } | |
| ), | |
| }; | |
| } | |