actly 1.1.5 → 1.2.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.
Files changed (119) hide show
  1. package/README.md +232 -434
  2. package/dist/core/act.cjs +353 -35
  3. package/dist/core/act.d.ts.map +1 -1
  4. package/dist/core/act.js +355 -37
  5. package/dist/core/act.js.map +1 -1
  6. package/dist/core/executor.cjs +2 -0
  7. package/dist/core/executor.d.ts +6 -1
  8. package/dist/core/executor.d.ts.map +1 -1
  9. package/dist/core/executor.js +2 -0
  10. package/dist/core/executor.js.map +1 -1
  11. package/dist/core/health.cjs +34 -0
  12. package/dist/core/health.d.ts +18 -0
  13. package/dist/core/health.d.ts.map +1 -0
  14. package/dist/core/health.js +28 -0
  15. package/dist/core/health.js.map +1 -0
  16. package/dist/core/shutdown.cjs +60 -0
  17. package/dist/core/shutdown.d.ts +8 -0
  18. package/dist/core/shutdown.d.ts.map +1 -0
  19. package/dist/core/shutdown.js +56 -0
  20. package/dist/core/shutdown.js.map +1 -0
  21. package/dist/core/tenant.cjs +71 -0
  22. package/dist/core/tenant.d.ts +29 -0
  23. package/dist/core/tenant.d.ts.map +1 -0
  24. package/dist/core/tenant.js +68 -0
  25. package/dist/core/tenant.js.map +1 -0
  26. package/dist/errors.cjs +182 -0
  27. package/dist/errors.d.ts +151 -0
  28. package/dist/errors.d.ts.map +1 -0
  29. package/dist/errors.js +171 -0
  30. package/dist/errors.js.map +1 -0
  31. package/dist/index.cjs +44 -4
  32. package/dist/index.d.ts +17 -2
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +17 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/observability.cjs +45 -0
  37. package/dist/observability.d.ts +145 -0
  38. package/dist/observability.d.ts.map +1 -0
  39. package/dist/observability.js +43 -0
  40. package/dist/observability.js.map +1 -0
  41. package/dist/policies/bulkhead.cjs +97 -0
  42. package/dist/policies/bulkhead.d.ts +3 -0
  43. package/dist/policies/bulkhead.d.ts.map +1 -0
  44. package/dist/policies/bulkhead.js +95 -0
  45. package/dist/policies/bulkhead.js.map +1 -0
  46. package/dist/policies/cache.cjs +168 -31
  47. package/dist/policies/cache.d.ts +17 -4
  48. package/dist/policies/cache.d.ts.map +1 -1
  49. package/dist/policies/cache.js +168 -31
  50. package/dist/policies/cache.js.map +1 -1
  51. package/dist/policies/circuitBreaker.cjs +85 -0
  52. package/dist/policies/circuitBreaker.d.ts +3 -0
  53. package/dist/policies/circuitBreaker.d.ts.map +1 -0
  54. package/dist/policies/circuitBreaker.js +83 -0
  55. package/dist/policies/circuitBreaker.js.map +1 -0
  56. package/dist/policies/dedupe.cjs +74 -45
  57. package/dist/policies/dedupe.d.ts +10 -28
  58. package/dist/policies/dedupe.d.ts.map +1 -1
  59. package/dist/policies/dedupe.js +74 -45
  60. package/dist/policies/dedupe.js.map +1 -1
  61. package/dist/policies/rateLimit.cjs +35 -0
  62. package/dist/policies/rateLimit.d.ts +3 -0
  63. package/dist/policies/rateLimit.d.ts.map +1 -0
  64. package/dist/policies/rateLimit.js +33 -0
  65. package/dist/policies/rateLimit.js.map +1 -0
  66. package/dist/policies/retry.cjs +45 -8
  67. package/dist/policies/retry.d.ts.map +1 -1
  68. package/dist/policies/retry.js +45 -8
  69. package/dist/policies/retry.js.map +1 -1
  70. package/dist/policies/timeout.cjs +25 -53
  71. package/dist/policies/timeout.d.ts +2 -33
  72. package/dist/policies/timeout.d.ts.map +1 -1
  73. package/dist/policies/timeout.js +31 -48
  74. package/dist/policies/timeout.js.map +1 -1
  75. package/dist/state/store.cjs +3 -3
  76. package/dist/state/store.d.ts +3 -3
  77. package/dist/state/store.js +3 -3
  78. package/dist/stores/memory.cjs +126 -53
  79. package/dist/stores/memory.d.ts +35 -16
  80. package/dist/stores/memory.d.ts.map +1 -1
  81. package/dist/stores/memory.js +125 -53
  82. package/dist/stores/memory.js.map +1 -1
  83. package/dist/types/index.d.ts +176 -3
  84. package/dist/types/index.d.ts.map +1 -1
  85. package/dist/utils/abort.cjs +108 -38
  86. package/dist/utils/abort.d.ts +43 -19
  87. package/dist/utils/abort.d.ts.map +1 -1
  88. package/dist/utils/abort.js +108 -38
  89. package/dist/utils/abort.js.map +1 -1
  90. package/dist/utils/abortPool.cjs +26 -0
  91. package/dist/utils/abortPool.d.ts +4 -0
  92. package/dist/utils/abortPool.d.ts.map +1 -0
  93. package/dist/utils/abortPool.js +22 -0
  94. package/dist/utils/abortPool.js.map +1 -0
  95. package/dist/utils/backoff.cjs +12 -1
  96. package/dist/utils/backoff.d.ts.map +1 -1
  97. package/dist/utils/backoff.js +12 -1
  98. package/dist/utils/backoff.js.map +1 -1
  99. package/dist/utils/key.cjs +77 -0
  100. package/dist/utils/key.d.ts +29 -0
  101. package/dist/utils/key.d.ts.map +1 -0
  102. package/dist/utils/key.js +75 -0
  103. package/dist/utils/key.js.map +1 -0
  104. package/dist/utils/limits.cjs +40 -0
  105. package/dist/utils/limits.d.ts +39 -0
  106. package/dist/utils/limits.d.ts.map +1 -0
  107. package/dist/utils/limits.js +38 -0
  108. package/dist/utils/limits.js.map +1 -0
  109. package/dist/utils/sanitize.cjs +29 -0
  110. package/dist/utils/sanitize.d.ts +3 -0
  111. package/dist/utils/sanitize.d.ts.map +1 -0
  112. package/dist/utils/sanitize.js +26 -0
  113. package/dist/utils/sanitize.js.map +1 -0
  114. package/dist/utils/validate.cjs +90 -16
  115. package/dist/utils/validate.d.ts +11 -0
  116. package/dist/utils/validate.d.ts.map +1 -1
  117. package/dist/utils/validate.js +85 -16
  118. package/dist/utils/validate.js.map +1 -1
  119. package/package.json +6 -5
