awaitly 1.35.0 → 2.0.0
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/{duration.d.ts → di-BDlT7InM.d.cts} +15 -1
- package/dist/{duration.d.cts → di-BbFFfO8y.d.ts} +15 -1
- package/dist/errors-DtXvrCiO.d.cts +708 -0
- package/dist/errors-DtXvrCiO.d.ts +708 -0
- package/dist/index.cjs +4594 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1970 -141
- package/dist/index.d.ts +1970 -141
- package/dist/index.js +4398 -1
- package/dist/index.js.map +1 -1
- package/dist/result.cjs +641 -1
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts +29 -4
- package/dist/result.d.ts +29 -4
- package/dist/result.js +561 -1
- package/dist/result.js.map +1 -1
- package/dist/testing.cjs +4202 -8
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -6
- package/dist/testing.d.ts +2 -6
- package/dist/testing.js +4154 -8
- package/dist/testing.js.map +1 -1
- package/dist/{run-entry-DGs0tySr.d.cts → types-B8NfNRGX.d.ts} +1078 -1502
- package/dist/{run-entry-BOuNyVoO.d.ts → types-BZ2f4MRR.d.cts} +1078 -1502
- package/dist/workflow.cjs +7096 -6
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +3346 -22
- package/dist/workflow.d.ts +3346 -22
- package/dist/workflow.js +6929 -6
- package/dist/workflow.js.map +1 -1
- package/package.json +3 -168
- package/dist/adapters.cjs +0 -7
- package/dist/adapters.cjs.map +0 -1
- package/dist/adapters.d.cts +0 -179
- package/dist/adapters.d.ts +0 -179
- package/dist/adapters.js +0 -7
- package/dist/adapters.js.map +0 -1
- package/dist/batch.cjs +0 -7
- package/dist/batch.cjs.map +0 -1
- package/dist/batch.d.cts +0 -200
- package/dist/batch.d.ts +0 -200
- package/dist/batch.js +0 -7
- package/dist/batch.js.map +0 -1
- package/dist/bind-deps.cjs +0 -2
- package/dist/bind-deps.cjs.map +0 -1
- package/dist/bind-deps.d.cts +0 -28
- package/dist/bind-deps.d.ts +0 -28
- package/dist/bind-deps.js +0 -2
- package/dist/bind-deps.js.map +0 -1
- package/dist/cache.cjs +0 -2
- package/dist/cache.cjs.map +0 -1
- package/dist/cache.d.cts +0 -269
- package/dist/cache.d.ts +0 -269
- package/dist/cache.js +0 -2
- package/dist/cache.js.map +0 -1
- package/dist/circuit-breaker.cjs +0 -7
- package/dist/circuit-breaker.cjs.map +0 -1
- package/dist/circuit-breaker.d.cts +0 -211
- package/dist/circuit-breaker.d.ts +0 -211
- package/dist/circuit-breaker.js +0 -7
- package/dist/circuit-breaker.js.map +0 -1
- package/dist/conditional.cjs +0 -2
- package/dist/conditional.cjs.map +0 -1
- package/dist/conditional.d.cts +0 -252
- package/dist/conditional.d.ts +0 -252
- package/dist/conditional.js +0 -2
- package/dist/conditional.js.map +0 -1
- package/dist/core.cjs +0 -7
- package/dist/core.cjs.map +0 -1
- package/dist/core.d.cts +0 -5
- package/dist/core.d.ts +0 -5
- package/dist/core.js +0 -7
- package/dist/core.js.map +0 -1
- package/dist/di-By77n4Fa.d.ts +0 -15
- package/dist/di-OJfsohf-.d.cts +0 -15
- package/dist/diagnostics.cjs +0 -8
- package/dist/diagnostics.cjs.map +0 -1
- package/dist/diagnostics.d.cts +0 -68
- package/dist/diagnostics.d.ts +0 -68
- package/dist/diagnostics.js +0 -8
- package/dist/diagnostics.js.map +0 -1
- package/dist/durable.cjs +0 -11
- package/dist/durable.cjs.map +0 -1
- package/dist/durable.d.cts +0 -9
- package/dist/durable.d.ts +0 -9
- package/dist/durable.js +0 -11
- package/dist/durable.js.map +0 -1
- package/dist/duration.cjs +0 -2
- package/dist/duration.cjs.map +0 -1
- package/dist/duration.js +0 -2
- package/dist/duration.js.map +0 -1
- package/dist/engine.cjs +0 -11
- package/dist/engine.cjs.map +0 -1
- package/dist/engine.d.cts +0 -115
- package/dist/engine.d.ts +0 -115
- package/dist/engine.js +0 -11
- package/dist/engine.js.map +0 -1
- package/dist/errors.cjs +0 -2
- package/dist/errors.cjs.map +0 -1
- package/dist/errors.d.cts +0 -361
- package/dist/errors.d.ts +0 -361
- package/dist/errors.js +0 -2
- package/dist/errors.js.map +0 -1
- package/dist/fetch.cjs +0 -7
- package/dist/fetch.cjs.map +0 -1
- package/dist/fetch.d.cts +0 -86
- package/dist/fetch.d.ts +0 -86
- package/dist/fetch.js +0 -7
- package/dist/fetch.js.map +0 -1
- package/dist/flow.cjs +0 -7
- package/dist/flow.cjs.map +0 -1
- package/dist/flow.d.cts +0 -163
- package/dist/flow.d.ts +0 -163
- package/dist/flow.js +0 -7
- package/dist/flow.js.map +0 -1
- package/dist/functional.cjs +0 -2
- package/dist/functional.cjs.map +0 -1
- package/dist/functional.d.cts +0 -444
- package/dist/functional.d.ts +0 -444
- package/dist/functional.js +0 -2
- package/dist/functional.js.map +0 -1
- package/dist/guards-4sV7mTqj.d.cts +0 -72
- package/dist/guards-BIX05ALH.d.ts +0 -72
- package/dist/hitl-DFn4Xa_l.d.cts +0 -468
- package/dist/hitl-DU5VpKq7.d.ts +0 -468
- package/dist/hitl.cjs +0 -7
- package/dist/hitl.cjs.map +0 -1
- package/dist/hitl.d.cts +0 -442
- package/dist/hitl.d.ts +0 -442
- package/dist/hitl.js +0 -7
- package/dist/hitl.js.map +0 -1
- package/dist/index-CnvBryQB.d.ts +0 -417
- package/dist/index-DEZEf8Fs.d.cts +0 -417
- package/dist/match-entry-DjI2bLpD.d.cts +0 -209
- package/dist/match-entry-DjI2bLpD.d.ts +0 -209
- package/dist/match.cjs +0 -2
- package/dist/match.cjs.map +0 -1
- package/dist/match.d.cts +0 -1
- package/dist/match.d.ts +0 -1
- package/dist/match.js +0 -2
- package/dist/match.js.map +0 -1
- package/dist/otel.cjs +0 -2
- package/dist/otel.cjs.map +0 -1
- package/dist/otel.d.cts +0 -188
- package/dist/otel.d.ts +0 -188
- package/dist/otel.js +0 -2
- package/dist/otel.js.map +0 -1
- package/dist/persistence-entry-B-8PjnSR.d.cts +0 -831
- package/dist/persistence-entry-D8zRkLiT.d.ts +0 -831
- package/dist/persistence.cjs +0 -2
- package/dist/persistence.cjs.map +0 -1
- package/dist/persistence.d.cts +0 -7
- package/dist/persistence.d.ts +0 -7
- package/dist/persistence.js +0 -2
- package/dist/persistence.js.map +0 -1
- package/dist/policies.cjs +0 -2
- package/dist/policies.cjs.map +0 -1
- package/dist/policies.d.cts +0 -379
- package/dist/policies.d.ts +0 -379
- package/dist/policies.js +0 -2
- package/dist/policies.js.map +0 -1
- package/dist/ratelimit.cjs +0 -7
- package/dist/ratelimit.cjs.map +0 -1
- package/dist/ratelimit.d.cts +0 -458
- package/dist/ratelimit.d.ts +0 -458
- package/dist/ratelimit.js +0 -7
- package/dist/ratelimit.js.map +0 -1
- package/dist/reliability.cjs +0 -11
- package/dist/reliability.cjs.map +0 -1
- package/dist/reliability.d.cts +0 -11
- package/dist/reliability.d.ts +0 -11
- package/dist/reliability.js +0 -11
- package/dist/reliability.js.map +0 -1
- package/dist/resolver.cjs +0 -7
- package/dist/resolver.cjs.map +0 -1
- package/dist/resolver.d.cts +0 -68
- package/dist/resolver.d.ts +0 -68
- package/dist/resolver.js +0 -7
- package/dist/resolver.js.map +0 -1
- package/dist/resource.cjs +0 -7
- package/dist/resource.cjs.map +0 -1
- package/dist/resource.d.cts +0 -174
- package/dist/resource.d.ts +0 -174
- package/dist/resource.js +0 -7
- package/dist/resource.js.map +0 -1
- package/dist/result/retry.cjs +0 -2
- package/dist/result/retry.cjs.map +0 -1
- package/dist/result/retry.d.cts +0 -70
- package/dist/result/retry.d.ts +0 -70
- package/dist/result/retry.js +0 -2
- package/dist/result/retry.js.map +0 -1
- package/dist/retry.cjs +0 -2
- package/dist/retry.cjs.map +0 -1
- package/dist/retry.d.cts +0 -388
- package/dist/retry.d.ts +0 -388
- package/dist/retry.js +0 -2
- package/dist/retry.js.map +0 -1
- package/dist/run.cjs +0 -7
- package/dist/run.cjs.map +0 -1
- package/dist/run.d.cts +0 -4
- package/dist/run.d.ts +0 -4
- package/dist/run.js +0 -7
- package/dist/run.js.map +0 -1
- package/dist/saga.cjs +0 -11
- package/dist/saga.cjs.map +0 -1
- package/dist/saga.d.cts +0 -164
- package/dist/saga.d.ts +0 -164
- package/dist/saga.js +0 -11
- package/dist/saga.js.map +0 -1
- package/dist/singleflight.cjs +0 -2
- package/dist/singleflight.cjs.map +0 -1
- package/dist/singleflight.d.cts +0 -145
- package/dist/singleflight.d.ts +0 -145
- package/dist/singleflight.js +0 -2
- package/dist/singleflight.js.map +0 -1
- package/dist/slugs.cjs +0 -2
- package/dist/slugs.cjs.map +0 -1
- package/dist/slugs.d.cts +0 -67
- package/dist/slugs.d.ts +0 -67
- package/dist/slugs.js +0 -2
- package/dist/slugs.js.map +0 -1
- package/dist/streaming.cjs +0 -9
- package/dist/streaming.cjs.map +0 -1
- package/dist/streaming.d.cts +0 -596
- package/dist/streaming.d.ts +0 -596
- package/dist/streaming.js +0 -9
- package/dist/streaming.js.map +0 -1
- package/dist/tagged-error.cjs +0 -2
- package/dist/tagged-error.cjs.map +0 -1
- package/dist/tagged-error.d.cts +0 -275
- package/dist/tagged-error.d.ts +0 -275
- package/dist/tagged-error.js +0 -2
- package/dist/tagged-error.js.map +0 -1
- package/dist/types-BziYHFkD.d.ts +0 -323
- package/dist/types-C5jLEUqY.d.cts +0 -323
- package/dist/webhook.cjs +0 -7
- package/dist/webhook.cjs.map +0 -1
- package/dist/webhook.d.cts +0 -499
- package/dist/webhook.d.ts +0 -499
- package/dist/webhook.js +0 -7
- package/dist/webhook.js.map +0 -1
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { R as Result, c as AsyncResult } from './run-entry-DGs0tySr.cjs';
|
|
2
|
-
import './errors.cjs';
|
|
3
|
-
import './tagged-error.cjs';
|
|
4
|
-
import './slugs.cjs';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Circuit Breaker for Steps
|
|
8
|
-
*
|
|
9
|
-
* Prevents cascading failures by tracking step failure rates and
|
|
10
|
-
* short-circuiting calls when a threshold is exceeded.
|
|
11
|
-
*
|
|
12
|
-
* Uses the circuit breaker pattern with three states:
|
|
13
|
-
* - CLOSED: Normal operation (steps executing)
|
|
14
|
-
* - OPEN: Fast-fail mode (steps blocked)
|
|
15
|
-
* - HALF_OPEN: Testing if service recovered
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* import { createCircuitBreaker } from 'awaitly';
|
|
20
|
-
*
|
|
21
|
-
* const breaker = createCircuitBreaker({
|
|
22
|
-
* failureThreshold: 5,
|
|
23
|
-
* resetTimeout: 30000,
|
|
24
|
-
* halfOpenMax: 3,
|
|
25
|
-
* });
|
|
26
|
-
*
|
|
27
|
-
* const result = await workflow(async ({ step }) => {
|
|
28
|
-
* const data = await breaker.execute(
|
|
29
|
-
* () => step(() => callExternalApi()),
|
|
30
|
-
* { name: 'external-api' }
|
|
31
|
-
* );
|
|
32
|
-
* return data;
|
|
33
|
-
* });
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Circuit breaker state.
|
|
39
|
-
*/
|
|
40
|
-
type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";
|
|
41
|
-
/**
|
|
42
|
-
* Configuration for circuit breaker behavior.
|
|
43
|
-
*/
|
|
44
|
-
interface CircuitBreakerConfig {
|
|
45
|
-
/**
|
|
46
|
-
* Number of failures within the window before opening the circuit.
|
|
47
|
-
* @default 5
|
|
48
|
-
*/
|
|
49
|
-
failureThreshold: number;
|
|
50
|
-
/**
|
|
51
|
-
* Time in ms to wait before transitioning from OPEN to HALF_OPEN.
|
|
52
|
-
* @default 30000 (30 seconds)
|
|
53
|
-
*/
|
|
54
|
-
resetTimeout: number;
|
|
55
|
-
/**
|
|
56
|
-
* Time window in ms for counting failures.
|
|
57
|
-
* Failures older than this are discarded.
|
|
58
|
-
* @default 60000 (1 minute)
|
|
59
|
-
*/
|
|
60
|
-
windowSize: number;
|
|
61
|
-
/**
|
|
62
|
-
* Maximum number of test requests allowed in HALF_OPEN state.
|
|
63
|
-
* If all succeed, circuit closes. If any fail, circuit reopens.
|
|
64
|
-
* @default 3
|
|
65
|
-
*/
|
|
66
|
-
halfOpenMax: number;
|
|
67
|
-
/**
|
|
68
|
-
* Optional callback when circuit state changes.
|
|
69
|
-
*/
|
|
70
|
-
onStateChange?: (from: CircuitState, to: CircuitState, name?: string) => void;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Error thrown when the circuit is open and calls are blocked.
|
|
74
|
-
*/
|
|
75
|
-
declare class CircuitOpenError extends Error {
|
|
76
|
-
readonly type: "CIRCUIT_OPEN";
|
|
77
|
-
readonly circuitName: string;
|
|
78
|
-
readonly state: CircuitState;
|
|
79
|
-
readonly retryAfterMs: number;
|
|
80
|
-
constructor(options: {
|
|
81
|
-
circuitName: string;
|
|
82
|
-
state: CircuitState;
|
|
83
|
-
retryAfterMs: number;
|
|
84
|
-
message?: string;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Type guard for CircuitOpenError.
|
|
89
|
-
*/
|
|
90
|
-
declare function isCircuitOpenError(error: unknown): error is CircuitOpenError;
|
|
91
|
-
/**
|
|
92
|
-
* Circuit breaker statistics.
|
|
93
|
-
*/
|
|
94
|
-
interface CircuitBreakerStats {
|
|
95
|
-
state: CircuitState;
|
|
96
|
-
failureCount: number;
|
|
97
|
-
successCount: number;
|
|
98
|
-
lastFailureTime: number | null;
|
|
99
|
-
lastSuccessTime: number | null;
|
|
100
|
-
halfOpenSuccesses: number;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Circuit breaker instance for protecting external calls.
|
|
104
|
-
*/
|
|
105
|
-
interface CircuitBreaker {
|
|
106
|
-
/**
|
|
107
|
-
* Execute an operation with circuit breaker protection.
|
|
108
|
-
* Throws CircuitOpenError if the circuit is open.
|
|
109
|
-
*
|
|
110
|
-
* @param operation - The operation to execute
|
|
111
|
-
* @param options - Optional name for logging/metrics
|
|
112
|
-
* @returns The operation result
|
|
113
|
-
* @throws CircuitOpenError if circuit is open
|
|
114
|
-
*/
|
|
115
|
-
execute<T>(operation: () => T | Promise<T>, options?: {
|
|
116
|
-
name?: string;
|
|
117
|
-
}): Promise<T>;
|
|
118
|
-
/**
|
|
119
|
-
* Execute a Result-returning operation with circuit breaker protection.
|
|
120
|
-
* Returns a CircuitOpenError result instead of throwing.
|
|
121
|
-
*
|
|
122
|
-
* @param operation - The operation returning a Result
|
|
123
|
-
* @param options - Optional name for logging/metrics
|
|
124
|
-
* @returns Result with the value or CircuitOpenError
|
|
125
|
-
*/
|
|
126
|
-
executeResult<T, E>(operation: () => Result<T, E> | AsyncResult<T, E>, options?: {
|
|
127
|
-
name?: string;
|
|
128
|
-
}): AsyncResult<T, E | CircuitOpenError>;
|
|
129
|
-
/**
|
|
130
|
-
* Get current circuit state.
|
|
131
|
-
*/
|
|
132
|
-
getState(): CircuitState;
|
|
133
|
-
/**
|
|
134
|
-
* Get circuit breaker statistics.
|
|
135
|
-
*/
|
|
136
|
-
getStats(): CircuitBreakerStats;
|
|
137
|
-
/**
|
|
138
|
-
* Manually reset the circuit breaker to CLOSED state.
|
|
139
|
-
*/
|
|
140
|
-
reset(): void;
|
|
141
|
-
/**
|
|
142
|
-
* Manually open the circuit (for testing or manual intervention).
|
|
143
|
-
*/
|
|
144
|
-
forceOpen(): void;
|
|
145
|
-
/**
|
|
146
|
-
* Record a manual success (useful for health checks).
|
|
147
|
-
*/
|
|
148
|
-
recordSuccess(): void;
|
|
149
|
-
/**
|
|
150
|
-
* Record a manual failure (useful for health checks).
|
|
151
|
-
*/
|
|
152
|
-
recordFailure(error?: unknown): void;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Create a circuit breaker instance.
|
|
156
|
-
*
|
|
157
|
-
* @param name - Name for this circuit breaker (used in errors and logging)
|
|
158
|
-
* @param config - Configuration options
|
|
159
|
-
* @returns A CircuitBreaker instance
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* ```typescript
|
|
163
|
-
* const apiBreaker = createCircuitBreaker('external-api', {
|
|
164
|
-
* failureThreshold: 5,
|
|
165
|
-
* resetTimeout: 30000,
|
|
166
|
-
* });
|
|
167
|
-
*
|
|
168
|
-
* // In workflow
|
|
169
|
-
* const data = await apiBreaker.execute(() =>
|
|
170
|
-
* step(() => fetchFromApi(id))
|
|
171
|
-
* );
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
declare function createCircuitBreaker(name: string, config?: Partial<CircuitBreakerConfig>): CircuitBreaker;
|
|
175
|
-
/**
|
|
176
|
-
* Preset configurations for common use cases.
|
|
177
|
-
*/
|
|
178
|
-
declare const circuitBreakerPresets: {
|
|
179
|
-
/**
|
|
180
|
-
* Aggressive circuit breaker for critical paths.
|
|
181
|
-
* Opens quickly (3 failures) and recovers slowly (60s).
|
|
182
|
-
*/
|
|
183
|
-
readonly critical: {
|
|
184
|
-
failureThreshold: number;
|
|
185
|
-
resetTimeout: number;
|
|
186
|
-
windowSize: number;
|
|
187
|
-
halfOpenMax: number;
|
|
188
|
-
};
|
|
189
|
-
/**
|
|
190
|
-
* Standard circuit breaker for typical API calls.
|
|
191
|
-
* Balanced between stability and availability.
|
|
192
|
-
*/
|
|
193
|
-
readonly standard: {
|
|
194
|
-
failureThreshold: number;
|
|
195
|
-
resetTimeout: number;
|
|
196
|
-
windowSize: number;
|
|
197
|
-
halfOpenMax: number;
|
|
198
|
-
};
|
|
199
|
-
/**
|
|
200
|
-
* Lenient circuit breaker for non-critical operations.
|
|
201
|
-
* Opens slowly (10 failures) and recovers quickly (15s).
|
|
202
|
-
*/
|
|
203
|
-
readonly lenient: {
|
|
204
|
-
failureThreshold: number;
|
|
205
|
-
resetTimeout: number;
|
|
206
|
-
windowSize: number;
|
|
207
|
-
halfOpenMax: number;
|
|
208
|
-
};
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
export { type CircuitBreaker, type CircuitBreakerConfig, type CircuitBreakerStats, CircuitOpenError, type CircuitState, circuitBreakerPresets, createCircuitBreaker, isCircuitOpenError };
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { R as Result, c as AsyncResult } from './run-entry-BOuNyVoO.js';
|
|
2
|
-
import './errors.js';
|
|
3
|
-
import './tagged-error.js';
|
|
4
|
-
import './slugs.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Circuit Breaker for Steps
|
|
8
|
-
*
|
|
9
|
-
* Prevents cascading failures by tracking step failure rates and
|
|
10
|
-
* short-circuiting calls when a threshold is exceeded.
|
|
11
|
-
*
|
|
12
|
-
* Uses the circuit breaker pattern with three states:
|
|
13
|
-
* - CLOSED: Normal operation (steps executing)
|
|
14
|
-
* - OPEN: Fast-fail mode (steps blocked)
|
|
15
|
-
* - HALF_OPEN: Testing if service recovered
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* import { createCircuitBreaker } from 'awaitly';
|
|
20
|
-
*
|
|
21
|
-
* const breaker = createCircuitBreaker({
|
|
22
|
-
* failureThreshold: 5,
|
|
23
|
-
* resetTimeout: 30000,
|
|
24
|
-
* halfOpenMax: 3,
|
|
25
|
-
* });
|
|
26
|
-
*
|
|
27
|
-
* const result = await workflow(async ({ step }) => {
|
|
28
|
-
* const data = await breaker.execute(
|
|
29
|
-
* () => step(() => callExternalApi()),
|
|
30
|
-
* { name: 'external-api' }
|
|
31
|
-
* );
|
|
32
|
-
* return data;
|
|
33
|
-
* });
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Circuit breaker state.
|
|
39
|
-
*/
|
|
40
|
-
type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";
|
|
41
|
-
/**
|
|
42
|
-
* Configuration for circuit breaker behavior.
|
|
43
|
-
*/
|
|
44
|
-
interface CircuitBreakerConfig {
|
|
45
|
-
/**
|
|
46
|
-
* Number of failures within the window before opening the circuit.
|
|
47
|
-
* @default 5
|
|
48
|
-
*/
|
|
49
|
-
failureThreshold: number;
|
|
50
|
-
/**
|
|
51
|
-
* Time in ms to wait before transitioning from OPEN to HALF_OPEN.
|
|
52
|
-
* @default 30000 (30 seconds)
|
|
53
|
-
*/
|
|
54
|
-
resetTimeout: number;
|
|
55
|
-
/**
|
|
56
|
-
* Time window in ms for counting failures.
|
|
57
|
-
* Failures older than this are discarded.
|
|
58
|
-
* @default 60000 (1 minute)
|
|
59
|
-
*/
|
|
60
|
-
windowSize: number;
|
|
61
|
-
/**
|
|
62
|
-
* Maximum number of test requests allowed in HALF_OPEN state.
|
|
63
|
-
* If all succeed, circuit closes. If any fail, circuit reopens.
|
|
64
|
-
* @default 3
|
|
65
|
-
*/
|
|
66
|
-
halfOpenMax: number;
|
|
67
|
-
/**
|
|
68
|
-
* Optional callback when circuit state changes.
|
|
69
|
-
*/
|
|
70
|
-
onStateChange?: (from: CircuitState, to: CircuitState, name?: string) => void;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Error thrown when the circuit is open and calls are blocked.
|
|
74
|
-
*/
|
|
75
|
-
declare class CircuitOpenError extends Error {
|
|
76
|
-
readonly type: "CIRCUIT_OPEN";
|
|
77
|
-
readonly circuitName: string;
|
|
78
|
-
readonly state: CircuitState;
|
|
79
|
-
readonly retryAfterMs: number;
|
|
80
|
-
constructor(options: {
|
|
81
|
-
circuitName: string;
|
|
82
|
-
state: CircuitState;
|
|
83
|
-
retryAfterMs: number;
|
|
84
|
-
message?: string;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Type guard for CircuitOpenError.
|
|
89
|
-
*/
|
|
90
|
-
declare function isCircuitOpenError(error: unknown): error is CircuitOpenError;
|
|
91
|
-
/**
|
|
92
|
-
* Circuit breaker statistics.
|
|
93
|
-
*/
|
|
94
|
-
interface CircuitBreakerStats {
|
|
95
|
-
state: CircuitState;
|
|
96
|
-
failureCount: number;
|
|
97
|
-
successCount: number;
|
|
98
|
-
lastFailureTime: number | null;
|
|
99
|
-
lastSuccessTime: number | null;
|
|
100
|
-
halfOpenSuccesses: number;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Circuit breaker instance for protecting external calls.
|
|
104
|
-
*/
|
|
105
|
-
interface CircuitBreaker {
|
|
106
|
-
/**
|
|
107
|
-
* Execute an operation with circuit breaker protection.
|
|
108
|
-
* Throws CircuitOpenError if the circuit is open.
|
|
109
|
-
*
|
|
110
|
-
* @param operation - The operation to execute
|
|
111
|
-
* @param options - Optional name for logging/metrics
|
|
112
|
-
* @returns The operation result
|
|
113
|
-
* @throws CircuitOpenError if circuit is open
|
|
114
|
-
*/
|
|
115
|
-
execute<T>(operation: () => T | Promise<T>, options?: {
|
|
116
|
-
name?: string;
|
|
117
|
-
}): Promise<T>;
|
|
118
|
-
/**
|
|
119
|
-
* Execute a Result-returning operation with circuit breaker protection.
|
|
120
|
-
* Returns a CircuitOpenError result instead of throwing.
|
|
121
|
-
*
|
|
122
|
-
* @param operation - The operation returning a Result
|
|
123
|
-
* @param options - Optional name for logging/metrics
|
|
124
|
-
* @returns Result with the value or CircuitOpenError
|
|
125
|
-
*/
|
|
126
|
-
executeResult<T, E>(operation: () => Result<T, E> | AsyncResult<T, E>, options?: {
|
|
127
|
-
name?: string;
|
|
128
|
-
}): AsyncResult<T, E | CircuitOpenError>;
|
|
129
|
-
/**
|
|
130
|
-
* Get current circuit state.
|
|
131
|
-
*/
|
|
132
|
-
getState(): CircuitState;
|
|
133
|
-
/**
|
|
134
|
-
* Get circuit breaker statistics.
|
|
135
|
-
*/
|
|
136
|
-
getStats(): CircuitBreakerStats;
|
|
137
|
-
/**
|
|
138
|
-
* Manually reset the circuit breaker to CLOSED state.
|
|
139
|
-
*/
|
|
140
|
-
reset(): void;
|
|
141
|
-
/**
|
|
142
|
-
* Manually open the circuit (for testing or manual intervention).
|
|
143
|
-
*/
|
|
144
|
-
forceOpen(): void;
|
|
145
|
-
/**
|
|
146
|
-
* Record a manual success (useful for health checks).
|
|
147
|
-
*/
|
|
148
|
-
recordSuccess(): void;
|
|
149
|
-
/**
|
|
150
|
-
* Record a manual failure (useful for health checks).
|
|
151
|
-
*/
|
|
152
|
-
recordFailure(error?: unknown): void;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Create a circuit breaker instance.
|
|
156
|
-
*
|
|
157
|
-
* @param name - Name for this circuit breaker (used in errors and logging)
|
|
158
|
-
* @param config - Configuration options
|
|
159
|
-
* @returns A CircuitBreaker instance
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* ```typescript
|
|
163
|
-
* const apiBreaker = createCircuitBreaker('external-api', {
|
|
164
|
-
* failureThreshold: 5,
|
|
165
|
-
* resetTimeout: 30000,
|
|
166
|
-
* });
|
|
167
|
-
*
|
|
168
|
-
* // In workflow
|
|
169
|
-
* const data = await apiBreaker.execute(() =>
|
|
170
|
-
* step(() => fetchFromApi(id))
|
|
171
|
-
* );
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
declare function createCircuitBreaker(name: string, config?: Partial<CircuitBreakerConfig>): CircuitBreaker;
|
|
175
|
-
/**
|
|
176
|
-
* Preset configurations for common use cases.
|
|
177
|
-
*/
|
|
178
|
-
declare const circuitBreakerPresets: {
|
|
179
|
-
/**
|
|
180
|
-
* Aggressive circuit breaker for critical paths.
|
|
181
|
-
* Opens quickly (3 failures) and recovers slowly (60s).
|
|
182
|
-
*/
|
|
183
|
-
readonly critical: {
|
|
184
|
-
failureThreshold: number;
|
|
185
|
-
resetTimeout: number;
|
|
186
|
-
windowSize: number;
|
|
187
|
-
halfOpenMax: number;
|
|
188
|
-
};
|
|
189
|
-
/**
|
|
190
|
-
* Standard circuit breaker for typical API calls.
|
|
191
|
-
* Balanced between stability and availability.
|
|
192
|
-
*/
|
|
193
|
-
readonly standard: {
|
|
194
|
-
failureThreshold: number;
|
|
195
|
-
resetTimeout: number;
|
|
196
|
-
windowSize: number;
|
|
197
|
-
halfOpenMax: number;
|
|
198
|
-
};
|
|
199
|
-
/**
|
|
200
|
-
* Lenient circuit breaker for non-critical operations.
|
|
201
|
-
* Opens slowly (10 failures) and recovers quickly (15s).
|
|
202
|
-
*/
|
|
203
|
-
readonly lenient: {
|
|
204
|
-
failureThreshold: number;
|
|
205
|
-
resetTimeout: number;
|
|
206
|
-
windowSize: number;
|
|
207
|
-
halfOpenMax: number;
|
|
208
|
-
};
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
export { type CircuitBreaker, type CircuitBreakerConfig, type CircuitBreakerStats, CircuitOpenError, type CircuitState, circuitBreakerPresets, createCircuitBreaker, isCircuitOpenError };
|
package/dist/circuit-breaker.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
var Ke={"step-require-id":"step-require-id","step-no-immediate-execution":"step-no-immediate-execution","step-require-thunk-for-key":"step-require-thunk-for-key","step-no-bare-await":"step-no-bare-await","step-no-try-catch-wrap":"step-no-try-catch-wrap","step-stable-cache-keys":"step-stable-cache-keys","workflow-no-floating":"workflow-no-floating","workflow-options-position":"workflow-options-position","workflow-callback-shape":"workflow-callback-shape","workflow-no-callable-form":"workflow-no-callable-form","workflow-no-dynamic-import":"workflow-no-dynamic-import","result-no-floating":"result-no-floating","result-require-handling":"result-require-handling","result-no-double-wrap":"result-no-double-wrap","result-no-manual-propagation":"result-no-manual-propagation","result-no-direct-ok-err":"result-no-direct-ok-err","error-check-unexpected-first":"error-check-unexpected-first","error-access-cause":"error-access-cause","error-normalize":"error-normalize","error-no-throw-in-deps":"error-no-throw-in-deps","concurrency-no-promise-all":"concurrency-no-promise-all","concurrency-no-promise-race":"concurrency-no-promise-race","concurrency-no-promise-allsettled":"concurrency-no-promise-allsettled","runtime-step-timeout":"runtime-step-timeout","runtime-step-aborted":"runtime-step-aborted","runtime-retry-exhausted":"runtime-retry-exhausted","runtime-rate-limit":"runtime-rate-limit","runtime-circuit-open":"runtime-circuit-open","runtime-unexpected":"runtime-unexpected","runtime-resolver-not-found":"runtime-resolver-not-found","runtime-saga-compensation":"runtime-saga-compensation"};function ye(t){return`https://jagreehal.github.io/awaitly/rules/#${t}`}var nr=Object.keys(Ke);var oe=class extends Error{_tag};function L(t,e){return class extends oe{_tag=t;constructor(m,w){let h=e?.message?e.message(m??{}):t;if(super(h),this.name=t,e?.slug!==void 0){if(!e.hint)throw new TypeError(`TaggedError: 'hint' is required when 'slug' is set (slug: "${e.slug}")`);Object.defineProperty(this,"code",{value:e.slug,enumerable:!0,writable:!1,configurable:!1}),Object.defineProperty(this,"hint",{value:e.hint,enumerable:!0,writable:!1,configurable:!1}),Object.defineProperty(this,"docsUrl",{value:ye(e.slug),enumerable:!0,writable:!1,configurable:!1})}if(Object.setPrototypeOf(this,new.target.prototype),m&&typeof m=="object"){let c;if(e?.slug!==void 0){let{_tag:F,name:A,message:D,stack:s,code:N,hint:B,docsUrl:U,...j}=m;c=j}else{let{_tag:F,name:A,message:D,stack:s,...N}=m;c=N}let T=Object.prototype.hasOwnProperty.call(c,"cause"),P=T?c.cause:void 0;T&&delete c.cause;let v=w?.cause!==void 0;if(T&&v)throw new TypeError("TaggedError: cannot provide 'cause' in props when also setting ErrorOptions.cause");Object.assign(this,c),T&&(this.cause=P),v&&(this.cause=w?.cause)}else w?.cause!==void 0&&(this.cause=w.cause)}}}Object.defineProperty(L,Symbol.hasInstance,{value:t=>t instanceof oe});(h=>{function t(c){return c instanceof Error}h.isError=t;function e(c){return c instanceof oe}h.isTaggedError=e;function m(c,T){let P=c._tag,v=T[P];return v(c)}h.match=m;function w(c,T,P){let v=c._tag,F=T[v];return F?F(c):P(c)}h.matchPartial=w})(L||={});var Te=class extends L("TimeoutError",{slug:"runtime-step-timeout",hint:"Increase the step's timeout option, or check why the upstream operation is slow.",message:e=>e.operation?`TimeoutError: ${e.operation} timed out after ${e.ms}ms`:`TimeoutError: Operation timed out after ${e.ms}ms`}){},ke=class extends L("RetryExhaustedError",{slug:"runtime-retry-exhausted",hint:"All retry attempts failed. Inspect lastError and decide whether to surface it or compensate.",message:e=>e.operation?`RetryExhaustedError: ${e.operation} failed after ${e.attempts} attempts`:`RetryExhaustedError: Operation failed after ${e.attempts} attempts`}){},Re=class extends L("RateLimitError",{slug:"runtime-rate-limit",hint:"Wait retryAfterMs before retrying, or apply step.cache to deduplicate calls.",message:e=>e.limiterName?`RateLimitError: Rate limit exceeded for ${e.limiterName}${e.retryAfterMs?`, retry after ${e.retryAfterMs}ms`:""}`:`RateLimitError: Rate limit exceeded${e.retryAfterMs?`, retry after ${e.retryAfterMs}ms`:""}`}){},ge=class extends L("CircuitBreakerOpenError",{slug:"runtime-circuit-open",hint:"The circuit is open. Wait for it to half-open or fall back to a degraded path.",message:e=>`CircuitBreakerOpenError: Circuit ${e.circuitName} is ${e.state??"OPEN"}${e.retryAfterMs?`, retry after ${Math.ceil(e.retryAfterMs/1e3)}s`:""}`}){},xe=class extends L("ValidationError",{message:e=>`ValidationError: Invalid ${e.field} - ${e.reason}`}){},Ce=class extends L("NotFoundError",{message:e=>e.id?`NotFoundError: ${e.resource} with id ${e.id} not found`:`NotFoundError: ${e.resource} not found`}){},he=class extends L("UnauthorizedError",{message:e=>e.reason?`UnauthorizedError: ${e.reason}`:e.action&&e.resource?`UnauthorizedError: Not authorized to ${e.action} ${e.resource}`:"UnauthorizedError: Access denied"}){},be=class extends L("NetworkError",{message:e=>e.url?`NetworkError: ${e.reason} (${e.url})`:`NetworkError: ${e.reason}`}){},Ae=class extends L("CompensationError",{slug:"runtime-saga-compensation",hint:"A saga compensation step failed. Inspect compensationError and ensure compensation is idempotent.",message:e=>`CompensationError: Failed to compensate step ${e.step}`}){},ue=class extends L("UnexpectedError",{slug:"runtime-unexpected",hint:"An unexpected exception escaped a step. Inspect cause; consider returning a typed Result instead of throwing.",message:e=>`UnexpectedError: ${e.cause instanceof Error?e.cause.message:String(e.cause??"unknown")}`}){};function Se(t){return{ok:!0,value:t}}var Fe=t=>typeof t=="object"&&t!==null&&"ok"in t&&typeof t.ok=="boolean"&&(t.ok?"value"in t:"error"in t),Pe=(t,e)=>{let m={},w=new Map;for(let h of Object.keys(t)){let c=t[h];typeof c=="function"&&(m[h]=(...T)=>{let P=(w.get(h)??0)+1;w.set(h,P);let v=P===1?h:`${h}#${P}`;return e(v,async()=>{let F=await c(...T);return Fe(F)?F:Se(F)})})}return m};function je(t){let e=t.trim().match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)$/i);if(!e)return;let m=parseFloat(e[1]),w=e[2].toLowerCase();return{_tag:"Duration",millis:m*({ms:1,s:1e3,m:6e4,h:36e5,d:864e5}[w]??1)}}function Be(t){return new ue({cause:t})}function W(t){return{ok:!0,value:t}}function K(t,e){let m=e?.cause;return{ok:!1,error:t,...m!==void 0?{cause:m}:{}}}function Le(t){if(t==null)return"unknown";if(typeof t=="string")return t.trim()||"unknown";if(typeof t=="object"){let e=t;if(typeof e._tag=="string"){let m=e._tag.trim();if(m)return m}if(typeof e.tag=="string"){let m=e.tag.trim();if(m)return m}if(typeof e.code=="string"){let m=e.code.trim();if(m)return m}else if(typeof e.code=="number")return String(e.code);if(t instanceof Error&&t.name){let m=t.name.trim();if(m)return m}}return"unknown"}function Ve(t,e){if(!(!e||!t))return e[t]}function He(t){let{intent:e,domain:m,owner:w,tags:h,stateChanges:c,emits:T,calls:P}=t;if(!e&&!m&&!w&&!h?.length&&!c?.length&&!T?.length&&!P?.length)return;let v={};return e&&(v.intent=e),m&&(v.domain=m),w&&(v.owner=w),h?.length&&(v.tags=h),c?.length&&(v.stateChanges=c),T?.length&&(v.emits=T),P?.length&&(v.calls=P),v}function H(t,e,m,w,h){let c=Le(t),T=Ve(c,e),P={tag:c,origin:m};return T!==void 0&&(P.classification=T),w!==void 0&&(P.attempt=w),h!==void 0&&(P.cumulativeDurationMs=h),P}var te=Symbol.for("step_timeout_marker");function Oe(t){return typeof t!="object"||t===null?!1:t.type==="STEP_TIMEOUT"?!0:te in t}function $e(t){if(!(typeof t!="object"||t===null)){if(t.type==="STEP_TIMEOUT"){let e=t;return{timeoutMs:e.timeoutMs,stepName:e.stepName,stepKey:e.stepKey,attempt:e.attempt}}if(te in t)return t[te]}}var Me=Symbol("early-exit");function We(t,e){return{[Me]:!0,error:t,meta:e}}function qe(t){return typeof t=="object"&&t!==null&&t[Me]===!0}var Ie=Symbol("mapper-exception");function ee(t){return{[Ie]:!0,thrown:t}}function Ye(t){return typeof t=="object"&&t!==null&&t[Ie]===!0}function me(t,e){let{backoff:m,initialDelay:w,maxDelay:h,jitter:c}=e,T;switch(m){case"fixed":T=w;break;case"linear":T=w*t;break;case"exponential":T=w*Math.pow(2,t-1);break}if(T=Math.min(T,h),c){let P=T*.25*Math.random();T=T+P}return Math.floor(T)}function fe(t){return new Promise(e=>setTimeout(e,t))}var ve=Symbol("timeout"),ie=Symbol("timeout-option");function ze(t){return typeof t=="object"&&t!==null&&t[ie]===!0}async function Je(t,e,m,w){let h=new AbortController,c=e.onTimeout??"error",T=()=>typeof c=="function"?c({name:m.name,key:m.key,ms:e.ms}):e.error??{type:"STEP_TIMEOUT",stepName:m.name,stepKey:m.key,timeoutMs:e.ms,attempt:m.attempt},P;w?.aborted&&h.abort(w.reason);let v;w&&!w.aborted&&(v=()=>h.abort(w.reason),w.addEventListener("abort",v,{once:!0}));let F=new Promise((D,s)=>{P=setTimeout(()=>{if(c!=="disconnect"&&h.abort(),c==="option"){s({[ie]:!0,ms:e.ms});return}s({[ve]:!0,error:T()})},e.ms)}),A;e.signal?A=Promise.resolve(t(h.signal)):A=Promise.resolve(t());try{return await Promise.race([A,F])}catch(D){if(typeof D=="object"&&D!==null&&D[ie]===!0)throw{[ie]:!0,ms:e.ms};if(typeof D=="object"&&D!==null&&D[ve]===!0){c==="disconnect"&&A.catch(()=>{});let s=D.error;if(typeof s=="object"&&s!==null&&s.type!=="STEP_TIMEOUT"){let N={timeoutMs:e.ms,stepName:m.name,stepKey:m.key,attempt:m.attempt};te in s?s[te]=N:Object.defineProperty(s,te,{value:N,enumerable:!1,writable:!0,configurable:!1})}throw s}throw D}finally{clearTimeout(P),v&&w&&w.removeEventListener("abort",v)}}var re={backoff:"exponential",initialDelay:100,maxDelay:3e4,jitter:!0,shouldRetry:()=>!0,onRetry:()=>{}};async function we(t,e,m){if(typeof t!="function"){let p=t,V=e;if(typeof V!="function")throw new TypeError("[awaitly] run(deps, fn) requires a callback as the second argument. Example: run({ getUser }, async (s) => s.getUser(id))");return we(({step:Z})=>V(Pe(p,Z),{step:Z}),m)}let w=t,h=e,{onError:c,onEvent:T,catchUnexpected:P,workflowId:v,workflowName:F,context:A,_workflowSignal:D}=h&&typeof h=="object"?h:{},s=v??crypto.randomUUID(),N=P??Be,B=[],U=0,j=p=>p??`step_${++U}`,u=p=>{let V=p.context!==void 0||A===void 0?p:{...p,context:A},q=F!==void 0&&V.workflowName===void 0?{...V,workflowName:F}:V;if(q.type==="step_success"){let Z=q.stepId;for(let ae=B.length-1;ae>=0;ae--){let $=B[ae];if($.type==="race"&&!$.winnerId){$.winnerId=Z;break}}}T?.(q,A)},_=We,X=p=>qe(p),z=(p,V)=>p,De=p=>typeof p=="function"?!1:!!(p&&typeof p=="object"&&"ok"in p||p&&typeof p=="object"&&"then"in p&&typeof p.then=="function");try{let V=function(a){let E={};for(let[n,o]of Object.entries(a))if(typeof o=="function")E[n]=o;else if(o&&typeof o=="object"&&"fn"in o)E[n]=o.fn;else throw new TypeError(`step.all: operation "${n}" must be a function or { fn, errors? } object`);return E},q=function(a,E){let n=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let o=performance.now(),r=!1;B.push({scopeId:n,type:"parallel"});let i=()=>{if(r)return;r=!0;let l=B.findIndex(d=>d.scopeId===n);l!==-1&&B.splice(l,1),u({type:"scope_end",workflowId:s,scopeId:n,ts:Date.now(),durationMs:performance.now()-o})};u({type:"scope_start",workflowId:s,scopeId:n,scopeType:"parallel",name:a,ts:Date.now()});try{let l=await E();if(i(),!l.ok)throw c?.(l.error,a,A),_(l.error,{origin:"result",resultCause:l.cause});return l.value}catch(l){throw i(),l}})()},Z=function(a,E){let n=Object.keys(a),o=E.name??`Parallel(${n.join(", ")})`,r=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let i=performance.now(),l=!1;B.push({scopeId:r,type:"parallel"});let d=()=>{if(l)return;l=!0;let f=B.findIndex(y=>y.scopeId===r);f!==-1&&B.splice(f,1),u({type:"scope_end",workflowId:s,scopeId:r,ts:Date.now(),durationMs:performance.now()-i})};u({type:"scope_start",workflowId:s,scopeId:r,scopeType:"parallel",name:o,ts:Date.now()});try{let f=await new Promise(R=>{if(n.length===0){R([]);return}let S=!1,I=n.length,g=new Array(n.length);for(let M=0;M<n.length;M++){let x=n[M],b=M;Promise.resolve(a[x]()).catch(C=>K({type:"PROMISE_REJECTED",cause:C},{cause:{type:"PROMISE_REJECTION",reason:C}})).then(C=>{if(!S){if(!C.ok){S=!0,R([{key:x,result:C}]);return}g[b]={key:x,result:C},I--,I===0&&R(g)}})}});d();let y={};for(let{key:R,result:S}of f){if(!S.ok)throw c?.(S.error,R,A),_(S.error,{origin:"result",resultCause:S.cause});y[R]=S.value}return y}catch(f){throw d(),f}})()};var er=V,rr=q,tr=Z;let p=(a,E,n)=>(async()=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step() requires an explicit string ID as the first argument. Example: step("fetchUser", () => fetchUser(id))');let o=n??{},r=He(o),i=a,l=o.key??a,d=o.key??a,{description:f,retry:y,timeout:R}=o,S=j(l),I=T,g=I?performance.now():0,x=De(E)?()=>E:E,C={attempts:Math.max(1,y?.attempts??1),backoff:y?.backoff??re.backoff,initialDelay:y?.initialDelay??re.initialDelay,maxDelay:y?.maxDelay??re.maxDelay,jitter:y?.jitter??re.jitter,shouldRetry:y?.shouldRetry??re.shouldRetry,onRetry:y?.onRetry??re.onRetry};T&&u({type:"step_start",workflowId:s,stepId:S,stepKey:l,name:i,description:f,ts:Date.now(),...r&&{metadata:r}});let Q;for(let O=1;O<=C.attempts;O++){let Ue=I?performance.now():0;try{let k;if(R?k=await Je(x,R,{name:i,key:l,attempt:O},D):k=await x(),k.ok){let G=performance.now()-g;return u({type:"step_success",workflowId:s,stepId:S,stepKey:l,name:i,description:f,ts:Date.now(),durationMs:G,...r&&{metadata:r}}),d&&u({type:"step_complete",workflowId:s,stepKey:d,name:i,description:f,ts:Date.now(),durationMs:G,result:k,...r&&{metadata:r}}),k.value}if(Q=k,O<C.attempts&&C.shouldRetry(k.error,O)){let G=me(O,C);u({type:"step_retry",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),attempt:O+1,maxAttempts:C.attempts,delayMs:G,error:k.error,...r&&{metadata:r},diagnostics:H(k.error,o.errorMeta,"result",O,performance.now()-g)}),C.onRetry(k.error,O,G),await fe(G);continue}C.attempts>1&&u({type:"step_retries_exhausted",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),durationMs:performance.now()-g,attempts:O,lastError:k.error,...r&&{metadata:r},diagnostics:H(k.error,o.errorMeta,"result",O,performance.now()-g)});break}catch(k){let G=performance.now()-Ue;if(ze(k)){let Y=k.ms;u({type:"step_timeout",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),timeoutMs:Y,attempt:O,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"timeout",O)}),u({type:"step_success",workflowId:s,stepId:S,stepKey:l,name:i,description:f,ts:Date.now(),durationMs:performance.now()-g,...r&&{metadata:r}}),d&&u({type:"step_complete",workflowId:s,stepKey:d,name:i,description:f,ts:Date.now(),durationMs:performance.now()-g,result:W(void 0),...r&&{metadata:r}});return}if(X(k))throw u({type:"step_aborted",workflowId:s,stepId:S,stepKey:l,name:i,description:f,ts:Date.now(),durationMs:G,...r&&{metadata:r}}),k;if(Oe(k)){let Y=$e(k),Ne=R?.ms??Y?.timeoutMs??0;if(u({type:"step_timeout",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),timeoutMs:Ne,attempt:O,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"timeout",O)}),O<C.attempts&&C.shouldRetry(k,O)){let de=me(O,C);u({type:"step_retry",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),attempt:O+1,maxAttempts:C.attempts,delayMs:de,error:k,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"timeout",O,performance.now()-g)}),C.onRetry(k,O,de),await fe(de);continue}C.attempts>1&&u({type:"step_retries_exhausted",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),durationMs:performance.now()-g,attempts:O,lastError:k,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"timeout",O,performance.now()-g)});let Ee=performance.now()-g;throw u({type:"step_error",workflowId:s,stepId:S,stepKey:l,name:i,description:f,ts:Date.now(),durationMs:Ee,error:k,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"timeout",O,Ee)}),d&&u({type:"step_complete",workflowId:s,stepKey:d,name:i,description:f,ts:Date.now(),durationMs:Ee,result:K(k,{cause:k}),meta:{origin:"throw",thrown:k},...r&&{metadata:r}}),c?.(k,i,A),_(k,{origin:"throw",thrown:k})}if(O<C.attempts&&C.shouldRetry(k,O)){let Y=me(O,C);u({type:"step_retry",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),attempt:O+1,maxAttempts:C.attempts,delayMs:Y,error:k,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"throw",O,performance.now()-g)}),C.onRetry(k,O,Y),await fe(Y);continue}C.attempts>1&&!Oe(k)&&u({type:"step_retries_exhausted",workflowId:s,stepId:S,stepKey:l,name:i,ts:Date.now(),durationMs:performance.now()-g,attempts:O,lastError:k,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"throw",O,performance.now()-g)});let pe=performance.now()-g,ne;try{ne=N(k)}catch(Y){throw ee(Y)}throw u({type:"step_error",workflowId:s,stepId:S,stepKey:l,name:i,description:f,ts:Date.now(),durationMs:pe,error:ne,...r&&{metadata:r},diagnostics:H(k,o.errorMeta,"throw",O,pe)}),d&&u({type:"step_complete",workflowId:s,stepKey:d,name:i,description:f,ts:Date.now(),durationMs:pe,result:K(ne,{cause:k}),meta:{origin:"throw",thrown:k},...r&&{metadata:r}}),c?.(ne,i,A),_(ne,{origin:"throw",thrown:k})}}let J=Q,ce=performance.now()-g,le=z(J.error,{origin:"result",resultCause:J.cause});throw u({type:"step_error",workflowId:s,stepId:S,stepKey:l,name:i,description:f,ts:Date.now(),durationMs:ce,error:le,...r&&{metadata:r},diagnostics:H(J.error,o.errorMeta,"result",C.attempts,ce)}),d&&u({type:"step_complete",workflowId:s,stepKey:d,name:i,description:f,ts:Date.now(),durationMs:ce,result:J,meta:{origin:"result",resultCause:J.cause},...r&&{metadata:r}}),c?.(le,i,A),_(le,{origin:"result",resultCause:J.cause})})();p.try=(a,E,n)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.try() requires an explicit string ID as the first argument. Example: step.try("parse", () => JSON.parse(str), { error: "PARSE_ERROR" })');let o="error"in n?()=>n.error:n.onError;if(n.retry||n.timeout)return p.retry(a,async()=>{try{return W(await E())}catch(f){return K(o(f),{cause:f})}},{attempts:n.retry?.attempts??1,...n.retry??{},key:n.key,timeout:n.timeout});let r=n.key??a,i=a,l=a,d=T;return(async()=>{let f=d?performance.now():0;T&&u({type:"step_start",workflowId:s,stepId:l,stepKey:r,name:i,ts:Date.now()});try{let y=await E(),R=performance.now()-f;return u({type:"step_success",workflowId:s,stepId:l,stepKey:r,name:i,ts:Date.now(),durationMs:R}),r&&u({type:"step_complete",workflowId:s,stepKey:r,name:i,ts:Date.now(),durationMs:R,result:W(y)}),y}catch(y){let R=o(y),S=performance.now()-f,I=z(R,{origin:"throw",thrown:y});throw u({type:"step_error",workflowId:s,stepId:l,stepKey:r,name:i,ts:Date.now(),durationMs:S,error:I}),r&&u({type:"step_complete",workflowId:s,stepKey:r,name:i,ts:Date.now(),durationMs:S,result:K(R,{cause:y}),meta:{origin:"throw",thrown:y}}),c?.(I,i,A),_(I,{origin:"throw",thrown:y})}})()},p.fromResult=(a,E,n)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.fromResult() requires an explicit string ID as the first argument. Example: step.fromResult("callProvider", () => callProvider(input), { onError: (e) => ({ type: "FAILED" }) })');let o=n.key??a,r=a,i=a,l="error"in n?()=>n.error:n.onError,d=T;return(async()=>{let f=d?performance.now():0;T&&u({type:"step_start",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now()});let y=await E();if(y.ok){let R=performance.now()-f;return u({type:"step_success",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:R}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:R,result:W(y.value)}),y.value}else{let R=l(y.error),S=performance.now()-f,I=z(R,{origin:"result",resultCause:y.error});throw u({type:"step_error",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:S,error:I}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:S,result:K(R,{cause:y.error}),meta:{origin:"result",resultCause:y.error}}),c?.(I,r,A),_(I,{origin:"result",resultCause:y.error})}})()},p.fromNullable=(a,E,n,o)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.fromNullable() requires an explicit string ID as the first argument. Example: step.fromNullable("getUser", () => db.find(id), () => ({ type: "NOT_FOUND" }))');return p(a,async()=>{let r=await E();return r!=null?W(r):K(n())},o)},p.retry=(a,E,n)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.retry() requires an explicit string ID as the first argument. Example: step.retry("fetchData", () => fetchData(), { attempts: 3 })');return p(a,E,{key:n.key??a,retry:{attempts:n.attempts,backoff:n.backoff,initialDelay:n.initialDelay,maxDelay:n.maxDelay,jitter:n.jitter,shouldRetry:n.shouldRetry,onRetry:n.onRetry},timeout:n.timeout})},p.withTimeout=(a,E,n)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.withTimeout() requires an explicit string ID as the first argument. Example: step.withTimeout("slowOp", () => slowOp(), { ms: 5000 })');return p(a,E,{key:n.key??a,timeout:n})},p.sleep=(a,E,n)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.sleep() requires an explicit string ID as the first argument. Example: step.sleep("delay", "5s")');let o=typeof E=="string"?je(E):E;if(!o)throw new Error(`step.sleep: invalid duration '${E}'`);let r=o.millis,i=n?.signal;return p(a,async()=>{if(D?.aborted||i?.aborted){let l=new Error("Sleep aborted");throw l.name="AbortError",l}return new Promise((l,d)=>{let f={timeoutId:void 0},y=()=>{f.timeoutId&&clearTimeout(f.timeoutId);let R=new Error("Sleep aborted");R.name="AbortError",d(R)};D?.addEventListener("abort",y,{once:!0}),i?.addEventListener("abort",y,{once:!0}),f.timeoutId=setTimeout(()=>{D?.removeEventListener("abort",y),i?.removeEventListener("abort",y),l(W(void 0))},r)})},{key:n?.key??a,description:n?.description})},p.all=((...a)=>{if(typeof a[0]!="string")throw new TypeError("step.all(name, ...): first argument must be a string (step name). Example: step.all('Fetch data', { user: () => fetchUser(), posts: () => fetchPosts() })");let E=a[0],n=a[1];if(typeof n=="function")return q(E,n);if(n&&typeof n=="object"&&!Array.isArray(n)){let r=V(n);return Z(r,{name:E})}throw new TypeError("step.all(name, ...): second argument must be a function (array form) or an object of operations (object form).")}),p.race=(a,E)=>{let n=`scope_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return(async()=>{let o=performance.now(),r=!1,i={scopeId:n,type:"race",winnerId:void 0};B.push(i);let l=()=>{if(r)return;r=!0;let d=B.findIndex(f=>f.scopeId===n);d!==-1&&B.splice(d,1),u({type:"scope_end",workflowId:s,scopeId:n,ts:Date.now(),durationMs:performance.now()-o,winnerId:i.winnerId})};u({type:"scope_start",workflowId:s,scopeId:n,scopeType:"race",name:a,ts:Date.now()});try{let d=await E();if(l(),!d.ok)throw c?.(d.error,a,A),_(d.error,{origin:"result",resultCause:d.cause});return d.value}catch(d){throw l(),d}})()},p.if=(a,E,n)=>n(),p.label=p.if,p.branch=async(a,E)=>{let{condition:n,then:o,else:r}=E;if(n())return await o();if(r)return await r()},p.arm=(a,E)=>({fn:a,errors:E}),p.forEach=async(a,E,n)=>{let o=[],r=n.maxIterations,i=0,l="run"in n,d=Symbol.asyncIterator in E?E:(async function*(){yield*E})();for await(let f of d){if(r!==void 0&&i>=r)break;let y;l?y=await n.run(f,i):y=await n.item.handler(f,i,p),o.push(y),i++}return o},p.item=a=>({__forEachItemHandler:!0,handler:a}),p.dep=(a,E)=>E,p.workflow=(a,E,n)=>p(a,E,n),p.map=async(a,E,n,o)=>{let r=o?.concurrency??E.length;return p(a,()=>r>=E.length?_e(E.map((i,l)=>n(i,l))):(async()=>{let i=[];for(let l=0;l<E.length;l+=r){let d=E.slice(l,l+r),f=await _e(d.map((y,R)=>n(y,l+R)));if(!f.ok)return f;i.push(...f.value)}return W(i)})(),{key:o?.key})},p.withFallback=(a,E,n)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.withFallback() requires an explicit string ID as the first argument. Example: step.withFallback("getUser", () => fetchUser(id), { fallback: () => fetchFromCache(id) })');let o=n.key??a,r=a,i=j(o),l=T;return(async()=>{let d=l?performance.now():0;T&&u({type:"step_start",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now()});let f;try{f=await E()}catch(g){if(X(g))throw u({type:"step_aborted",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:performance.now()-d}),g;let M;try{M=N(g)}catch(b){throw ee(b)}if(n.on!==void 0&&n.on!==M){let b=performance.now()-d;throw u({type:"step_error",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:b,error:M}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:b,result:K(M,{cause:g}),meta:{origin:"throw",thrown:g}}),c?.(M,r,A),_(M,{origin:"throw",thrown:g})}let x;try{x=await n.fallback()}catch(b){if(X(b))throw u({type:"step_aborted",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:performance.now()-d}),b;let C;try{C=N(b)}catch(J){throw ee(J)}let Q=performance.now()-d;throw u({type:"step_error",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:Q,error:C}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:Q,result:K(C,{cause:b}),meta:{origin:"throw",thrown:b}}),c?.(C,r,A),_(C,{origin:"throw",thrown:b})}if(x.ok){let b=performance.now()-d;return u({type:"step_success",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:b}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:b,result:x,meta:{origin:"fallback",fallbackUsed:!0,fallbackReason:String(M)}}),x.value}else{let b=performance.now()-d,C=z(x.error,{origin:"result",resultCause:x.cause});throw u({type:"step_error",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:b,error:C}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:b,result:x,meta:{origin:"result",resultCause:x.cause}}),c?.(C,r,A),_(C,{origin:"result",resultCause:x.cause})}}if(f.ok){let g=performance.now()-d;return u({type:"step_success",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:g}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:g,result:f}),f.value}let y=f.error;if(n.on!==void 0&&n.on!==y){let g=performance.now()-d,M=z(y,{origin:"result",resultCause:f.cause});throw u({type:"step_error",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:g,error:M}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:g,result:f,meta:{origin:"result",resultCause:f.cause}}),c?.(M,r,A),_(M,{origin:"result",resultCause:f.cause})}let R;try{R=await n.fallback()}catch(g){if(X(g))throw u({type:"step_aborted",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:performance.now()-d}),g;let M;try{M=N(g)}catch(b){throw ee(b)}let x=performance.now()-d;throw u({type:"step_error",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:x,error:M}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:x,result:K(M,{cause:g}),meta:{origin:"throw",thrown:g}}),c?.(M,r,A),_(M,{origin:"throw",thrown:g})}if(R.ok){let g=performance.now()-d;return u({type:"step_success",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:g}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:g,result:R,meta:{origin:"fallback",fallbackUsed:!0,fallbackReason:String(y)}}),R.value}let S=performance.now()-d,I=z(R.error,{origin:"result",resultCause:R.cause});throw u({type:"step_error",workflowId:s,stepId:i,stepKey:o,name:r,ts:Date.now(),durationMs:S,error:I}),o&&u({type:"step_complete",workflowId:s,stepKey:o,name:r,ts:Date.now(),durationMs:S,result:R,meta:{origin:"result",resultCause:R.cause}}),c?.(I,r,A),_(I,{origin:"result",resultCause:R.cause})})()},p.withResource=(a,E)=>{if(typeof a!="string"||a.length===0)throw new Error('[awaitly] step.withResource() requires an explicit string ID as the first argument. Example: step.withResource("useDb", { acquire: () => connect(), use: (db) => query(db), release: (db) => db.close() })');let n=a,o=a,r=j(n),i=T;return(async()=>{let l=i?performance.now():0;T&&u({type:"step_start",workflowId:s,stepId:r,stepKey:n,name:o,ts:Date.now()});let d;try{d=await E.acquire()}catch(x){if(X(x))throw u({type:"step_aborted",workflowId:s,stepId:r,stepKey:n,name:o,ts:Date.now(),durationMs:performance.now()-l}),x;let b;try{b=N(x)}catch(Q){throw ee(Q)}let C=performance.now()-l;throw u({type:"step_error",workflowId:s,stepId:r,stepKey:n,name:o,ts:Date.now(),durationMs:C,error:b}),n&&u({type:"step_complete",workflowId:s,stepKey:n,name:o,ts:Date.now(),durationMs:C,result:K(b,{cause:x}),meta:{origin:"throw",thrown:x}}),c?.(b,o,A),_(b,{origin:"throw",thrown:x})}if(!d.ok){let x=performance.now()-l,b=z(d.error,{origin:"result",resultCause:d.cause});throw u({type:"step_error",workflowId:s,stepId:r,stepKey:n,name:o,ts:Date.now(),durationMs:x,error:b}),n&&u({type:"step_complete",workflowId:s,stepKey:n,name:o,ts:Date.now(),durationMs:x,result:d,meta:{origin:"result",resultCause:d.cause}}),c?.(b,o,A),_(b,{origin:"result",resultCause:d.cause})}let f=d.value,y,R,S=!1;try{y=await E.use(f)}catch(x){if(X(x)){try{await E.release(f)}catch(b){console.warn(`[awaitly] step.withResource("${a}"): release threw after earlyExit:`,b)}throw x}R=x,S=!0}try{await E.release(f)}catch(x){console.warn(`[awaitly] step.withResource("${a}"): release threw:`,x)}if(S){let x;try{x=N(R)}catch(C){throw ee(C)}let b=performance.now()-l;throw u({type:"step_error",workflowId:s,stepId:r,stepKey:n,name:o,ts:Date.now(),durationMs:b,error:x}),n&&u({type:"step_complete",workflowId:s,stepKey:n,name:o,ts:Date.now(),durationMs:b,result:K(x,{cause:R}),meta:{origin:"throw",thrown:R}}),c?.(x,o,A),_(x,{origin:"throw",thrown:R})}let I=y;if(I.ok){let x=performance.now()-l;return u({type:"step_success",workflowId:s,stepId:r,stepKey:n,name:o,ts:Date.now(),durationMs:x}),n&&u({type:"step_complete",workflowId:s,stepKey:n,name:o,ts:Date.now(),durationMs:x,result:I}),I.value}let g=performance.now()-l,M=z(I.error,{origin:"result",resultCause:I.cause});throw u({type:"step_error",workflowId:s,stepId:r,stepKey:n,name:o,ts:Date.now(),durationMs:g,error:M}),n&&u({type:"step_complete",workflowId:s,stepKey:n,name:o,ts:Date.now(),durationMs:g,result:I,meta:{origin:"result",resultCause:I.cause}}),c?.(M,o,A),_(M,{origin:"result",resultCause:I.cause})})()};let $=await w({step:p});if(process.env.NODE_ENV!=="production"&&$!==null&&typeof $=="object"&&"ok"in $&&typeof $.ok=="boolean"){let a=$;(a.ok===!0&&"value"in a||a.ok===!1&&"error"in a)&&console.warn(`awaitly: Workflow executor returned a Result-like object. Return raw values, not ok() or err().
|
|
2
|
-
|
|
3
|
-
Incorrect: return ok({ data });
|
|
4
|
-
Correct: return { data };
|
|
5
|
-
|
|
6
|
-
See: https://jagreehal.github.io/awaitly/guides/troubleshooting/#returning-ok-from-workflow-executor-double-wrapping`)}return W($)}catch(p){if(Ye(p))throw p.thrown;if(X(p)){let q=p.meta.origin==="throw"?p.meta.thrown:p.meta.origin==="result"?p.meta.resultCause:void 0;return K(p.error,{cause:q})}let V=N(p);return c?.(V,"unexpected",A),K(V,{cause:p})}}we.strict=(t,e)=>we(t,e);async function _e(t){return t.length===0?W([]):new Promise(e=>{let m=!1,w=t.length,h=new Array(t.length);for(let c=0;c<t.length;c++){let T=c;Promise.resolve(t[T]).catch(P=>K({type:"PROMISE_REJECTED",cause:P},{cause:{type:"PROMISE_REJECTION",reason:P}})).then(P=>{if(!m){if(!P.ok){m=!0,e(P);return}h[T]=P.value,w--,w===0&&e(W(h))}})}})}var se=class extends Error{type="CIRCUIT_OPEN";circuitName;state;retryAfterMs;constructor(e){super(e.message??`Circuit breaker "${e.circuitName}" is ${e.state}. Retry after ${Math.ceil(e.retryAfterMs/1e3)}s`),this.name="CircuitOpenError",this.circuitName=e.circuitName,this.state=e.state,this.retryAfterMs=e.retryAfterMs}};function Ge(t){return typeof t=="object"&&t!==null&&t.type==="CIRCUIT_OPEN"}var Xe={failureThreshold:5,resetTimeout:3e4,windowSize:6e4,halfOpenMax:3};function Ze(t,e){let m={...Xe,...e},w="CLOSED",h=[],c=null,T=null,P=0,v=0;function F(){let U=Date.now();h=h.filter(j=>U-j.timestamp<m.windowSize)}function A(U){if(w!==U){let j=w;w=U,U==="HALF_OPEN"&&(v=0),m.onStateChange?.(j,U,t)}}function D(){return w!=="OPEN"||c===null?!1:Date.now()-c>=m.resetTimeout?(A("HALF_OPEN"),!0):!1}function s(){T=Date.now(),P++,w==="HALF_OPEN"&&(v++,v>=m.halfOpenMax&&(A("CLOSED"),h=[]))}function N(U){let j=Date.now();c=j,F(),h.push({timestamp:j,error:U}),(w==="HALF_OPEN"||w==="CLOSED"&&h.length>=m.failureThreshold)&&A("OPEN")}function B(){if(w==="CLOSED")return 0;if(w==="OPEN"){if(D())return 0;let U=Date.now(),j=c?U-c:0;return Math.max(0,m.resetTimeout-j)}return 0}return{async execute(U,j){let u=B();if(u>0)throw new se({circuitName:t,state:w,retryAfterMs:u});try{let _=await U();return s(),_}catch(_){throw N(_),_}},async executeResult(U,j){let u=B();if(u>0)return K(new se({circuitName:t,state:w,retryAfterMs:u}));try{let _=await U();return _.ok?s():N(_.error),_}catch(_){throw N(_),_}},getState(){return w==="OPEN"&&D(),w},getStats(){return F(),{state:this.getState(),failureCount:h.length,successCount:P,lastFailureTime:c,lastSuccessTime:T,halfOpenSuccesses:v}},reset(){A("CLOSED"),h=[],v=0},forceOpen(){c=Date.now(),A("OPEN")},recordSuccess(){s()},recordFailure(U){N(U??new Error("Manual failure"))}}}var Qe={critical:{failureThreshold:3,resetTimeout:6e4,windowSize:3e4,halfOpenMax:1},standard:{failureThreshold:5,resetTimeout:3e4,windowSize:6e4,halfOpenMax:3},lenient:{failureThreshold:10,resetTimeout:15e3,windowSize:12e4,halfOpenMax:5}};export{se as CircuitOpenError,Qe as circuitBreakerPresets,Ze as createCircuitBreaker,Ge as isCircuitOpenError};
|
|
7
|
-
//# sourceMappingURL=circuit-breaker.js.map
|