@parsrun/service 0.1.29 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +30 -3
- package/dist/client.js +1 -0
- package/dist/client.js.map +1 -1
- package/dist/define.d.ts +29 -6
- package/dist/define.js.map +1 -1
- package/dist/events/index.d.ts +95 -15
- package/dist/events/index.js.map +1 -1
- package/dist/{handler-CmiDUWZv.d.ts → handler-eCIZLODd.d.ts} +45 -3
- package/dist/{index-CVOAoJjZ.d.ts → index-reEpIe1R.d.ts} +82 -11
- package/dist/index.d.ts +53 -9
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/resilience/index.d.ts +76 -9
- package/dist/resilience/index.js +1 -0
- package/dist/resilience/index.js.map +1 -1
- package/dist/rpc/index.d.ts +3 -3
- package/dist/rpc/index.js +1 -0
- package/dist/rpc/index.js.map +1 -1
- package/dist/serialization/index.d.ts +27 -2
- package/dist/serialization/index.js.map +1 -1
- package/dist/{server-DFE8n2Sx.d.ts → server-BB9AbnkP.d.ts} +50 -6
- package/dist/tracing/index.d.ts +94 -15
- package/dist/tracing/index.js.map +1 -1
- package/dist/transports/cloudflare/index.d.ts +72 -10
- package/dist/transports/cloudflare/index.js.map +1 -1
- package/dist/{types-n4LLSPQU.d.ts → types-DHZaZwAt.d.ts} +51 -0
- package/package.json +3 -3
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* @parsrun/service - Circuit Breaker
|
|
3
3
|
* Prevents cascading failures by failing fast when a service is unhealthy
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Options for configuring a circuit breaker.
|
|
7
|
+
*/
|
|
5
8
|
interface CircuitBreakerOptions {
|
|
6
9
|
/** Number of failures before opening circuit */
|
|
7
10
|
failureThreshold: number;
|
|
@@ -12,6 +15,12 @@ interface CircuitBreakerOptions {
|
|
|
12
15
|
/** Optional callback on state change */
|
|
13
16
|
onStateChange?: (from: CircuitState, to: CircuitState) => void;
|
|
14
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Circuit breaker state.
|
|
20
|
+
* - "closed": Normal operation, requests pass through
|
|
21
|
+
* - "open": Failing fast, requests are rejected immediately
|
|
22
|
+
* - "half-open": Testing if service recovered, limited requests allowed
|
|
23
|
+
*/
|
|
15
24
|
type CircuitState = "closed" | "open" | "half-open";
|
|
16
25
|
/**
|
|
17
26
|
* Circuit Breaker implementation
|
|
@@ -67,6 +76,9 @@ declare class CircuitBreaker {
|
|
|
67
76
|
* @parsrun/service - Bulkhead
|
|
68
77
|
* Limits concurrent requests to prevent resource exhaustion
|
|
69
78
|
*/
|
|
79
|
+
/**
|
|
80
|
+
* Options for configuring a bulkhead.
|
|
81
|
+
*/
|
|
70
82
|
interface BulkheadOptions {
|
|
71
83
|
/** Maximum concurrent requests */
|
|
72
84
|
maxConcurrent: number;
|
|
@@ -133,6 +145,9 @@ declare class Bulkhead {
|
|
|
133
145
|
* @parsrun/service - Retry
|
|
134
146
|
* Retry failed operations with backoff
|
|
135
147
|
*/
|
|
148
|
+
/**
|
|
149
|
+
* Options for configuring retry behavior.
|
|
150
|
+
*/
|
|
136
151
|
interface RetryOptions {
|
|
137
152
|
/** Number of retry attempts (not including initial attempt) */
|
|
138
153
|
attempts: number;
|
|
@@ -150,15 +165,42 @@ interface RetryOptions {
|
|
|
150
165
|
onRetry?: (error: unknown, attempt: number, delay: number) => void;
|
|
151
166
|
}
|
|
152
167
|
/**
|
|
153
|
-
* Wrap a function with retry logic
|
|
168
|
+
* Wrap a function with retry logic.
|
|
169
|
+
* Returns a new function that will retry on failure.
|
|
170
|
+
*
|
|
171
|
+
* @param fn - The function to wrap
|
|
172
|
+
* @param options - Retry configuration
|
|
173
|
+
* @returns A wrapped function with retry behavior
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const fetchWithRetry = withRetry(
|
|
178
|
+
* () => fetch('/api/data'),
|
|
179
|
+
* { attempts: 3, backoff: 'exponential', initialDelay: 100, maxDelay: 5000 }
|
|
180
|
+
* );
|
|
181
|
+
* const response = await fetchWithRetry();
|
|
182
|
+
* ```
|
|
154
183
|
*/
|
|
155
184
|
declare function withRetry<T>(fn: () => Promise<T>, options: RetryOptions): () => Promise<T>;
|
|
156
185
|
/**
|
|
157
|
-
* Execute a function with retry
|
|
186
|
+
* Execute a function with retry logic immediately.
|
|
187
|
+
*
|
|
188
|
+
* @param fn - The function to execute
|
|
189
|
+
* @param options - Retry configuration
|
|
190
|
+
* @returns Promise resolving to the function result
|
|
158
191
|
*/
|
|
159
192
|
declare function executeWithRetry<T>(fn: () => Promise<T>, options: RetryOptions): Promise<T>;
|
|
160
193
|
/**
|
|
161
|
-
* Create a retry wrapper with preset options
|
|
194
|
+
* Create a reusable retry wrapper with preset default options.
|
|
195
|
+
*
|
|
196
|
+
* @param defaultOptions - Default retry configuration
|
|
197
|
+
* @returns A function that executes with retry using the defaults
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const retry = createRetryWrapper({ attempts: 3, backoff: 'exponential' });
|
|
202
|
+
* const result = await retry(() => fetchData());
|
|
203
|
+
* ```
|
|
162
204
|
*/
|
|
163
205
|
declare function createRetryWrapper(defaultOptions: Partial<RetryOptions>): <T>(fn: () => Promise<T>, options?: Partial<RetryOptions>) => Promise<T>;
|
|
164
206
|
|
|
@@ -167,30 +209,55 @@ declare function createRetryWrapper(defaultOptions: Partial<RetryOptions>): <T>(
|
|
|
167
209
|
* Timeout wrapper for async operations
|
|
168
210
|
*/
|
|
169
211
|
/**
|
|
170
|
-
*
|
|
212
|
+
* Error thrown when an operation exceeds its timeout.
|
|
171
213
|
*/
|
|
172
214
|
declare class TimeoutExceededError extends Error {
|
|
215
|
+
/** The timeout value in milliseconds that was exceeded */
|
|
173
216
|
readonly timeout: number;
|
|
174
217
|
constructor(timeout: number);
|
|
175
218
|
}
|
|
176
219
|
/**
|
|
177
|
-
* Wrap a function with timeout
|
|
220
|
+
* Wrap a function with a timeout.
|
|
221
|
+
* Returns a new function that will reject if the timeout is exceeded.
|
|
222
|
+
*
|
|
223
|
+
* @param fn - The function to wrap
|
|
224
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
225
|
+
* @param onTimeout - Optional callback or throw function when timeout occurs
|
|
226
|
+
* @returns A wrapped function with timeout behavior
|
|
178
227
|
*/
|
|
179
228
|
declare function withTimeout<T>(fn: () => Promise<T>, timeoutMs: number, onTimeout?: () => void | never): () => Promise<T>;
|
|
180
229
|
/**
|
|
181
|
-
* Execute a function with timeout
|
|
230
|
+
* Execute a function with timeout immediately.
|
|
231
|
+
*
|
|
232
|
+
* @param fn - The function to execute
|
|
233
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
234
|
+
* @param onTimeout - Optional callback or throw function when timeout occurs
|
|
235
|
+
* @returns Promise resolving to the function result or rejecting on timeout
|
|
182
236
|
*/
|
|
183
237
|
declare function executeWithTimeout<T>(fn: () => Promise<T>, timeoutMs: number, onTimeout?: () => void | never): Promise<T>;
|
|
184
238
|
/**
|
|
185
|
-
* Create a timeout wrapper with preset duration
|
|
239
|
+
* Create a reusable timeout wrapper with preset duration.
|
|
240
|
+
*
|
|
241
|
+
* @param defaultTimeoutMs - Default timeout in milliseconds
|
|
242
|
+
* @returns A function that executes with timeout
|
|
186
243
|
*/
|
|
187
244
|
declare function createTimeoutWrapper(defaultTimeoutMs: number): <T>(fn: () => Promise<T>, timeoutMs?: number) => Promise<T>;
|
|
188
245
|
/**
|
|
189
|
-
* Race multiple promises with a timeout
|
|
246
|
+
* Race multiple promises with a timeout.
|
|
247
|
+
* Returns the first promise to resolve, or rejects on timeout.
|
|
248
|
+
*
|
|
249
|
+
* @param promises - Array of promises to race
|
|
250
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
251
|
+
* @returns Promise resolving to the first result
|
|
190
252
|
*/
|
|
191
253
|
declare function raceWithTimeout<T>(promises: Promise<T>[], timeoutMs: number): Promise<T>;
|
|
192
254
|
/**
|
|
193
|
-
* Execute with
|
|
255
|
+
* Execute a function with an absolute deadline.
|
|
256
|
+
* Converts the deadline to a relative timeout.
|
|
257
|
+
*
|
|
258
|
+
* @param fn - The function to execute
|
|
259
|
+
* @param deadline - Absolute deadline as a Date
|
|
260
|
+
* @returns Promise resolving to the function result
|
|
194
261
|
*/
|
|
195
262
|
declare function executeWithDeadline<T>(fn: () => Promise<T>, deadline: Date): Promise<T>;
|
|
196
263
|
|
package/dist/resilience/index.js
CHANGED
|
@@ -307,6 +307,7 @@ function createRetryWrapper(defaultOptions) {
|
|
|
307
307
|
|
|
308
308
|
// src/resilience/timeout.ts
|
|
309
309
|
var TimeoutExceededError = class extends Error {
|
|
310
|
+
/** The timeout value in milliseconds that was exceeded */
|
|
310
311
|
timeout;
|
|
311
312
|
constructor(timeout) {
|
|
312
313
|
super(`Operation timed out after ${timeout}ms`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/rpc/errors.ts","../../src/resilience/circuit-breaker.ts","../../src/resilience/bulkhead.ts","../../src/resilience/retry.ts","../../src/resilience/timeout.ts"],"sourcesContent":["/**\n * @parsrun/service - RPC Errors\n */\n\nimport { ParsError } from \"@parsrun/core\";\n\n/**\n * Base RPC error\n */\nexport class RpcError extends ParsError {\n public readonly retryable: boolean;\n public readonly retryAfter?: number;\n\n constructor(\n message: string,\n code: string,\n statusCode: number = 500,\n options?: {\n retryable?: boolean;\n retryAfter?: number;\n details?: Record<string, unknown>;\n }\n ) {\n super(message, code, statusCode, options?.details);\n this.name = \"RpcError\";\n this.retryable = options?.retryable ?? false;\n if (options?.retryAfter !== undefined) {\n this.retryAfter = options.retryAfter;\n }\n }\n}\n\n/**\n * Service not found error\n */\nexport class ServiceNotFoundError extends RpcError {\n constructor(serviceName: string) {\n super(`Service not found: ${serviceName}`, \"SERVICE_NOT_FOUND\", 404, {\n retryable: false,\n details: { service: serviceName },\n });\n this.name = \"ServiceNotFoundError\";\n }\n}\n\n/**\n * Method not found error\n */\nexport class MethodNotFoundError extends RpcError {\n constructor(serviceName: string, methodName: string) {\n super(\n `Method not found: ${serviceName}.${methodName}`,\n \"METHOD_NOT_FOUND\",\n 404,\n {\n retryable: false,\n details: { service: serviceName, method: methodName },\n }\n );\n this.name = \"MethodNotFoundError\";\n }\n}\n\n/**\n * Version mismatch error\n */\nexport class VersionMismatchError extends RpcError {\n constructor(serviceName: string, requested: string, available: string) {\n super(\n `Version mismatch for ${serviceName}: requested ${requested}, available ${available}`,\n \"VERSION_MISMATCH\",\n 400,\n {\n retryable: false,\n details: { service: serviceName, requested, available },\n }\n );\n this.name = \"VersionMismatchError\";\n }\n}\n\n/**\n * Timeout error\n */\nexport class TimeoutError extends RpcError {\n constructor(serviceName: string, methodName: string, timeoutMs: number) {\n super(\n `Request to ${serviceName}.${methodName} timed out after ${timeoutMs}ms`,\n \"TIMEOUT\",\n 504,\n {\n retryable: true,\n details: { service: serviceName, method: methodName, timeout: timeoutMs },\n }\n );\n this.name = \"TimeoutError\";\n }\n}\n\n/**\n * Circuit breaker open error\n */\nexport class CircuitOpenError extends RpcError {\n constructor(serviceName: string, resetAfterMs: number) {\n super(\n `Circuit breaker open for ${serviceName}`,\n \"CIRCUIT_OPEN\",\n 503,\n {\n retryable: true,\n retryAfter: Math.ceil(resetAfterMs / 1000),\n details: { service: serviceName, resetAfterMs },\n }\n );\n this.name = \"CircuitOpenError\";\n }\n}\n\n/**\n * Bulkhead rejected error\n */\nexport class BulkheadRejectedError extends RpcError {\n constructor(serviceName: string) {\n super(\n `Request rejected by bulkhead for ${serviceName}: too many concurrent requests`,\n \"BULKHEAD_REJECTED\",\n 503,\n {\n retryable: true,\n retryAfter: 1,\n details: { service: serviceName },\n }\n );\n this.name = \"BulkheadRejectedError\";\n }\n}\n\n/**\n * Transport error\n */\nexport class TransportError extends RpcError {\n constructor(message: string, cause?: Error) {\n const options: { retryable: boolean; details?: Record<string, unknown> } = {\n retryable: true,\n };\n if (cause) {\n options.details = { cause: cause.message };\n }\n super(message, \"TRANSPORT_ERROR\", 502, options);\n this.name = \"TransportError\";\n }\n}\n\n/**\n * Serialization error\n */\nexport class SerializationError extends RpcError {\n constructor(message: string, cause?: Error) {\n const options: { retryable: boolean; details?: Record<string, unknown> } = {\n retryable: false,\n };\n if (cause) {\n options.details = { cause: cause.message };\n }\n super(message, \"SERIALIZATION_ERROR\", 400, options);\n this.name = \"SerializationError\";\n }\n}\n\n/**\n * Convert unknown error to RpcError\n */\nexport function toRpcError(error: unknown): RpcError {\n if (error instanceof RpcError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new RpcError(error.message, \"INTERNAL_ERROR\", 500, {\n retryable: false,\n details: { originalError: error.name },\n });\n }\n\n return new RpcError(String(error), \"UNKNOWN_ERROR\", 500, {\n retryable: false,\n });\n}\n","/**\n * @parsrun/service - Circuit Breaker\n * Prevents cascading failures by failing fast when a service is unhealthy\n */\n\nimport { CircuitOpenError } from \"../rpc/errors.js\";\n\n// ============================================================================\n// CIRCUIT BREAKER\n// ============================================================================\n\nexport interface CircuitBreakerOptions {\n /** Number of failures before opening circuit */\n failureThreshold: number;\n /** Time to wait before half-open state (ms) */\n resetTimeout: number;\n /** Number of successes in half-open to close circuit */\n successThreshold: number;\n /** Optional callback on state change */\n onStateChange?: (from: CircuitState, to: CircuitState) => void;\n}\n\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\n/**\n * Circuit Breaker implementation\n *\n * States:\n * - CLOSED: Normal operation, requests pass through\n * - OPEN: Failing fast, requests are rejected immediately\n * - HALF-OPEN: Testing if service recovered, limited requests allowed\n */\nexport class CircuitBreaker {\n private _state: CircuitState = \"closed\";\n private failures = 0;\n private successes = 0;\n private lastFailureTime = 0;\n private readonly options: CircuitBreakerOptions;\n\n constructor(options: CircuitBreakerOptions) {\n this.options = options;\n }\n\n /**\n * Get current state\n */\n get state(): CircuitState {\n // Check if we should transition from open to half-open\n if (this._state === \"open\") {\n const timeSinceFailure = Date.now() - this.lastFailureTime;\n if (timeSinceFailure >= this.options.resetTimeout) {\n this.transitionTo(\"half-open\");\n }\n }\n return this._state;\n }\n\n /**\n * Execute a function with circuit breaker protection\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check state (this may transition from open to half-open)\n const currentState = this.state;\n\n if (currentState === \"open\") {\n const resetAfter = this.options.resetTimeout - (Date.now() - this.lastFailureTime);\n throw new CircuitOpenError(\"service\", Math.max(0, resetAfter));\n }\n\n try {\n const result = await fn();\n this.onSuccess();\n return result;\n } catch (error) {\n this.onFailure();\n throw error;\n }\n }\n\n /**\n * Record a successful call\n */\n private onSuccess(): void {\n if (this._state === \"half-open\") {\n this.successes++;\n if (this.successes >= this.options.successThreshold) {\n this.transitionTo(\"closed\");\n }\n } else if (this._state === \"closed\") {\n // Reset failure count on success\n this.failures = 0;\n }\n }\n\n /**\n * Record a failed call\n */\n private onFailure(): void {\n this.lastFailureTime = Date.now();\n\n if (this._state === \"half-open\") {\n // Any failure in half-open goes back to open\n this.transitionTo(\"open\");\n } else if (this._state === \"closed\") {\n this.failures++;\n if (this.failures >= this.options.failureThreshold) {\n this.transitionTo(\"open\");\n }\n }\n }\n\n /**\n * Transition to a new state\n */\n private transitionTo(newState: CircuitState): void {\n const oldState = this._state;\n this._state = newState;\n\n // Reset counters on state change\n if (newState === \"closed\") {\n this.failures = 0;\n this.successes = 0;\n } else if (newState === \"half-open\") {\n this.successes = 0;\n }\n\n this.options.onStateChange?.(oldState, newState);\n }\n\n /**\n * Manually reset the circuit breaker\n */\n reset(): void {\n this.transitionTo(\"closed\");\n }\n\n /**\n * Get circuit breaker statistics\n */\n getStats(): {\n state: CircuitState;\n failures: number;\n successes: number;\n lastFailureTime: number;\n } {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n lastFailureTime: this.lastFailureTime,\n };\n }\n}\n","/**\n * @parsrun/service - Bulkhead\n * Limits concurrent requests to prevent resource exhaustion\n */\n\nimport { BulkheadRejectedError } from \"../rpc/errors.js\";\n\n// ============================================================================\n// BULKHEAD\n// ============================================================================\n\nexport interface BulkheadOptions {\n /** Maximum concurrent requests */\n maxConcurrent: number;\n /** Maximum queue size (0 = no queue) */\n maxQueue: number;\n /** Optional callback when request is rejected */\n onRejected?: () => void;\n}\n\ninterface QueuedRequest<T> {\n fn: () => Promise<T>;\n resolve: (value: T) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Bulkhead implementation\n *\n * Limits the number of concurrent requests to protect resources.\n * Excess requests can be queued up to maxQueue limit.\n */\nexport class Bulkhead {\n private _concurrent = 0;\n private readonly queue: QueuedRequest<unknown>[] = [];\n private readonly options: BulkheadOptions;\n\n constructor(options: BulkheadOptions) {\n this.options = options;\n }\n\n /**\n * Get current concurrent count\n */\n get concurrent(): number {\n return this._concurrent;\n }\n\n /**\n * Get current queue size\n */\n get queued(): number {\n return this.queue.length;\n }\n\n /**\n * Check if bulkhead is full\n */\n get isFull(): boolean {\n return (\n this._concurrent >= this.options.maxConcurrent &&\n this.queue.length >= this.options.maxQueue\n );\n }\n\n /**\n * Execute a function with bulkhead protection\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if we can execute immediately\n if (this._concurrent < this.options.maxConcurrent) {\n return this.doExecute(fn);\n }\n\n // Check if we can queue\n if (this.queue.length < this.options.maxQueue) {\n return this.enqueue(fn);\n }\n\n // Reject\n this.options.onRejected?.();\n throw new BulkheadRejectedError(\"service\");\n }\n\n /**\n * Execute immediately\n */\n private async doExecute<T>(fn: () => Promise<T>): Promise<T> {\n this._concurrent++;\n try {\n return await fn();\n } finally {\n this._concurrent--;\n this.processQueue();\n }\n }\n\n /**\n * Add to queue\n */\n private enqueue<T>(fn: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this.queue.push({\n fn,\n resolve: resolve as (value: unknown) => void,\n reject,\n });\n });\n }\n\n /**\n * Process queued requests\n */\n private processQueue(): void {\n if (this.queue.length === 0) return;\n if (this._concurrent >= this.options.maxConcurrent) return;\n\n const queued = this.queue.shift();\n if (!queued) return;\n\n this.doExecute(queued.fn)\n .then(queued.resolve)\n .catch(queued.reject);\n }\n\n /**\n * Get bulkhead statistics\n */\n getStats(): {\n concurrent: number;\n queued: number;\n maxConcurrent: number;\n maxQueue: number;\n } {\n return {\n concurrent: this._concurrent,\n queued: this.queue.length,\n maxConcurrent: this.options.maxConcurrent,\n maxQueue: this.options.maxQueue,\n };\n }\n\n /**\n * Clear the queue (reject all pending)\n */\n clearQueue(): void {\n const error = new BulkheadRejectedError(\"service\");\n while (this.queue.length > 0) {\n const queued = this.queue.shift();\n queued?.reject(error);\n }\n }\n}\n","/**\n * @parsrun/service - Retry\n * Retry failed operations with backoff\n */\n\n// ============================================================================\n// RETRY\n// ============================================================================\n\nexport interface RetryOptions {\n /** Number of retry attempts (not including initial attempt) */\n attempts: number;\n /** Backoff strategy */\n backoff: \"linear\" | \"exponential\";\n /** Initial delay in ms */\n initialDelay: number;\n /** Maximum delay in ms */\n maxDelay: number;\n /** Jitter factor (0-1) to add randomness */\n jitter?: number;\n /** Should retry predicate */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Callback on retry */\n onRetry?: (error: unknown, attempt: number, delay: number) => void;\n}\n\n/**\n * Default retry predicate - retry on retryable errors\n */\nconst defaultShouldRetry = (error: unknown): boolean => {\n if (error && typeof error === \"object\" && \"retryable\" in error) {\n return (error as { retryable: boolean }).retryable;\n }\n return false;\n};\n\n/**\n * Calculate delay for retry attempt\n */\nfunction calculateDelay(\n attempt: number,\n options: RetryOptions\n): number {\n let delay: number;\n\n if (options.backoff === \"exponential\") {\n // Exponential backoff: initialDelay * 2^attempt\n delay = options.initialDelay * Math.pow(2, attempt);\n } else {\n // Linear backoff: initialDelay * (attempt + 1)\n delay = options.initialDelay * (attempt + 1);\n }\n\n // Apply max delay\n delay = Math.min(delay, options.maxDelay);\n\n // Apply jitter\n if (options.jitter && options.jitter > 0) {\n const jitterRange = delay * options.jitter;\n delay = delay - jitterRange / 2 + Math.random() * jitterRange;\n }\n\n return Math.round(delay);\n}\n\n/**\n * Sleep for a given duration\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Wrap a function with retry logic\n */\nexport function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions\n): () => Promise<T> {\n const shouldRetry = options.shouldRetry ?? defaultShouldRetry;\n\n return async (): Promise<T> => {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= options.attempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Check if we should retry\n if (attempt >= options.attempts || !shouldRetry(error, attempt)) {\n throw error;\n }\n\n // Calculate delay\n const delay = calculateDelay(attempt, options);\n\n // Callback\n options.onRetry?.(error, attempt + 1, delay);\n\n // Wait before retry\n await sleep(delay);\n }\n }\n\n throw lastError;\n };\n}\n\n/**\n * Execute a function with retry\n */\nexport async function executeWithRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions\n): Promise<T> {\n return withRetry(fn, options)();\n}\n\n/**\n * Create a retry wrapper with preset options\n */\nexport function createRetryWrapper(\n defaultOptions: Partial<RetryOptions>\n): <T>(fn: () => Promise<T>, options?: Partial<RetryOptions>) => Promise<T> {\n const defaults: RetryOptions = {\n attempts: defaultOptions.attempts ?? 3,\n backoff: defaultOptions.backoff ?? \"exponential\",\n initialDelay: defaultOptions.initialDelay ?? 100,\n maxDelay: defaultOptions.maxDelay ?? 10_000,\n jitter: defaultOptions.jitter ?? 0.1,\n };\n\n if (defaultOptions.shouldRetry) {\n defaults.shouldRetry = defaultOptions.shouldRetry;\n }\n if (defaultOptions.onRetry) {\n defaults.onRetry = defaultOptions.onRetry;\n }\n\n return async <T>(\n fn: () => Promise<T>,\n options?: Partial<RetryOptions>\n ): Promise<T> => {\n return executeWithRetry(fn, { ...defaults, ...options });\n };\n}\n","/**\n * @parsrun/service - Timeout\n * Timeout wrapper for async operations\n */\n\n// ============================================================================\n// TIMEOUT\n// ============================================================================\n\n/**\n * Timeout error\n */\nexport class TimeoutExceededError extends Error {\n readonly timeout: number;\n\n constructor(timeout: number) {\n super(`Operation timed out after ${timeout}ms`);\n this.name = \"TimeoutExceededError\";\n this.timeout = timeout;\n }\n}\n\n/**\n * Wrap a function with timeout\n */\nexport function withTimeout<T>(\n fn: () => Promise<T>,\n timeoutMs: number,\n onTimeout?: () => void | never\n): () => Promise<T> {\n return async (): Promise<T> => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n if (onTimeout) {\n try {\n onTimeout();\n } catch (error) {\n reject(error);\n return;\n }\n }\n reject(new TimeoutExceededError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([fn(), timeoutPromise]);\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n };\n}\n\n/**\n * Execute a function with timeout\n */\nexport async function executeWithTimeout<T>(\n fn: () => Promise<T>,\n timeoutMs: number,\n onTimeout?: () => void | never\n): Promise<T> {\n return withTimeout(fn, timeoutMs, onTimeout)();\n}\n\n/**\n * Create a timeout wrapper with preset duration\n */\nexport function createTimeoutWrapper(\n defaultTimeoutMs: number\n): <T>(fn: () => Promise<T>, timeoutMs?: number) => Promise<T> {\n return async <T>(fn: () => Promise<T>, timeoutMs?: number): Promise<T> => {\n return executeWithTimeout(fn, timeoutMs ?? defaultTimeoutMs);\n };\n}\n\n/**\n * Race multiple promises with a timeout\n */\nexport async function raceWithTimeout<T>(\n promises: Promise<T>[],\n timeoutMs: number\n): Promise<T> {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new TimeoutExceededError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([...promises, timeoutPromise]);\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n}\n\n/**\n * Execute with deadline (absolute time)\n */\nexport async function executeWithDeadline<T>(\n fn: () => Promise<T>,\n deadline: Date\n): Promise<T> {\n const now = Date.now();\n const deadlineMs = deadline.getTime();\n const timeoutMs = Math.max(0, deadlineMs - now);\n\n if (timeoutMs === 0) {\n throw new TimeoutExceededError(0);\n }\n\n return executeWithTimeout(fn, timeoutMs);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/rpc/errors.ts","../../src/resilience/circuit-breaker.ts","../../src/resilience/bulkhead.ts","../../src/resilience/retry.ts","../../src/resilience/timeout.ts"],"sourcesContent":["/**\n * @parsrun/service - RPC Errors\n */\n\nimport { ParsError } from \"@parsrun/core\";\n\n/**\n * Base RPC error\n */\nexport class RpcError extends ParsError {\n public readonly retryable: boolean;\n public readonly retryAfter?: number;\n\n constructor(\n message: string,\n code: string,\n statusCode: number = 500,\n options?: {\n retryable?: boolean;\n retryAfter?: number;\n details?: Record<string, unknown>;\n }\n ) {\n super(message, code, statusCode, options?.details);\n this.name = \"RpcError\";\n this.retryable = options?.retryable ?? false;\n if (options?.retryAfter !== undefined) {\n this.retryAfter = options.retryAfter;\n }\n }\n}\n\n/**\n * Service not found error\n */\nexport class ServiceNotFoundError extends RpcError {\n constructor(serviceName: string) {\n super(`Service not found: ${serviceName}`, \"SERVICE_NOT_FOUND\", 404, {\n retryable: false,\n details: { service: serviceName },\n });\n this.name = \"ServiceNotFoundError\";\n }\n}\n\n/**\n * Method not found error\n */\nexport class MethodNotFoundError extends RpcError {\n constructor(serviceName: string, methodName: string) {\n super(\n `Method not found: ${serviceName}.${methodName}`,\n \"METHOD_NOT_FOUND\",\n 404,\n {\n retryable: false,\n details: { service: serviceName, method: methodName },\n }\n );\n this.name = \"MethodNotFoundError\";\n }\n}\n\n/**\n * Version mismatch error\n */\nexport class VersionMismatchError extends RpcError {\n constructor(serviceName: string, requested: string, available: string) {\n super(\n `Version mismatch for ${serviceName}: requested ${requested}, available ${available}`,\n \"VERSION_MISMATCH\",\n 400,\n {\n retryable: false,\n details: { service: serviceName, requested, available },\n }\n );\n this.name = \"VersionMismatchError\";\n }\n}\n\n/**\n * Timeout error\n */\nexport class TimeoutError extends RpcError {\n constructor(serviceName: string, methodName: string, timeoutMs: number) {\n super(\n `Request to ${serviceName}.${methodName} timed out after ${timeoutMs}ms`,\n \"TIMEOUT\",\n 504,\n {\n retryable: true,\n details: { service: serviceName, method: methodName, timeout: timeoutMs },\n }\n );\n this.name = \"TimeoutError\";\n }\n}\n\n/**\n * Circuit breaker open error\n */\nexport class CircuitOpenError extends RpcError {\n constructor(serviceName: string, resetAfterMs: number) {\n super(\n `Circuit breaker open for ${serviceName}`,\n \"CIRCUIT_OPEN\",\n 503,\n {\n retryable: true,\n retryAfter: Math.ceil(resetAfterMs / 1000),\n details: { service: serviceName, resetAfterMs },\n }\n );\n this.name = \"CircuitOpenError\";\n }\n}\n\n/**\n * Bulkhead rejected error\n */\nexport class BulkheadRejectedError extends RpcError {\n constructor(serviceName: string) {\n super(\n `Request rejected by bulkhead for ${serviceName}: too many concurrent requests`,\n \"BULKHEAD_REJECTED\",\n 503,\n {\n retryable: true,\n retryAfter: 1,\n details: { service: serviceName },\n }\n );\n this.name = \"BulkheadRejectedError\";\n }\n}\n\n/**\n * Transport error\n */\nexport class TransportError extends RpcError {\n constructor(message: string, cause?: Error) {\n const options: { retryable: boolean; details?: Record<string, unknown> } = {\n retryable: true,\n };\n if (cause) {\n options.details = { cause: cause.message };\n }\n super(message, \"TRANSPORT_ERROR\", 502, options);\n this.name = \"TransportError\";\n }\n}\n\n/**\n * Serialization error\n */\nexport class SerializationError extends RpcError {\n constructor(message: string, cause?: Error) {\n const options: { retryable: boolean; details?: Record<string, unknown> } = {\n retryable: false,\n };\n if (cause) {\n options.details = { cause: cause.message };\n }\n super(message, \"SERIALIZATION_ERROR\", 400, options);\n this.name = \"SerializationError\";\n }\n}\n\n/**\n * Convert unknown error to RpcError\n */\nexport function toRpcError(error: unknown): RpcError {\n if (error instanceof RpcError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new RpcError(error.message, \"INTERNAL_ERROR\", 500, {\n retryable: false,\n details: { originalError: error.name },\n });\n }\n\n return new RpcError(String(error), \"UNKNOWN_ERROR\", 500, {\n retryable: false,\n });\n}\n","/**\n * @parsrun/service - Circuit Breaker\n * Prevents cascading failures by failing fast when a service is unhealthy\n */\n\nimport { CircuitOpenError } from \"../rpc/errors.js\";\n\n// ============================================================================\n// CIRCUIT BREAKER\n// ============================================================================\n\n/**\n * Options for configuring a circuit breaker.\n */\nexport interface CircuitBreakerOptions {\n /** Number of failures before opening circuit */\n failureThreshold: number;\n /** Time to wait before half-open state (ms) */\n resetTimeout: number;\n /** Number of successes in half-open to close circuit */\n successThreshold: number;\n /** Optional callback on state change */\n onStateChange?: (from: CircuitState, to: CircuitState) => void;\n}\n\n/**\n * Circuit breaker state.\n * - \"closed\": Normal operation, requests pass through\n * - \"open\": Failing fast, requests are rejected immediately\n * - \"half-open\": Testing if service recovered, limited requests allowed\n */\nexport type CircuitState = \"closed\" | \"open\" | \"half-open\";\n\n/**\n * Circuit Breaker implementation\n *\n * States:\n * - CLOSED: Normal operation, requests pass through\n * - OPEN: Failing fast, requests are rejected immediately\n * - HALF-OPEN: Testing if service recovered, limited requests allowed\n */\nexport class CircuitBreaker {\n private _state: CircuitState = \"closed\";\n private failures = 0;\n private successes = 0;\n private lastFailureTime = 0;\n private readonly options: CircuitBreakerOptions;\n\n constructor(options: CircuitBreakerOptions) {\n this.options = options;\n }\n\n /**\n * Get current state\n */\n get state(): CircuitState {\n // Check if we should transition from open to half-open\n if (this._state === \"open\") {\n const timeSinceFailure = Date.now() - this.lastFailureTime;\n if (timeSinceFailure >= this.options.resetTimeout) {\n this.transitionTo(\"half-open\");\n }\n }\n return this._state;\n }\n\n /**\n * Execute a function with circuit breaker protection\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check state (this may transition from open to half-open)\n const currentState = this.state;\n\n if (currentState === \"open\") {\n const resetAfter = this.options.resetTimeout - (Date.now() - this.lastFailureTime);\n throw new CircuitOpenError(\"service\", Math.max(0, resetAfter));\n }\n\n try {\n const result = await fn();\n this.onSuccess();\n return result;\n } catch (error) {\n this.onFailure();\n throw error;\n }\n }\n\n /**\n * Record a successful call\n */\n private onSuccess(): void {\n if (this._state === \"half-open\") {\n this.successes++;\n if (this.successes >= this.options.successThreshold) {\n this.transitionTo(\"closed\");\n }\n } else if (this._state === \"closed\") {\n // Reset failure count on success\n this.failures = 0;\n }\n }\n\n /**\n * Record a failed call\n */\n private onFailure(): void {\n this.lastFailureTime = Date.now();\n\n if (this._state === \"half-open\") {\n // Any failure in half-open goes back to open\n this.transitionTo(\"open\");\n } else if (this._state === \"closed\") {\n this.failures++;\n if (this.failures >= this.options.failureThreshold) {\n this.transitionTo(\"open\");\n }\n }\n }\n\n /**\n * Transition to a new state\n */\n private transitionTo(newState: CircuitState): void {\n const oldState = this._state;\n this._state = newState;\n\n // Reset counters on state change\n if (newState === \"closed\") {\n this.failures = 0;\n this.successes = 0;\n } else if (newState === \"half-open\") {\n this.successes = 0;\n }\n\n this.options.onStateChange?.(oldState, newState);\n }\n\n /**\n * Manually reset the circuit breaker\n */\n reset(): void {\n this.transitionTo(\"closed\");\n }\n\n /**\n * Get circuit breaker statistics\n */\n getStats(): {\n state: CircuitState;\n failures: number;\n successes: number;\n lastFailureTime: number;\n } {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n lastFailureTime: this.lastFailureTime,\n };\n }\n}\n","/**\n * @parsrun/service - Bulkhead\n * Limits concurrent requests to prevent resource exhaustion\n */\n\nimport { BulkheadRejectedError } from \"../rpc/errors.js\";\n\n// ============================================================================\n// BULKHEAD\n// ============================================================================\n\n/**\n * Options for configuring a bulkhead.\n */\nexport interface BulkheadOptions {\n /** Maximum concurrent requests */\n maxConcurrent: number;\n /** Maximum queue size (0 = no queue) */\n maxQueue: number;\n /** Optional callback when request is rejected */\n onRejected?: () => void;\n}\n\ninterface QueuedRequest<T> {\n fn: () => Promise<T>;\n resolve: (value: T) => void;\n reject: (error: Error) => void;\n}\n\n/**\n * Bulkhead implementation\n *\n * Limits the number of concurrent requests to protect resources.\n * Excess requests can be queued up to maxQueue limit.\n */\nexport class Bulkhead {\n private _concurrent = 0;\n private readonly queue: QueuedRequest<unknown>[] = [];\n private readonly options: BulkheadOptions;\n\n constructor(options: BulkheadOptions) {\n this.options = options;\n }\n\n /**\n * Get current concurrent count\n */\n get concurrent(): number {\n return this._concurrent;\n }\n\n /**\n * Get current queue size\n */\n get queued(): number {\n return this.queue.length;\n }\n\n /**\n * Check if bulkhead is full\n */\n get isFull(): boolean {\n return (\n this._concurrent >= this.options.maxConcurrent &&\n this.queue.length >= this.options.maxQueue\n );\n }\n\n /**\n * Execute a function with bulkhead protection\n */\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n // Check if we can execute immediately\n if (this._concurrent < this.options.maxConcurrent) {\n return this.doExecute(fn);\n }\n\n // Check if we can queue\n if (this.queue.length < this.options.maxQueue) {\n return this.enqueue(fn);\n }\n\n // Reject\n this.options.onRejected?.();\n throw new BulkheadRejectedError(\"service\");\n }\n\n /**\n * Execute immediately\n */\n private async doExecute<T>(fn: () => Promise<T>): Promise<T> {\n this._concurrent++;\n try {\n return await fn();\n } finally {\n this._concurrent--;\n this.processQueue();\n }\n }\n\n /**\n * Add to queue\n */\n private enqueue<T>(fn: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this.queue.push({\n fn,\n resolve: resolve as (value: unknown) => void,\n reject,\n });\n });\n }\n\n /**\n * Process queued requests\n */\n private processQueue(): void {\n if (this.queue.length === 0) return;\n if (this._concurrent >= this.options.maxConcurrent) return;\n\n const queued = this.queue.shift();\n if (!queued) return;\n\n this.doExecute(queued.fn)\n .then(queued.resolve)\n .catch(queued.reject);\n }\n\n /**\n * Get bulkhead statistics\n */\n getStats(): {\n concurrent: number;\n queued: number;\n maxConcurrent: number;\n maxQueue: number;\n } {\n return {\n concurrent: this._concurrent,\n queued: this.queue.length,\n maxConcurrent: this.options.maxConcurrent,\n maxQueue: this.options.maxQueue,\n };\n }\n\n /**\n * Clear the queue (reject all pending)\n */\n clearQueue(): void {\n const error = new BulkheadRejectedError(\"service\");\n while (this.queue.length > 0) {\n const queued = this.queue.shift();\n queued?.reject(error);\n }\n }\n}\n","/**\n * @parsrun/service - Retry\n * Retry failed operations with backoff\n */\n\n// ============================================================================\n// RETRY\n// ============================================================================\n\n/**\n * Options for configuring retry behavior.\n */\nexport interface RetryOptions {\n /** Number of retry attempts (not including initial attempt) */\n attempts: number;\n /** Backoff strategy */\n backoff: \"linear\" | \"exponential\";\n /** Initial delay in ms */\n initialDelay: number;\n /** Maximum delay in ms */\n maxDelay: number;\n /** Jitter factor (0-1) to add randomness */\n jitter?: number;\n /** Should retry predicate */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Callback on retry */\n onRetry?: (error: unknown, attempt: number, delay: number) => void;\n}\n\n/**\n * Default retry predicate - retry on retryable errors\n */\nconst defaultShouldRetry = (error: unknown): boolean => {\n if (error && typeof error === \"object\" && \"retryable\" in error) {\n return (error as { retryable: boolean }).retryable;\n }\n return false;\n};\n\n/**\n * Calculate delay for retry attempt\n */\nfunction calculateDelay(\n attempt: number,\n options: RetryOptions\n): number {\n let delay: number;\n\n if (options.backoff === \"exponential\") {\n // Exponential backoff: initialDelay * 2^attempt\n delay = options.initialDelay * Math.pow(2, attempt);\n } else {\n // Linear backoff: initialDelay * (attempt + 1)\n delay = options.initialDelay * (attempt + 1);\n }\n\n // Apply max delay\n delay = Math.min(delay, options.maxDelay);\n\n // Apply jitter\n if (options.jitter && options.jitter > 0) {\n const jitterRange = delay * options.jitter;\n delay = delay - jitterRange / 2 + Math.random() * jitterRange;\n }\n\n return Math.round(delay);\n}\n\n/**\n * Sleep for a given duration\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Wrap a function with retry logic.\n * Returns a new function that will retry on failure.\n *\n * @param fn - The function to wrap\n * @param options - Retry configuration\n * @returns A wrapped function with retry behavior\n *\n * @example\n * ```typescript\n * const fetchWithRetry = withRetry(\n * () => fetch('/api/data'),\n * { attempts: 3, backoff: 'exponential', initialDelay: 100, maxDelay: 5000 }\n * );\n * const response = await fetchWithRetry();\n * ```\n */\nexport function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions\n): () => Promise<T> {\n const shouldRetry = options.shouldRetry ?? defaultShouldRetry;\n\n return async (): Promise<T> => {\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= options.attempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Check if we should retry\n if (attempt >= options.attempts || !shouldRetry(error, attempt)) {\n throw error;\n }\n\n // Calculate delay\n const delay = calculateDelay(attempt, options);\n\n // Callback\n options.onRetry?.(error, attempt + 1, delay);\n\n // Wait before retry\n await sleep(delay);\n }\n }\n\n throw lastError;\n };\n}\n\n/**\n * Execute a function with retry logic immediately.\n *\n * @param fn - The function to execute\n * @param options - Retry configuration\n * @returns Promise resolving to the function result\n */\nexport async function executeWithRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions\n): Promise<T> {\n return withRetry(fn, options)();\n}\n\n/**\n * Create a reusable retry wrapper with preset default options.\n *\n * @param defaultOptions - Default retry configuration\n * @returns A function that executes with retry using the defaults\n *\n * @example\n * ```typescript\n * const retry = createRetryWrapper({ attempts: 3, backoff: 'exponential' });\n * const result = await retry(() => fetchData());\n * ```\n */\nexport function createRetryWrapper(\n defaultOptions: Partial<RetryOptions>\n): <T>(fn: () => Promise<T>, options?: Partial<RetryOptions>) => Promise<T> {\n const defaults: RetryOptions = {\n attempts: defaultOptions.attempts ?? 3,\n backoff: defaultOptions.backoff ?? \"exponential\",\n initialDelay: defaultOptions.initialDelay ?? 100,\n maxDelay: defaultOptions.maxDelay ?? 10_000,\n jitter: defaultOptions.jitter ?? 0.1,\n };\n\n if (defaultOptions.shouldRetry) {\n defaults.shouldRetry = defaultOptions.shouldRetry;\n }\n if (defaultOptions.onRetry) {\n defaults.onRetry = defaultOptions.onRetry;\n }\n\n return async <T>(\n fn: () => Promise<T>,\n options?: Partial<RetryOptions>\n ): Promise<T> => {\n return executeWithRetry(fn, { ...defaults, ...options });\n };\n}\n","/**\n * @parsrun/service - Timeout\n * Timeout wrapper for async operations\n */\n\n// ============================================================================\n// TIMEOUT\n// ============================================================================\n\n/**\n * Error thrown when an operation exceeds its timeout.\n */\nexport class TimeoutExceededError extends Error {\n /** The timeout value in milliseconds that was exceeded */\n readonly timeout: number;\n\n constructor(timeout: number) {\n super(`Operation timed out after ${timeout}ms`);\n this.name = \"TimeoutExceededError\";\n this.timeout = timeout;\n }\n}\n\n/**\n * Wrap a function with a timeout.\n * Returns a new function that will reject if the timeout is exceeded.\n *\n * @param fn - The function to wrap\n * @param timeoutMs - Timeout in milliseconds\n * @param onTimeout - Optional callback or throw function when timeout occurs\n * @returns A wrapped function with timeout behavior\n */\nexport function withTimeout<T>(\n fn: () => Promise<T>,\n timeoutMs: number,\n onTimeout?: () => void | never\n): () => Promise<T> {\n return async (): Promise<T> => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n if (onTimeout) {\n try {\n onTimeout();\n } catch (error) {\n reject(error);\n return;\n }\n }\n reject(new TimeoutExceededError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([fn(), timeoutPromise]);\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n };\n}\n\n/**\n * Execute a function with timeout immediately.\n *\n * @param fn - The function to execute\n * @param timeoutMs - Timeout in milliseconds\n * @param onTimeout - Optional callback or throw function when timeout occurs\n * @returns Promise resolving to the function result or rejecting on timeout\n */\nexport async function executeWithTimeout<T>(\n fn: () => Promise<T>,\n timeoutMs: number,\n onTimeout?: () => void | never\n): Promise<T> {\n return withTimeout(fn, timeoutMs, onTimeout)();\n}\n\n/**\n * Create a reusable timeout wrapper with preset duration.\n *\n * @param defaultTimeoutMs - Default timeout in milliseconds\n * @returns A function that executes with timeout\n */\nexport function createTimeoutWrapper(\n defaultTimeoutMs: number\n): <T>(fn: () => Promise<T>, timeoutMs?: number) => Promise<T> {\n return async <T>(fn: () => Promise<T>, timeoutMs?: number): Promise<T> => {\n return executeWithTimeout(fn, timeoutMs ?? defaultTimeoutMs);\n };\n}\n\n/**\n * Race multiple promises with a timeout.\n * Returns the first promise to resolve, or rejects on timeout.\n *\n * @param promises - Array of promises to race\n * @param timeoutMs - Timeout in milliseconds\n * @returns Promise resolving to the first result\n */\nexport async function raceWithTimeout<T>(\n promises: Promise<T>[],\n timeoutMs: number\n): Promise<T> {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n reject(new TimeoutExceededError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([...promises, timeoutPromise]);\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n}\n\n/**\n * Execute a function with an absolute deadline.\n * Converts the deadline to a relative timeout.\n *\n * @param fn - The function to execute\n * @param deadline - Absolute deadline as a Date\n * @returns Promise resolving to the function result\n */\nexport async function executeWithDeadline<T>(\n fn: () => Promise<T>,\n deadline: Date\n): Promise<T> {\n const now = Date.now();\n const deadlineMs = deadline.getTime();\n const timeoutMs = Math.max(0, deadlineMs - now);\n\n if (timeoutMs === 0) {\n throw new TimeoutExceededError(0);\n }\n\n return executeWithTimeout(fn, timeoutMs);\n}\n"],"mappings":"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","names":[]}
|
package/dist/rpc/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { B as BulkheadRejectedError, C as CallOptions, i as CircuitOpenError, b as EmbeddedRegistry, E as EmbeddedTransport, H as HttpTransport, f as HttpTransportOptions, M as MethodNotFoundError, R as RpcClient, h as RpcError, k as SerializationError, S as ServiceNotFoundError, T as TimeoutError, j as TransportError, V as VersionMismatchError, a as createEmbeddedTransport, e as createHttpHandler, d as createHttpTransport, c as createRpcClient, g as getEmbeddedRegistry, t as toRpcError } from '../index-
|
|
2
|
-
export { a as RpcHandler, e as RpcHandlerContext, b as RpcHandlers, d as RpcMiddleware, R as RpcServer, c as createRpcServer, l as loggingMiddleware, t as tenantMiddleware, v as validationMiddleware } from '../server-
|
|
3
|
-
import '../types-
|
|
1
|
+
export { B as BulkheadRejectedError, C as CallOptions, i as CircuitOpenError, b as EmbeddedRegistry, E as EmbeddedTransport, H as HttpTransport, f as HttpTransportOptions, M as MethodNotFoundError, R as RpcClient, h as RpcError, k as SerializationError, S as ServiceNotFoundError, T as TimeoutError, j as TransportError, V as VersionMismatchError, a as createEmbeddedTransport, e as createHttpHandler, d as createHttpTransport, c as createRpcClient, g as getEmbeddedRegistry, t as toRpcError } from '../index-reEpIe1R.js';
|
|
2
|
+
export { a as RpcHandler, e as RpcHandlerContext, b as RpcHandlers, d as RpcMiddleware, R as RpcServer, c as createRpcServer, l as loggingMiddleware, t as tenantMiddleware, v as validationMiddleware } from '../server-BB9AbnkP.js';
|
|
3
|
+
import '../types-DHZaZwAt.js';
|
|
4
4
|
import '../serialization/index.js';
|
|
5
5
|
import '@parsrun/core';
|
package/dist/rpc/index.js
CHANGED
|
@@ -474,6 +474,7 @@ function withRetry(fn, options) {
|
|
|
474
474
|
|
|
475
475
|
// src/resilience/timeout.ts
|
|
476
476
|
var TimeoutExceededError = class extends Error {
|
|
477
|
+
/** The timeout value in milliseconds that was exceeded */
|
|
477
478
|
timeout;
|
|
478
479
|
constructor(timeout) {
|
|
479
480
|
super(`Operation timed out after ${timeout}ms`);
|