package/dist/core/act.js CHANGED
@@ -3,19 +3,93 @@ import { retryPolicy } from '../policies/retry.js';
3
3
  import { timeoutPolicy, totalTimeoutPolicy } from '../policies/timeout.js';
4
4
  import { dedupePolicy } from '../policies/dedupe.js';
5
5
  import { cachePolicy } from '../policies/cache.js';
6
- import { InMemoryStore } from '../stores/memory.js';
6
+ import { circuitBreakerPolicy } from '../policies/circuitBreaker.js';
7
+ import { bulkheadPolicy } from '../policies/bulkhead.js';
8
+ import { rateLimitPolicy } from '../policies/rateLimit.js';
9
+ import { createDefaultStore } from '../stores/memory.js';
7
10
  import { isSyncStore } from '../stores/base.js';
8
- import { linkSignal } from '../utils/abort.js';
11
+ import { linkSignal, raceAbort } from '../utils/abort.js';
12
+ import { sanitizeError, sanitizeErrorMessage } from '../utils/sanitize.js';
13
+ import { registerInflight, unregisterInflight, recordError, recordSuccess } from './health.js';
14
+ import { registerDrainable, unregisterDrainable } from './shutdown.js';
9
15
  import { assertKey, assertOptions, } from '../utils/validate.js';
10
16
  // Module-level default store so cache and dedupe persist across calls.
11
- // Always an InMemoryStore (SyncStateStore) required because the default
12
- // chain may include dedupePolicy, which mandates synchronous store access.
13
- // For SSR isolation or per-test control, use `withStore()` or call
14
- // `execute()` directly with an explicit store.
15
- const defaultStore = new InMemoryStore();
17
+ // Bounded by default (maxSize: 10_000, autoCleanup: 60s) to
18
+ // prevent unbounded memory growth in long-running servers. Callers who
19
+ // want truly unbounded storage must construct their own `InMemoryStore`
20
+ // with `maxSize: Infinity` and pass it via `withStore()`.
21
+ const defaultStore = createDefaultStore();
16
22
  // Namespace prefixes used by policies. Kept here (not in policy files) so
17
23
  // `invalidate()` can resolve cache keys without importing policy internals.
18
24
  const CACHE_NS = 'cache:';
25
+ /**
26
+ * Generate a trace ID for correlation across logs/metrics.
27
+ *
28
+ * Uses `crypto.randomUUID()` on Node 20+ (fast, native). Falls back to a
29
+ * timestamp+random string for environments without it.
30
+ */
31
+ function generateTraceId() {
32
+ const crypto = globalThis.crypto;
33
+ if (crypto && typeof crypto.randomUUID === 'function') {
34
+ return crypto.randomUUID();
35
+ }
36
+ return `actly-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
37
+ }
38
+ /**
39
+ * Build the observability context (or return undefined if no hooks).
40
+ * The context is shared via PolicyContext.observability so every policy
41
+ * can emit events through the same traceId + hooks.
42
+ */
43
+ function buildObservability(hooks, traceId) {
44
+ // Contract: if no hooks are supplied, return undefined.
45
+ // Policies check `ctx.observability != null` before allocating events.
46
+ if (!hooks)
47
+ return undefined;
48
+ // Check that at least one hook is actually defined (avoid allocating
49
+ // context for an empty hooks object).
50
+ const hasAnyHook = !!hooks.onAttempt ||
51
+ !!hooks.onRetry ||
52
+ !!hooks.onCacheHit ||
53
+ !!hooks.onCacheMiss ||
54
+ !!hooks.onDedupeJoin ||
55
+ !!hooks.onTimeout ||
56
+ !!hooks.onFinalSuccess ||
57
+ !!hooks.onFinalFailure;
58
+ if (!hasAnyHook)
59
+ return undefined;
60
+ return {
61
+ traceId: traceId ?? generateTraceId(),
62
+ hooks,
63
+ joinerCounter: 0,
64
+ };
65
+ }
66
+ /**
67
+ * Determine the `failedBy` discriminator from a caught error.
68
+ * Name sniffing requires `instanceof Error` to prevent plain-object spoofing.
69
+ */
70
+ function classifyFailure(error) {
71
+ if (error == null || typeof error !== 'object')
72
+ return 'fn-error';
73
+ const code = error.code;
74
+ if (code === 'ACTLY_ABORT')
75
+ return 'abort';
76
+ if (code === 'ACTLY_TIMEOUT')
77
+ return 'timeout';
78
+ if (code === 'ACTLY_TOTAL_TIMEOUT')
79
+ return 'total-timeout';
80
+ if (code === 'ACTLY_RETRY_EXHAUSTED')
81
+ return 'retry-exhausted';
82
+ if (code === 'ACTLY_VALIDATION')
83
+ return 'validation';
84
+ // Fall back to name sniffing for non-actly errors (e.g. DOMException abort).
85
+ // Require instanceof Error to prevent plain-object spoofing.
86
+ if (error instanceof Error) {
87
+ const name = error.name;
88
+ if (name === 'AbortError')
89
+ return 'abort';
90
+ }
91
+ return 'fn-error';
92
+ }
19
93
  /**
20
94
  * Normalise `dedupe: true` shorthand to `DedupeOptions`.
21
95
  * Returns `undefined` if dedupe is disabled or absent.
@@ -39,25 +113,35 @@ function normalizeDedupe(opt) {
39
113
  function buildPolicies(options) {
40
114
  const dedupe = normalizeDedupe(options.dedupe);
41
115
  const policies = [];
42
- // 0. Outermost: hard wall-clock budget over the entire operation.
43
- // If it fires, no inner policy can extend the deadline.
116
+ // Outermost: rate limiter (blocks before any work is done)
117
+ if (options.rateLimit) {
118
+ policies.push(rateLimitPolicy(options.rateLimit));
119
+ }
120
+ // Circuit breaker (blocks if downstream is failing)
121
+ if (options.circuitBreaker) {
122
+ policies.push(circuitBreakerPolicy(options.circuitBreaker));
123
+ }
124
+ // Hard wall-clock budget over the entire operation
44
125
  if (options.totalTimeout && options.totalTimeout.ms > 0) {
45
126
  policies.push(totalTimeoutPolicy(options.totalTimeout));
46
127
  }
47
- // 1. Cache: a hit short-circuits everything below it.
128
+ // Cache: a hit short-circuits everything below it
48
129
  if (options.cache && options.cache.ttl > 0) {
49
130
  policies.push(cachePolicy(options.cache));
50
131
  }
51
- // 2. Dedupe: collapses concurrent callers before retry fires.
132
+ // Bulkhead: limits concurrency per key
133
+ if (options.bulkhead) {
134
+ policies.push(bulkheadPolicy(options.bulkhead));
135
+ }
136
+ // Dedupe: collapses concurrent callers before retry fires
52
137
  if (dedupe) {
53
138
  policies.push(dedupePolicy(dedupe));
54
139
  }
55
- // 3. Retry: owns the attempt loop.
56
- // `attempts: 1` is a no-op — skip to avoid overhead.
140
+ // Retry: owns the attempt loop (attempts: 1 is a no-op — skip)
57
141
  if (options.retry && options.retry.attempts > 1) {
58
142
  policies.push(retryPolicy(options.retry));
59
143
  }
60
- // 4. Innermost: per-attempt clock. Resets on every retry.
144
+ // Innermost: per-attempt clock. Resets on every retry
61
145
  if (options.timeout && options.timeout.ms > 0) {
62
146
  policies.push(timeoutPolicy(options.timeout));
63
147
  }
@@ -74,9 +158,11 @@ function buildPolicies(options) {
74
158
  */
75
159
  function buildRootSignal(userSignal) {
76
160
  const controller = new AbortController();
77
- if (userSignal)
78
- linkSignal(userSignal, controller);
79
- return controller;
161
+ if (userSignal) {
162
+ const unlink = linkSignal(userSignal, controller);
163
+ return { controller, cleanup: unlink };
164
+ }
165
+ return { controller, cleanup: () => { } };
80
166
  }
81
167
  /**
82
168
  * Execute `fn` with the given reliability policies.
@@ -109,34 +195,183 @@ function buildRootSignal(userSignal) {
109
195
  * }
110
196
  */
111
197
  export async function act(key, fn, options = {}) {
112
- // Validate input upfront. Programmer errors throw — they should not be
113
- // swallowed into an ActFailure because the caller's code is broken.
114
198
  assertKey(key);
115
199
  assertOptions(options);
200
+ // Fast path: no options means no policies, no signal, no observability.
201
+ const hasAnyOption = options.retry !== undefined ||
202
+ options.timeout !== undefined ||
203
+ options.totalTimeout !== undefined ||
204
+ options.dedupe !== undefined ||
205
+ options.cache !== undefined ||
206
+ options.signal !== undefined ||
207
+ options.observability !== undefined ||
208
+ options.traceId !== undefined ||
209
+ options.circuitBreaker !== undefined ||
210
+ options.bulkhead !== undefined ||
211
+ options.rateLimit !== undefined ||
212
+ options.hedge !== undefined ||
213
+ options.fallback !== undefined ||
214
+ options.audit !== undefined;
215
+ if (!hasAnyOption) {
216
+ const startedAt = Date.now();
217
+ registerInflight('default');
218
+ registerDrainable('default');
219
+ try {
220
+ const value = await fn(new AbortController().signal);
221
+ recordSuccess('default');
222
+ return { ok: true, value, source: 'fresh', attempts: 1, durationMs: Date.now() - startedAt };
223
+ }
224
+ catch (error) {
225
+ recordError('default', 'fn-error', sanitizeErrorMessage(error));
226
+ return { ok: false, error, attempts: 1, durationMs: Date.now() - startedAt };
227
+ }
228
+ finally {
229
+ unregisterInflight('default');
230
+ unregisterDrainable('default');
231
+ }
232
+ }
116
233
  const meta = { attempts: 1, source: 'fresh' };
117
- const rootController = buildRootSignal(options.signal);
118
- // Fast-fail if the user signal is already aborted. We do this after
119
- // validation so the caller still gets a TypeError for bad options rather
120
- // than a silent abort.
234
+ const { controller: rootController, cleanup } = buildRootSignal(options.signal);
235
+ const observability = buildObservability(options.observability, options.traceId);
236
+ const startedAt = Date.now();
237
+ const scope = 'default';
238
+ registerInflight(scope);
239
+ registerDrainable(scope);
121
240
  if (rootController.signal.aborted) {
122
- return { ok: false, error: rootController.signal.reason, attempts: 0 };
241
+ cleanup();
242
+ unregisterInflight(scope);
243
+ unregisterDrainable(scope);
244
+ const error = rootController.signal.reason;
245
+ if (observability) {
246
+ observability.hooks.onFinalFailure?.({
247
+ type: 'final-failure',
248
+ key, traceId: observability.traceId, timestamp: Date.now(),
249
+ attempts: 0, durationMs: Date.now() - startedAt,
250
+ failedBy: 'abort', error,
251
+ });
252
+ }
253
+ if (options.audit) {
254
+ options.audit.log({ key, traceId: observability?.traceId ?? '', timestamp: Date.now(), durationMs: Date.now() - startedAt, ok: false, attempts: 0, failedBy: 'abort', error });
255
+ }
256
+ recordError(scope, 'ACTLY_ABORT', sanitizeErrorMessage(error));
257
+ return { ok: false, error, attempts: 0, traceId: observability?.traceId, durationMs: Date.now() - startedAt };
123
258
  }
124
259
  const policies = buildPolicies(options);
260
+ const hasRetryPolicy = !!(options.retry && options.retry.attempts > 1);
261
+ if (observability && !hasRetryPolicy) {
262
+ observability.hooks.onAttempt?.({
263
+ type: 'attempt', key, traceId: observability.traceId,
264
+ timestamp: Date.now(), attempt: 1,
265
+ });
266
+ }
267
+ // Wrap fn with hedge request if configured
268
+ const fnWithHedge = options.hedge ? wrapHedge(fn, options.hedge.delayMs) : fn;
125
269
  try {
126
- const value = await execute({
270
+ const value = await raceAbort(execute({
127
271
  key,
128
- fn,
272
+ fn: fnWithHedge,
129
273
  policies,
130
274
  store: defaultStore,
131
275
  meta,
132
276
  signal: rootController.signal,
133
- });
134
- return { ok: true, value, source: meta.source, attempts: meta.attempts };
277
+ observability,
278
+ }), rootController.signal);
279
+ const durationMs = Date.now() - startedAt;
280
+ recordSuccess(scope);
281
+ if (observability) {
282
+ observability.hooks.onFinalSuccess?.({
283
+ type: 'final-success',
284
+ key, traceId: observability.traceId, timestamp: Date.now(),
285
+ source: meta.source, attempts: meta.attempts, durationMs,
286
+ });
287
+ }
288
+ if (options.audit) {
289
+ options.audit.log({ key, traceId: observability?.traceId ?? '', timestamp: Date.now(), durationMs, ok: true, attempts: meta.attempts });
290
+ }
291
+ return { ok: true, value, source: meta.source, attempts: meta.attempts, traceId: observability?.traceId, durationMs };
135
292
  }
136
293
  catch (error) {
137
- return { ok: false, error, attempts: meta.attempts };
294
+ const durationMs = Date.now() - startedAt;
295
+ const failedBy = rootController.signal.aborted ? 'abort' : classifyFailure(error);
296
+ // Fallback: if configured, return fallback value instead of failure.
297
+ // Record the error in health check so monitoring can detect downstream
298
+ // failures even when fallback masks them from the caller.
299
+ let errorRecorded = false;
300
+ if (options.fallback) {
301
+ recordError(scope, failedBy, sanitizeErrorMessage(error));
302
+ errorRecorded = true;
303
+ try {
304
+ const fallbackValue = typeof options.fallback.value === 'function'
305
+ ? await options.fallback.value()
306
+ : options.fallback.value;
307
+ if (observability) {
308
+ observability.hooks.onFinalSuccess?.({
309
+ type: 'final-success',
310
+ key, traceId: observability.traceId, timestamp: Date.now(),
311
+ source: meta.source, attempts: meta.attempts, durationMs,
312
+ });
313
+ }
314
+ if (options.audit) {
315
+ options.audit.log({ key, traceId: observability?.traceId ?? '', timestamp: Date.now(), durationMs, ok: true, attempts: meta.attempts });
316
+ }
317
+ return { ok: true, value: fallbackValue, source: 'fresh', attempts: meta.attempts, traceId: observability?.traceId, durationMs };
318
+ }
319
+ catch {
320
+ // fallback itself failed — fall through to normal failure
321
+ }
322
+ }
323
+ const sanitizedError = options.audit ? sanitizeError(error) : error;
324
+ if (!errorRecorded) {
325
+ recordError(scope, failedBy, sanitizeErrorMessage(error));
326
+ }
327
+ if (observability) {
328
+ observability.hooks.onFinalFailure?.({
329
+ type: 'final-failure',
330
+ key, traceId: observability.traceId, timestamp: Date.now(),
331
+ attempts: meta.attempts, durationMs,
332
+ failedBy, error,
333
+ });
334
+ }
335
+ if (options.audit) {
336
+ options.audit.log({ key, traceId: observability?.traceId ?? '', timestamp: Date.now(), durationMs, ok: false, attempts: meta.attempts, failedBy, error: sanitizedError });
337
+ }
338
+ return { ok: false, error, attempts: meta.attempts, traceId: observability?.traceId, durationMs };
339
+ }
340
+ finally {
341
+ cleanup();
342
+ unregisterInflight(scope);
343
+ unregisterDrainable(scope);
138
344
  }
139
345
  }
346
+ // Hedge request: sends a second call after delayMs, races them.
347
+ // Clears timer on settle to prevent leak. Marks primary as handled
348
+ // to prevent unhandled rejection if hedge wins.
349
+ function wrapHedge(fn, delayMs) {
350
+ return async (signal) => {
351
+ let timer;
352
+ const primary = fn(signal);
353
+ const hedgeTimeout = new Promise((_, reject) => {
354
+ timer = setTimeout(() => reject(new Error('__HEDGE_TIMEOUT__')), delayMs);
355
+ });
356
+ try {
357
+ return await Promise.race([primary, hedgeTimeout]);
358
+ }
359
+ catch (e) {
360
+ if (e instanceof Error && e.message === '__HEDGE_TIMEOUT__') {
361
+ // Primary is still running — mark as handled to prevent unhandled rejection
362
+ Promise.resolve(primary).catch(() => { });
363
+ const hedgePromise = Promise.resolve(fn(signal));
364
+ hedgePromise.catch(() => { }); // mark hedge as handled if primary wins
365
+ return await Promise.race([primary, hedgePromise]);
366
+ }
367
+ throw e;
368
+ }
369
+ finally {
370
+ if (timer)
371
+ clearTimeout(timer);
372
+ }
373
+ };
374
+ }
140
375
  /**
141
376
  * Invalidate the cached value for `key` on the default module-level store.
142
377
  *
@@ -154,34 +389,107 @@ export async function act(key, fn, options = {}) {
154
389
  * ```
155
390
  */
156
391
  export function invalidate(key) {
392
+ assertKey(key);
157
393
  const cacheKey = CACHE_NS + key;
158
394
  const existed = defaultStore.has(cacheKey);
159
395
  defaultStore.delete(cacheKey);
160
396
  return existed;
161
397
  }
162
398
  export function withStore(store) {
399
+ const scope = 'scoped:' + Math.random().toString(36).slice(2, 8);
163
400
  const scopedAct = async (key, fn, options = {}) => {
164
401
  assertKey(key);
165
402
  assertOptions(options);
166
403
  const meta = { attempts: 1, source: 'fresh' };
167
- const rootController = buildRootSignal(options.signal);
404
+ const { controller: rootController, cleanup } = buildRootSignal(options.signal);
405
+ const observability = buildObservability(options.observability, options.traceId);
406
+ const startedAt = Date.now();
407
+ registerInflight(scope);
408
+ registerDrainable(scope);
168
409
  if (rootController.signal.aborted) {
169
- return { ok: false, error: rootController.signal.reason, attempts: 0 };
410
+ cleanup();
411
+ unregisterInflight(scope);
412
+ unregisterDrainable(scope);
413
+ const error = rootController.signal.reason;
414
+ if (observability) {
415
+ observability.hooks.onFinalFailure?.({
416
+ type: 'final-failure', key, traceId: observability.traceId, timestamp: Date.now(),
417
+ attempts: 0, durationMs: Date.now() - startedAt, failedBy: 'abort', error,
418
+ });
419
+ }
420
+ return { ok: false, error, attempts: 0, traceId: observability?.traceId, durationMs: Date.now() - startedAt };
170
421
  }
171
422
  const policies = buildPolicies(options);
423
+ const hasRetryPolicy = !!(options.retry && options.retry.attempts > 1);
424
+ if (observability && !hasRetryPolicy) {
425
+ observability.hooks.onAttempt?.({
426
+ type: 'attempt', key, traceId: observability.traceId,
427
+ timestamp: Date.now(), attempt: 1,
428
+ });
429
+ }
430
+ const fnWithHedge = options.hedge ? wrapHedge(fn, options.hedge.delayMs) : fn;
172
431
  try {
173
- const value = await execute({
432
+ const value = await raceAbort(execute({
174
433
  key,
175
- fn,
434
+ fn: fnWithHedge,
176
435
  policies,
177
436
  store,
178
437
  meta,
179
438
  signal: rootController.signal,
180
- });
181
- return { ok: true, value, source: meta.source, attempts: meta.attempts };
439
+ observability,
440
+ }), rootController.signal);
441
+ const durationMs = Date.now() - startedAt;
442
+ recordSuccess(scope);
443
+ if (observability) {
444
+ observability.hooks.onFinalSuccess?.({
445
+ type: 'final-success', key, traceId: observability.traceId, timestamp: Date.now(),
446
+ source: meta.source, attempts: meta.attempts, durationMs,
447
+ });
448
+ }
449
+ if (options.audit) {
450
+ options.audit.log({ key, traceId: observability?.traceId ?? '', timestamp: Date.now(), durationMs, ok: true, attempts: meta.attempts });
451
+ }
452
+ return { ok: true, value, source: meta.source, attempts: meta.attempts, traceId: observability?.traceId, durationMs };
182
453
  }
183
454
  catch (error) {
184
- return { ok: false, error, attempts: meta.attempts };
455
+ const durationMs = Date.now() - startedAt;
456
+ const failedBy = rootController.signal.aborted ? 'abort' : classifyFailure(error);
457
+ let errorRecorded = false;
458
+ if (options.fallback) {
459
+ recordError(scope, failedBy, sanitizeErrorMessage(error));
460
+ errorRecorded = true;
461
+ try {
462
+ const fallbackValue = typeof options.fallback.value === 'function'
463
+ ? await options.fallback.value()
464
+ : options.fallback.value;
465
+ if (options.audit) {
466
+ options.audit.log({ key, traceId: observability?.traceId ?? '', timestamp: Date.now(), durationMs, ok: true, attempts: meta.attempts });
467
+ }
468
+ return { ok: true, value: fallbackValue, source: 'fresh', attempts: meta.attempts, traceId: observability?.traceId, durationMs };
469
+ }
470
+ catch {
471
+ // fallback failed — fall through
472
+ }
473
+ }
474
+ if (!errorRecorded) {
475
+ recordError(scope, failedBy, sanitizeErrorMessage(error));
476
+ }
477
+ if (observability) {
478
+ observability.hooks.onFinalFailure?.({
479
+ type: 'final-failure', key, traceId: observability.traceId, timestamp: Date.now(),
480
+ attempts: meta.attempts, durationMs, failedBy, error,
481
+ });
482
+ }
483
+ if (options.audit) {
484
+ const sanitizedError = sanitizeError(error);
485
+ options.audit.log({ key, traceId: observability?.traceId ?? '', timestamp: Date.now(), durationMs, ok: false, attempts: meta.attempts, failedBy, error: sanitizedError });
486
+ }
487
+ return { ok: false, error, attempts: meta.attempts, traceId: observability?.traceId, durationMs };
488
+ }
489
+ finally {
490
+ cleanup();
491
+ unregisterInflight(scope);
492
+ unregisterDrainable(scope);
185
493
  }
186
494
  };
187
495
  // Build the `invalidate` implementation. The runtime branch on
@@ -190,15 +498,25 @@ export function withStore(store) {
190
498
  // (`boolean | Promise<boolean>`) to match either overload signature
191
499
  // individually. The overloads at the call site guarantee callers see
192
500
  // the correct type.
501
+ //
502
+ // FIX: The old async path did has() then delete() in separate awaits —
503
+ // a TOCTOU race. Sync stores are safe (single synchronous frame).
504
+ // Async stores document this as a known limitation.
193
505
  const invalidateImpl = (key) => {
194
506
  assertKey(key);
195
507
  const cacheKey = CACHE_NS + key;
196
508
  if (isSyncStore(store)) {
509
+ // Sync store: has() + delete() in the same synchronous frame is safe in single-frame.
197
510
  const existed = store.has(cacheKey);
198
511
  store.delete(cacheKey);
199
512
  return existed;
200
513
  }
201
- // Async store branch.
514
+ // Async store: safe in single-frame delete. We check has() first, then delete.
515
+ // Between the two awaits, another caller could delete — but the return
516
+ // value is "did this key exist at the time we checked", which is the
517
+ // best we can do without a store-level delete-and-return-existed API.
518
+ // For true safe in single-frame semantics, async stores should implement a
519
+ // `deleteIfExists()` method — documented as a future API enhancement.
202
520
  return (async () => {
203
521
  const existed = await store.has(cacheKey);
204
522
  await store.delete(cacheKey);
@@ -1 +1 @@
1
- {"version":3,"file":"act.js","sourceRoot":"","sources":["../../src/core/act.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"act.js","sourceRoot":"","sources":["../../src/core/act.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,8 @@ async function execute(input) {
38
38
  key: input.key,
39
39
  store: input.store,
40
40
  meta: input.meta,
41
+ // Thread observability through. Policies read this lazily.
42
+ observability: input.observability,
41
43
  };
42
44
  // Build the call chain from inside out.
43
45
  // reduceRight ensures policies[0] becomes the outermost wrapper (runs first).
@@ -1,4 +1,4 @@
1
- import type { ActFn, PolicyApplier, AnyStateStore, RunMeta } from '../types/index.js';
1
+ import type { ActFn, PolicyApplier, AnyStateStore, RunMeta, ObservabilityContext } from '../types/index.js';
2
2
  /**
3
3
  * Symbol stamped onto `PolicyApplier` functions by `dedupePolicy`.
4
4
  *
@@ -31,6 +31,11 @@ export interface ExecutorInput<T> {
31
31
  * inward.
32
32
  */
33
33
  signal: AbortSignal;
34
+ /**
35
+ * Observability context. When present, policies emit events
36
+ * via the hooks. When absent (the common case), zero overhead.
37
+ */
38
+ observability?: ObservabilityContext;
34
39
  }
35
40
  /**
36
41
  * Pure execution engine.
@@ -1 +1 @@
1
- {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EAEb,aAAa,EACb,OAAO,EACR,MAAM,mBAAmB,CAAA;AAG1B;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,eAAoC,CAAA;AAEpE,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,GAAG,EAAO,MAAM,CAAA;IAChB,EAAE,EAAQ,KAAK,CAAC,CAAC,CAAC,CAAA;IAClB;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACzC,KAAK,EAAK,aAAa,CAAA;IACvB,IAAI,EAAM,OAAO,CAAA;IACjB;;;;;;OAMG;IACH,MAAM,EAAI,WAAW,CAAA;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA+BpE"}
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EAEb,aAAa,EACb,OAAO,EACP,oBAAoB,EACrB,MAAM,mBAAmB,CAAA;AAG1B;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,eAAoC,CAAA;AAEpE,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,GAAG,EAAO,MAAM,CAAA;IAChB,EAAE,EAAQ,KAAK,CAAC,CAAC,CAAC,CAAA;IAClB;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACzC,KAAK,EAAK,aAAa,CAAA;IACvB,IAAI,EAAM,OAAO,CAAA;IACjB;;;;;;OAMG;IACH,MAAM,EAAI,WAAW,CAAA;IACrB;;;OAGG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAA;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAiCpE"}
@@ -34,6 +34,8 @@ export async function execute(input) {
34
34
  key: input.key,
35
35
  store: input.store,
36
36
  meta: input.meta,
37
+ // Thread observability through. Policies read this lazily.
38
+ observability: input.observability,
37
39
  };
38
40
  // Build the call chain from inside out.
39
41
  // reduceRight ensures policies[0] becomes the outermost wrapper (runs first).
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAA;AA6BpE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAI,KAAuB;IACtD,wEAAwE;IACxE,uEAAuE;IACvE,qEAAqE;IACrE,4CAA4C;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,CAAE,CAA4D,CAAC,mBAAmB,CAAC,CACxF,CAAA;IACD,IAAI,SAAS,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,wEAAwE;YACxE,uDAAuD;YACvD,kEAAkE,CACnE,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAkB;QACzB,GAAG,EAAI,KAAK,CAAC,GAAG;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAG,KAAK,CAAC,IAAI;KAClB,CAAA;IAED,wCAAwC;IACxC,8EAA8E;IAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CACxC,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,EAC/C,KAAK,CAAC,EAAE,CACT,CAAA;IAED,mDAAmD;IACnD,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC"}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/core/executor.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAA;AAkCpE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAI,KAAuB;IACtD,wEAAwE;IACxE,uEAAuE;IACvE,qEAAqE;IACrE,4CAA4C;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,CAAE,CAA4D,CAAC,mBAAmB,CAAC,CACxF,CAAA;IACD,IAAI,SAAS,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,wEAAwE;YACxE,uDAAuD;YACvD,kEAAkE,CACnE,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAkB;QACzB,GAAG,EAAI,KAAK,CAAC,GAAG;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAG,KAAK,CAAC,IAAI;QACjB,2DAA2D;QAC3D,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAA;IAED,wCAAwC;IACxC,8EAA8E;IAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,CACxC,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,EAC/C,KAAK,CAAC,EAAE,CACT,CAAA;IAED,mDAAmD;IACnD,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerInflight = registerInflight;
4
+ exports.unregisterInflight = unregisterInflight;
5
+ exports.recordError = recordError;
6
+ exports.recordSuccess = recordSuccess;
7
+ exports.createHealthCheck = createHealthCheck;
8
+ let globalInflight = 0;
9
+ let startTime = Date.now();
10
+ let globalLastError;
11
+ let globalLastSuccessAt;
12
+ function registerInflight(_scope) {
13
+ globalInflight++;
14
+ }
15
+ function unregisterInflight(_scope) {
16
+ globalInflight = Math.max(0, globalInflight - 1);
17
+ }
18
+ function recordError(_scope, code, message) {
19
+ globalLastError = { code, message, timestamp: Date.now() };
20
+ }
21
+ function recordSuccess(_scope) {
22
+ globalLastSuccessAt = Date.now();
23
+ }
24
+ function createHealthCheck(store) {
25
+ return () => {
26
+ return {
27
+ storeSize: store.size(),
28
+ pendingInflight: globalInflight,
29
+ uptimeMs: Date.now() - startTime,
30
+ lastError: globalLastError,
31
+ lastSuccessAt: globalLastSuccessAt,
32
+ };
33
+ };
34
+ }
@@ -0,0 +1,18 @@
1
+ import type { InMemoryStore } from '../stores/memory.js';
2
+ export interface HealthStatus {
3
+ storeSize: number;
4
+ pendingInflight: number;
5
+ uptimeMs: number;
6
+ lastError?: {
7
+ code: string;
8
+ message: string;
9
+ timestamp: number;
10
+ };
11
+ lastSuccessAt?: number;
12
+ }
13
+ export declare function registerInflight(_scope: string): void;
14
+ export declare function unregisterInflight(_scope: string): void;
15
+ export declare function recordError(_scope: string, code: string, message: string): void;
16
+ export declare function recordSuccess(_scope: string): void;
17
+ export declare function createHealthCheck(store: InMemoryStore): () => HealthStatus;
18
+ //# sourceMappingURL=health.d.ts.map