footprintjs 4.16.0 → 4.17.2
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/AGENTS.md +567 -82
- package/CLAUDE.md +57 -0
- package/README.md +2 -0
- package/dist/advanced.js +4 -2
- package/dist/detach.js +78 -0
- package/dist/esm/advanced.js +2 -1
- package/dist/esm/detach.js +57 -0
- package/dist/esm/lib/builder/FlowChartBuilder.js +171 -61
- package/dist/esm/lib/contract/openapi.js +4 -5
- package/dist/esm/lib/contract/schema.js +115 -4
- package/dist/esm/lib/decide/decide.js +4 -5
- package/dist/esm/lib/decide/evidence.js +3 -2
- package/dist/esm/lib/detach/drivers/immediate.js +66 -0
- package/dist/esm/lib/detach/drivers/microtaskBatch.js +113 -0
- package/dist/esm/lib/detach/drivers/sendBeacon.js +78 -0
- package/dist/esm/lib/detach/drivers/setImmediate.js +81 -0
- package/dist/esm/lib/detach/drivers/setTimeout.js +69 -0
- package/dist/esm/lib/detach/drivers/workerThread.js +117 -0
- package/dist/esm/lib/detach/flush.js +91 -0
- package/dist/esm/lib/detach/handle.js +134 -0
- package/dist/esm/lib/detach/registry.js +97 -0
- package/dist/esm/lib/detach/runChild.js +40 -0
- package/dist/esm/lib/detach/spawn.js +86 -0
- package/dist/esm/lib/detach/types.js +37 -0
- package/dist/esm/lib/engine/errors/errorInfo.js +4 -4
- package/dist/esm/lib/engine/graph/StageNode.js +2 -2
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +9 -8
- package/dist/esm/lib/engine/handlers/ContinuationResolver.js +12 -9
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +7 -8
- package/dist/esm/lib/engine/handlers/ExtractorRunner.js +14 -8
- package/dist/esm/lib/engine/handlers/NodeResolver.js +5 -3
- package/dist/esm/lib/engine/handlers/RuntimeStructureManager.js +11 -14
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +9 -9
- package/dist/esm/lib/engine/handlers/StageRunner.js +9 -11
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +13 -12
- package/dist/esm/lib/engine/handlers/SubflowInputMapper.js +4 -4
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +85 -96
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +18 -36
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +6 -5
- package/dist/esm/lib/engine/narrative/recorders/AdaptiveNarrativeFlowRecorder.js +7 -6
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.js +10 -10
- package/dist/esm/lib/engine/narrative/recorders/MilestoneNarrativeFlowRecorder.js +5 -3
- package/dist/esm/lib/engine/narrative/recorders/ProgressiveNarrativeFlowRecorder.js +4 -3
- package/dist/esm/lib/engine/narrative/recorders/RLENarrativeFlowRecorder.js +4 -4
- package/dist/esm/lib/engine/narrative/recorders/SeparateNarrativeFlowRecorder.js +5 -6
- package/dist/esm/lib/engine/narrative/recorders/SilentNarrativeFlowRecorder.js +5 -6
- package/dist/esm/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.js +5 -3
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +97 -71
- package/dist/esm/lib/memory/DiagnosticCollector.js +6 -8
- package/dist/esm/lib/memory/EventLog.js +5 -3
- package/dist/esm/lib/memory/SharedMemory.js +3 -2
- package/dist/esm/lib/memory/StageContext.js +44 -14
- package/dist/esm/lib/memory/TransactionBuffer.js +9 -8
- package/dist/esm/lib/memory/backtrack.js +3 -4
- package/dist/esm/lib/memory/commitLogUtils.js +2 -2
- package/dist/esm/lib/memory/utils.js +2 -3
- package/dist/esm/lib/pause/types.js +33 -14
- package/dist/esm/lib/reactive/createTypedScope.js +10 -8
- package/dist/esm/lib/reactive/types.js +3 -1
- package/dist/esm/lib/recorder/BoundaryStateTracker.js +263 -0
- package/dist/esm/lib/recorder/CompositeRecorder.js +3 -1
- package/dist/esm/lib/recorder/InOutRecorder.js +5 -6
- package/dist/esm/lib/recorder/KeyedRecorder.js +2 -4
- package/dist/esm/lib/recorder/QualityRecorder.js +15 -14
- package/dist/esm/lib/recorder/SequenceRecorder.js +11 -12
- package/dist/esm/lib/recorder/TopologyRecorder.js +36 -40
- package/dist/esm/lib/recorder/index.js +2 -1
- package/dist/esm/lib/recorder/qualityTrace.js +4 -5
- package/dist/esm/lib/runner/ExecutionRuntime.js +20 -4
- package/dist/esm/lib/runner/FlowChartExecutor.js +99 -55
- package/dist/esm/lib/runner/RunContext.js +5 -3
- package/dist/esm/lib/runner/RunnableChart.js +7 -9
- package/dist/esm/lib/runner/getSubtreeSnapshot.js +4 -5
- package/dist/esm/lib/schema/errors.js +4 -3
- package/dist/esm/lib/schema/validate.js +4 -5
- package/dist/esm/lib/scope/ScopeFacade.js +52 -35
- package/dist/esm/lib/scope/providers/baseStateCompatible.js +9 -9
- package/dist/esm/lib/scope/providers/guards.js +2 -2
- package/dist/esm/lib/scope/recorders/DebugRecorder.js +9 -7
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +10 -8
- package/dist/esm/lib/scope/state/zod/defineScopeFromZod.js +2 -3
- package/dist/esm/lib/scope/state/zod/resolver.js +2 -3
- package/dist/esm/lib/scope/state/zod/scopeFactory.js +16 -20
- package/dist/esm/lib/scope/state/zod/utils/validateHelper.js +57 -14
- package/dist/esm/trace.js +4 -1
- package/dist/lib/builder/FlowChartBuilder.js +171 -61
- package/dist/lib/contract/openapi.js +4 -5
- package/dist/lib/contract/schema.js +115 -4
- package/dist/lib/decide/decide.js +4 -5
- package/dist/lib/decide/evidence.js +3 -2
- package/dist/lib/detach/drivers/immediate.js +70 -0
- package/dist/lib/detach/drivers/microtaskBatch.js +117 -0
- package/dist/lib/detach/drivers/sendBeacon.js +82 -0
- package/dist/lib/detach/drivers/setImmediate.js +85 -0
- package/dist/lib/detach/drivers/setTimeout.js +73 -0
- package/dist/lib/detach/drivers/workerThread.js +121 -0
- package/dist/lib/detach/flush.js +95 -0
- package/dist/lib/detach/handle.js +140 -0
- package/dist/lib/detach/registry.js +106 -0
- package/dist/lib/detach/runChild.js +67 -0
- package/dist/lib/detach/spawn.js +92 -0
- package/dist/lib/detach/types.js +38 -0
- package/dist/lib/engine/errors/errorInfo.js +4 -4
- package/dist/lib/engine/graph/StageNode.js +2 -2
- package/dist/lib/engine/handlers/ChildrenExecutor.js +9 -8
- package/dist/lib/engine/handlers/ContinuationResolver.js +12 -9
- package/dist/lib/engine/handlers/DeciderHandler.js +7 -8
- package/dist/lib/engine/handlers/ExtractorRunner.js +14 -8
- package/dist/lib/engine/handlers/NodeResolver.js +5 -3
- package/dist/lib/engine/handlers/RuntimeStructureManager.js +11 -14
- package/dist/lib/engine/handlers/SelectorHandler.js +9 -9
- package/dist/lib/engine/handlers/StageRunner.js +9 -11
- package/dist/lib/engine/handlers/SubflowExecutor.js +13 -12
- package/dist/lib/engine/handlers/SubflowInputMapper.js +4 -4
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +85 -96
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +18 -36
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +6 -5
- package/dist/lib/engine/narrative/recorders/AdaptiveNarrativeFlowRecorder.js +7 -6
- package/dist/lib/engine/narrative/recorders/ManifestFlowRecorder.js +10 -10
- package/dist/lib/engine/narrative/recorders/MilestoneNarrativeFlowRecorder.js +5 -3
- package/dist/lib/engine/narrative/recorders/ProgressiveNarrativeFlowRecorder.js +4 -3
- package/dist/lib/engine/narrative/recorders/RLENarrativeFlowRecorder.js +4 -4
- package/dist/lib/engine/narrative/recorders/SeparateNarrativeFlowRecorder.js +5 -6
- package/dist/lib/engine/narrative/recorders/SilentNarrativeFlowRecorder.js +5 -6
- package/dist/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.js +5 -3
- package/dist/lib/engine/traversal/FlowchartTraverser.js +97 -71
- package/dist/lib/memory/DiagnosticCollector.js +6 -8
- package/dist/lib/memory/EventLog.js +5 -3
- package/dist/lib/memory/SharedMemory.js +3 -2
- package/dist/lib/memory/StageContext.js +44 -14
- package/dist/lib/memory/TransactionBuffer.js +9 -8
- package/dist/lib/memory/backtrack.js +3 -4
- package/dist/lib/memory/commitLogUtils.js +2 -2
- package/dist/lib/memory/utils.js +2 -3
- package/dist/lib/pause/types.js +33 -14
- package/dist/lib/reactive/createTypedScope.js +10 -8
- package/dist/lib/reactive/types.js +3 -1
- package/dist/lib/recorder/BoundaryStateTracker.js +267 -0
- package/dist/lib/recorder/CompositeRecorder.js +3 -1
- package/dist/lib/recorder/InOutRecorder.js +5 -6
- package/dist/lib/recorder/KeyedRecorder.js +2 -4
- package/dist/lib/recorder/QualityRecorder.js +15 -14
- package/dist/lib/recorder/SequenceRecorder.js +11 -12
- package/dist/lib/recorder/TopologyRecorder.js +36 -40
- package/dist/lib/recorder/index.js +4 -2
- package/dist/lib/recorder/qualityTrace.js +4 -5
- package/dist/lib/runner/ExecutionRuntime.js +20 -4
- package/dist/lib/runner/FlowChartExecutor.js +99 -55
- package/dist/lib/runner/RunContext.js +5 -3
- package/dist/lib/runner/RunnableChart.js +7 -9
- package/dist/lib/runner/getSubtreeSnapshot.js +4 -5
- package/dist/lib/schema/errors.js +4 -3
- package/dist/lib/schema/validate.js +4 -5
- package/dist/lib/scope/ScopeFacade.js +52 -35
- package/dist/lib/scope/providers/baseStateCompatible.js +9 -9
- package/dist/lib/scope/providers/guards.js +2 -2
- package/dist/lib/scope/recorders/DebugRecorder.js +9 -7
- package/dist/lib/scope/recorders/MetricRecorder.js +10 -8
- package/dist/lib/scope/state/zod/defineScopeFromZod.js +2 -3
- package/dist/lib/scope/state/zod/resolver.js +2 -3
- package/dist/lib/scope/state/zod/scopeFactory.js +16 -20
- package/dist/lib/scope/state/zod/utils/validateHelper.js +57 -14
- package/dist/trace.js +6 -2
- package/dist/types/advanced.d.ts +1 -0
- package/dist/types/detach.d.ts +59 -0
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +81 -0
- package/dist/types/lib/detach/drivers/immediate.d.ts +39 -0
- package/dist/types/lib/detach/drivers/microtaskBatch.d.ts +57 -0
- package/dist/types/lib/detach/drivers/sendBeacon.d.ts +38 -0
- package/dist/types/lib/detach/drivers/setImmediate.d.ts +32 -0
- package/dist/types/lib/detach/drivers/setTimeout.d.ts +34 -0
- package/dist/types/lib/detach/drivers/workerThread.d.ts +50 -0
- package/dist/types/lib/detach/flush.d.ts +62 -0
- package/dist/types/lib/detach/handle.d.ts +83 -0
- package/dist/types/lib/detach/registry.d.ts +82 -0
- package/dist/types/lib/detach/runChild.d.ts +41 -0
- package/dist/types/lib/detach/spawn.d.ts +64 -0
- package/dist/types/lib/detach/types.d.ts +200 -0
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +0 -1
- package/dist/types/lib/engine/types.d.ts +0 -1
- package/dist/types/lib/reactive/types.d.ts +4 -0
- package/dist/types/lib/recorder/BoundaryStateTracker.d.ts +215 -0
- package/dist/types/lib/recorder/index.d.ts +1 -0
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +28 -0
- package/dist/types/lib/scope/ScopeFacade.d.ts +4 -0
- package/dist/types/lib/scope/state/zod/utils/validateHelper.d.ts +13 -1
- package/dist/types/trace.d.ts +1 -0
- package/package.json +6 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* detach/flush.ts — Drain every in-flight detached handle to terminal.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Drain-loop with deadline. Same shape as a graceful HTTP
|
|
5
|
+
* server shutdown: snapshot the queue, await everything in
|
|
6
|
+
* flight, repeat until empty or deadline.
|
|
7
|
+
* Role: Graceful-shutdown hook for consumers who launched
|
|
8
|
+
* fire-and-forget work and want to make sure it actually
|
|
9
|
+
* flushed before exiting (server stop, test cleanup, etc.).
|
|
10
|
+
*
|
|
11
|
+
* Why iterate (not single Promise.all over a snapshot):
|
|
12
|
+
* - A child stage can itself call `detachAndForget` while running —
|
|
13
|
+
* new handles arrive WHILE we're flushing. A single snapshot would
|
|
14
|
+
* miss them. Looping until `size() === 0` drains transitively.
|
|
15
|
+
*
|
|
16
|
+
* Why dedupe via `seen` Set:
|
|
17
|
+
* - Handles already terminal (but not yet `unregister`ed by their
|
|
18
|
+
* driver's finally-block) can re-appear in subsequent snapshots.
|
|
19
|
+
* Without dedupe, the `done` counter would double-count them.
|
|
20
|
+
*
|
|
21
|
+
* Why `Promise.allSettled` (not `Promise.all`):
|
|
22
|
+
* - One handle's rejection must NOT abort the rest. A failed child
|
|
23
|
+
* is normal (it's why `wait()` rejects); we still want to drain
|
|
24
|
+
* the siblings.
|
|
25
|
+
*/
|
|
26
|
+
import { ids, lookup, size } from './registry.js';
|
|
27
|
+
/**
|
|
28
|
+
* Wait for every in-flight detached handle to reach a terminal state.
|
|
29
|
+
* Returns counts for diagnostics. PROCESS-WIDE — drains every driver
|
|
30
|
+
* across every executor. For per-executor scoping, consumers should
|
|
31
|
+
* collect their own handles from `executor.detachAndJoinLater(...)`
|
|
32
|
+
* calls and await `Promise.allSettled([...].map(h => h.wait()))`
|
|
33
|
+
* themselves.
|
|
34
|
+
*
|
|
35
|
+
* @example Graceful server shutdown
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { flushAllDetached } from 'footprintjs/detach';
|
|
38
|
+
*
|
|
39
|
+
* process.on('SIGTERM', async () => {
|
|
40
|
+
* const stats = await flushAllDetached({ timeoutMs: 10_000 });
|
|
41
|
+
* console.log(`Drained ${stats.done} done, ${stats.failed} failed, ${stats.pending} pending.`);
|
|
42
|
+
* process.exit(stats.pending === 0 ? 0 : 1);
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export async function flushAllDetached(opts) {
|
|
47
|
+
const timeoutMs = opts?.timeoutMs ?? 30_000;
|
|
48
|
+
const startedAt = Date.now();
|
|
49
|
+
const seen = new Set();
|
|
50
|
+
let done = 0;
|
|
51
|
+
let failed = 0;
|
|
52
|
+
while (size() > 0) {
|
|
53
|
+
const remainingMs = timeoutMs - (Date.now() - startedAt);
|
|
54
|
+
if (remainingMs <= 0)
|
|
55
|
+
return { done, failed, pending: size() };
|
|
56
|
+
// Snapshot of NEW (unseen) handles. Existing terminal-but-still-
|
|
57
|
+
// registered handles re-appear in subsequent snapshots; the seen
|
|
58
|
+
// set prevents double-counting.
|
|
59
|
+
const newIds = ids().filter((id) => !seen.has(id));
|
|
60
|
+
if (newIds.length === 0) {
|
|
61
|
+
// Everything in the registry is already awaited — yield once and
|
|
62
|
+
// re-check. The driver's unregister-in-finally hasn't run yet.
|
|
63
|
+
await Promise.resolve();
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
for (const id of newIds)
|
|
67
|
+
seen.add(id);
|
|
68
|
+
const handles = newIds.map((id) => lookup(id)).filter((h) => h !== undefined);
|
|
69
|
+
// Race the drain against the per-iteration timeout. We use a
|
|
70
|
+
// `'timeout'` sentinel on the timeout side so the type narrows.
|
|
71
|
+
let timerId;
|
|
72
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
73
|
+
timerId = setTimeout(() => resolve('__detach_timeout__'), remainingMs);
|
|
74
|
+
});
|
|
75
|
+
const drainPromise = Promise.allSettled(handles.map((h) => h.wait()));
|
|
76
|
+
const result = await Promise.race([drainPromise, timeoutPromise]);
|
|
77
|
+
if (timerId !== undefined)
|
|
78
|
+
clearTimeout(timerId);
|
|
79
|
+
if (result === '__detach_timeout__') {
|
|
80
|
+
return { done, failed, pending: size() };
|
|
81
|
+
}
|
|
82
|
+
for (const r of result) {
|
|
83
|
+
if (r.status === 'fulfilled')
|
|
84
|
+
done++;
|
|
85
|
+
else
|
|
86
|
+
failed++;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { done, failed, pending: 0 };
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmx1c2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC9mbHVzaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBRUgsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBc0JsRDs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxJQUFtQjtJQUN4RCxNQUFNLFNBQVMsR0FBRyxJQUFJLEVBQUUsU0FBUyxJQUFJLE1BQU0sQ0FBQztJQUM1QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDN0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUMvQixJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFDYixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFFZixPQUFPLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sV0FBVyxHQUFHLFNBQVMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQztRQUN6RCxJQUFJLFdBQVcsSUFBSSxDQUFDO1lBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7UUFFL0QsaUVBQWlFO1FBQ2pFLGlFQUFpRTtRQUNqRSxnQ0FBZ0M7UUFDaEMsTUFBTSxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNuRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEIsaUVBQWlFO1lBQ2pFLCtEQUErRDtZQUMvRCxNQUFNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN4QixTQUFTO1FBQ1gsQ0FBQztRQUNELEtBQUssTUFBTSxFQUFFLElBQUksTUFBTTtZQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFdEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFxQixFQUFFLENBQUMsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxDQUFDO1FBRWpHLDZEQUE2RDtRQUM3RCxnRUFBZ0U7UUFDaEUsSUFBSSxPQUFrRCxDQUFDO1FBQ3ZELE1BQU0sY0FBYyxHQUFHLElBQUksT0FBTyxDQUF1QixDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ25FLE9BQU8sR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDekUsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsWUFBWSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFDbEUsSUFBSSxPQUFPLEtBQUssU0FBUztZQUFFLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVqRCxJQUFJLE1BQU0sS0FBSyxvQkFBb0IsRUFBRSxDQUFDO1lBQ3BDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQzNDLENBQUM7UUFDRCxLQUFLLE1BQU0sQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxXQUFXO2dCQUFFLElBQUksRUFBRSxDQUFDOztnQkFDaEMsTUFBTSxFQUFFLENBQUM7UUFDaEIsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDdEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZGV0YWNoL2ZsdXNoLnRzIOKAlCBEcmFpbiBldmVyeSBpbi1mbGlnaHQgZGV0YWNoZWQgaGFuZGxlIHRvIHRlcm1pbmFsLlxuICpcbiAqIFBhdHRlcm46ICBEcmFpbi1sb29wIHdpdGggZGVhZGxpbmUuIFNhbWUgc2hhcGUgYXMgYSBncmFjZWZ1bCBIVFRQXG4gKiAgICAgICAgICAgc2VydmVyIHNodXRkb3duOiBzbmFwc2hvdCB0aGUgcXVldWUsIGF3YWl0IGV2ZXJ5dGhpbmcgaW5cbiAqICAgICAgICAgICBmbGlnaHQsIHJlcGVhdCB1bnRpbCBlbXB0eSBvciBkZWFkbGluZS5cbiAqIFJvbGU6ICAgICBHcmFjZWZ1bC1zaHV0ZG93biBob29rIGZvciBjb25zdW1lcnMgd2hvIGxhdW5jaGVkXG4gKiAgICAgICAgICAgZmlyZS1hbmQtZm9yZ2V0IHdvcmsgYW5kIHdhbnQgdG8gbWFrZSBzdXJlIGl0IGFjdHVhbGx5XG4gKiAgICAgICAgICAgZmx1c2hlZCBiZWZvcmUgZXhpdGluZyAoc2VydmVyIHN0b3AsIHRlc3QgY2xlYW51cCwgZXRjLikuXG4gKlxuICogV2h5IGl0ZXJhdGUgKG5vdCBzaW5nbGUgUHJvbWlzZS5hbGwgb3ZlciBhIHNuYXBzaG90KTpcbiAqICAgLSBBIGNoaWxkIHN0YWdlIGNhbiBpdHNlbGYgY2FsbCBgZGV0YWNoQW5kRm9yZ2V0YCB3aGlsZSBydW5uaW5nIOKAlFxuICogICAgIG5ldyBoYW5kbGVzIGFycml2ZSBXSElMRSB3ZSdyZSBmbHVzaGluZy4gQSBzaW5nbGUgc25hcHNob3Qgd291bGRcbiAqICAgICBtaXNzIHRoZW0uIExvb3BpbmcgdW50aWwgYHNpemUoKSA9PT0gMGAgZHJhaW5zIHRyYW5zaXRpdmVseS5cbiAqXG4gKiBXaHkgZGVkdXBlIHZpYSBgc2VlbmAgU2V0OlxuICogICAtIEhhbmRsZXMgYWxyZWFkeSB0ZXJtaW5hbCAoYnV0IG5vdCB5ZXQgYHVucmVnaXN0ZXJgZWQgYnkgdGhlaXJcbiAqICAgICBkcml2ZXIncyBmaW5hbGx5LWJsb2NrKSBjYW4gcmUtYXBwZWFyIGluIHN1YnNlcXVlbnQgc25hcHNob3RzLlxuICogICAgIFdpdGhvdXQgZGVkdXBlLCB0aGUgYGRvbmVgIGNvdW50ZXIgd291bGQgZG91YmxlLWNvdW50IHRoZW0uXG4gKlxuICogV2h5IGBQcm9taXNlLmFsbFNldHRsZWRgIChub3QgYFByb21pc2UuYWxsYCk6XG4gKiAgIC0gT25lIGhhbmRsZSdzIHJlamVjdGlvbiBtdXN0IE5PVCBhYm9ydCB0aGUgcmVzdC4gQSBmYWlsZWQgY2hpbGRcbiAqICAgICBpcyBub3JtYWwgKGl0J3Mgd2h5IGB3YWl0KClgIHJlamVjdHMpOyB3ZSBzdGlsbCB3YW50IHRvIGRyYWluXG4gKiAgICAgdGhlIHNpYmxpbmdzLlxuICovXG5cbmltcG9ydCB7IGlkcywgbG9va3VwLCBzaXplIH0gZnJvbSAnLi9yZWdpc3RyeS5qcyc7XG5pbXBvcnQgdHlwZSB7IERldGFjaEhhbmRsZSB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZsdXNoUmVzdWx0IHtcbiAgLyoqIEhhbmRsZXMgd2hvc2UgYHdhaXQoKWAgd2UgRVhQTElDSVRMWSBhd2FpdGVkIGFuZCBzYXcgZnVsZmlsbGVkLlxuICAgKiAgQmVzdC1lZmZvcnQgY291bnQg4oCUIGEgY2hpbGQgdGhhdCBjb21wbGV0ZXMgaW5zaWRlIGFub3RoZXInc1xuICAgKiAgYHdhaXQoKWAgbWF5IGZpbmlzaCAoYW5kIHVucmVnaXN0ZXIpIGJlZm9yZSB3ZSBnZXQgYSBjaGFuY2UgdG9cbiAgICogIGF3YWl0IGl0IGRpcmVjdGx5LiBUaGUgRFJBSU4gaXMgc3RpbGwgZ3VhcmFudGVlZCAocmVnaXN0cnkgZW1wdHlcbiAgICogIG9uIHJldHVybik7IG9ubHkgdGhlIENPVU5UIGlzIGFwcHJveGltYXRlLiAqL1xuICByZWFkb25seSBkb25lOiBudW1iZXI7XG4gIC8qKiBIYW5kbGVzIHdob3NlIGB3YWl0KClgIHJlamVjdGVkLiBTYW1lIGJlc3QtZWZmb3J0IHNlbWFudGljcy4gKi9cbiAgcmVhZG9ubHkgZmFpbGVkOiBudW1iZXI7XG4gIC8qKiBIYW5kbGVzIHN0aWxsIGluLWZsaWdodCB3aGVuIHRoZSBkZWFkbGluZSBleHBpcmVkLiBgMGAgaW5kaWNhdGVzXG4gICAqICBhIHN1Y2Nlc3NmdWwgKGNvbXBsZXRlKSBkcmFpbiDigJQgcmVnaXN0cnkgd2FzIGVtcHR5IG9uIHJldHVybi4gKi9cbiAgcmVhZG9ubHkgcGVuZGluZzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZsdXNoT3B0aW9ucyB7XG4gIC8qKiBNYXggd2FsbC1jbG9jayB0byBzcGVuZCBkcmFpbmluZywgaW4gbWlsbGlzZWNvbmRzLiBEZWZhdWx0IDMwcy4gKi9cbiAgcmVhZG9ubHkgdGltZW91dE1zPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIFdhaXQgZm9yIGV2ZXJ5IGluLWZsaWdodCBkZXRhY2hlZCBoYW5kbGUgdG8gcmVhY2ggYSB0ZXJtaW5hbCBzdGF0ZS5cbiAqIFJldHVybnMgY291bnRzIGZvciBkaWFnbm9zdGljcy4gUFJPQ0VTUy1XSURFIOKAlCBkcmFpbnMgZXZlcnkgZHJpdmVyXG4gKiBhY3Jvc3MgZXZlcnkgZXhlY3V0b3IuIEZvciBwZXItZXhlY3V0b3Igc2NvcGluZywgY29uc3VtZXJzIHNob3VsZFxuICogY29sbGVjdCB0aGVpciBvd24gaGFuZGxlcyBmcm9tIGBleGVjdXRvci5kZXRhY2hBbmRKb2luTGF0ZXIoLi4uKWBcbiAqIGNhbGxzIGFuZCBhd2FpdCBgUHJvbWlzZS5hbGxTZXR0bGVkKFsuLi5dLm1hcChoID0+IGgud2FpdCgpKSlgXG4gKiB0aGVtc2VsdmVzLlxuICpcbiAqIEBleGFtcGxlIEdyYWNlZnVsIHNlcnZlciBzaHV0ZG93blxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgZmx1c2hBbGxEZXRhY2hlZCB9IGZyb20gJ2Zvb3RwcmludGpzL2RldGFjaCc7XG4gKlxuICogcHJvY2Vzcy5vbignU0lHVEVSTScsIGFzeW5jICgpID0+IHtcbiAqICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBmbHVzaEFsbERldGFjaGVkKHsgdGltZW91dE1zOiAxMF8wMDAgfSk7XG4gKiAgIGNvbnNvbGUubG9nKGBEcmFpbmVkICR7c3RhdHMuZG9uZX0gZG9uZSwgJHtzdGF0cy5mYWlsZWR9IGZhaWxlZCwgJHtzdGF0cy5wZW5kaW5nfSBwZW5kaW5nLmApO1xuICogICBwcm9jZXNzLmV4aXQoc3RhdHMucGVuZGluZyA9PT0gMCA/IDAgOiAxKTtcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmbHVzaEFsbERldGFjaGVkKG9wdHM/OiBGbHVzaE9wdGlvbnMpOiBQcm9taXNlPEZsdXNoUmVzdWx0PiB7XG4gIGNvbnN0IHRpbWVvdXRNcyA9IG9wdHM/LnRpbWVvdXRNcyA/PyAzMF8wMDA7XG4gIGNvbnN0IHN0YXJ0ZWRBdCA9IERhdGUubm93KCk7XG4gIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgbGV0IGRvbmUgPSAwO1xuICBsZXQgZmFpbGVkID0gMDtcblxuICB3aGlsZSAoc2l6ZSgpID4gMCkge1xuICAgIGNvbnN0IHJlbWFpbmluZ01zID0gdGltZW91dE1zIC0gKERhdGUubm93KCkgLSBzdGFydGVkQXQpO1xuICAgIGlmIChyZW1haW5pbmdNcyA8PSAwKSByZXR1cm4geyBkb25lLCBmYWlsZWQsIHBlbmRpbmc6IHNpemUoKSB9O1xuXG4gICAgLy8gU25hcHNob3Qgb2YgTkVXICh1bnNlZW4pIGhhbmRsZXMuIEV4aXN0aW5nIHRlcm1pbmFsLWJ1dC1zdGlsbC1cbiAgICAvLyByZWdpc3RlcmVkIGhhbmRsZXMgcmUtYXBwZWFyIGluIHN1YnNlcXVlbnQgc25hcHNob3RzOyB0aGUgc2VlblxuICAgIC8vIHNldCBwcmV2ZW50cyBkb3VibGUtY291bnRpbmcuXG4gICAgY29uc3QgbmV3SWRzID0gaWRzKCkuZmlsdGVyKChpZCkgPT4gIXNlZW4uaGFzKGlkKSk7XG4gICAgaWYgKG5ld0lkcy5sZW5ndGggPT09IDApIHtcbiAgICAgIC8vIEV2ZXJ5dGhpbmcgaW4gdGhlIHJlZ2lzdHJ5IGlzIGFscmVhZHkgYXdhaXRlZCDigJQgeWllbGQgb25jZSBhbmRcbiAgICAgIC8vIHJlLWNoZWNrLiBUaGUgZHJpdmVyJ3MgdW5yZWdpc3Rlci1pbi1maW5hbGx5IGhhc24ndCBydW4geWV0LlxuICAgICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBpZCBvZiBuZXdJZHMpIHNlZW4uYWRkKGlkKTtcblxuICAgIGNvbnN0IGhhbmRsZXMgPSBuZXdJZHMubWFwKChpZCkgPT4gbG9va3VwKGlkKSkuZmlsdGVyKChoKTogaCBpcyBEZXRhY2hIYW5kbGUgPT4gaCAhPT0gdW5kZWZpbmVkKTtcblxuICAgIC8vIFJhY2UgdGhlIGRyYWluIGFnYWluc3QgdGhlIHBlci1pdGVyYXRpb24gdGltZW91dC4gV2UgdXNlIGFcbiAgICAvLyBgJ3RpbWVvdXQnYCBzZW50aW5lbCBvbiB0aGUgdGltZW91dCBzaWRlIHNvIHRoZSB0eXBlIG5hcnJvd3MuXG4gICAgbGV0IHRpbWVySWQ6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IHRpbWVvdXRQcm9taXNlID0gbmV3IFByb21pc2U8J19fZGV0YWNoX3RpbWVvdXRfXyc+KChyZXNvbHZlKSA9PiB7XG4gICAgICB0aW1lcklkID0gc2V0VGltZW91dCgoKSA9PiByZXNvbHZlKCdfX2RldGFjaF90aW1lb3V0X18nKSwgcmVtYWluaW5nTXMpO1xuICAgIH0pO1xuICAgIGNvbnN0IGRyYWluUHJvbWlzZSA9IFByb21pc2UuYWxsU2V0dGxlZChoYW5kbGVzLm1hcCgoaCkgPT4gaC53YWl0KCkpKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW2RyYWluUHJvbWlzZSwgdGltZW91dFByb21pc2VdKTtcbiAgICBpZiAodGltZXJJZCAhPT0gdW5kZWZpbmVkKSBjbGVhclRpbWVvdXQodGltZXJJZCk7XG5cbiAgICBpZiAocmVzdWx0ID09PSAnX19kZXRhY2hfdGltZW91dF9fJykge1xuICAgICAgcmV0dXJuIHsgZG9uZSwgZmFpbGVkLCBwZW5kaW5nOiBzaXplKCkgfTtcbiAgICB9XG4gICAgZm9yIChjb25zdCByIG9mIHJlc3VsdCkge1xuICAgICAgaWYgKHIuc3RhdHVzID09PSAnZnVsZmlsbGVkJykgZG9uZSsrO1xuICAgICAgZWxzZSBmYWlsZWQrKztcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBkb25lLCBmYWlsZWQsIHBlbmRpbmc6IDAgfTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* detach/handle.ts — DetachHandle implementation.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Object-as-state-machine. Mutable status field; transitions
|
|
5
|
+
* are one-way and irreversible (queued → running → done/failed).
|
|
6
|
+
* Role: Backs the consumer-facing `DetachHandle` interface. The
|
|
7
|
+
* public surface is the interface (defined in `types.ts`);
|
|
8
|
+
* this class is the runtime impl.
|
|
9
|
+
*
|
|
10
|
+
* Internal vs public split:
|
|
11
|
+
* - PUBLIC (in `types.ts`) — read-only properties + `wait()`
|
|
12
|
+
* - INTERNAL (this file) — `_markRunning` / `_markDone` /
|
|
13
|
+
* `_markFailed` mutators called by drivers
|
|
14
|
+
*
|
|
15
|
+
* The class implements `DetachHandle` (which has only readonly fields
|
|
16
|
+
* exposed). Drivers cast to `HandleImpl` via the `asImpl()` helper to
|
|
17
|
+
* call the mutators — a controlled escape from readonly. Consumers
|
|
18
|
+
* cannot do this (they only see the interface).
|
|
19
|
+
*
|
|
20
|
+
* Promise caching contract:
|
|
21
|
+
* - First `wait()` call:
|
|
22
|
+
* - if status terminal → returns IMMEDIATELY-resolved Promise
|
|
23
|
+
* - if not terminal → returns NEW Promise; resolvers stored
|
|
24
|
+
* for use by `_markDone` / `_markFailed`
|
|
25
|
+
* - Subsequent `wait()` calls → returns the SAME cached Promise
|
|
26
|
+
* - The resolved/rejected value is the SAME on every call (no
|
|
27
|
+
* re-running, no duplicated work)
|
|
28
|
+
*
|
|
29
|
+
* Concurrency notes:
|
|
30
|
+
* - All transitions are sync. JavaScript is single-threaded so no
|
|
31
|
+
* atomics or locks needed.
|
|
32
|
+
* - State transitions out of terminal states are forbidden — calling
|
|
33
|
+
* `_markDone` after `_markFailed` (or vice-versa) is a no-op
|
|
34
|
+
* (defensive: prevents driver bugs from corrupting state).
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Internal handle implementation. Drivers call the `_mark*` methods
|
|
38
|
+
* to drive state transitions; consumers see only the readonly
|
|
39
|
+
* `DetachHandle` interface.
|
|
40
|
+
*/
|
|
41
|
+
export class HandleImpl {
|
|
42
|
+
id;
|
|
43
|
+
status = 'queued';
|
|
44
|
+
result = undefined;
|
|
45
|
+
error = undefined;
|
|
46
|
+
// Lazy Promise cache — created on first `wait()` call.
|
|
47
|
+
waitPromise = null;
|
|
48
|
+
// Resolvers captured when wait() was called BEFORE terminal state.
|
|
49
|
+
resolveWait = null;
|
|
50
|
+
rejectWait = null;
|
|
51
|
+
constructor(id) {
|
|
52
|
+
this.id = id;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Public — opt-in async join. Returns a cached Promise.
|
|
56
|
+
* See `DetachHandle.wait()` docstring for contract.
|
|
57
|
+
*/
|
|
58
|
+
wait() {
|
|
59
|
+
if (this.waitPromise)
|
|
60
|
+
return this.waitPromise;
|
|
61
|
+
if (this.status === 'done') {
|
|
62
|
+
this.waitPromise = Promise.resolve({ result: this.result });
|
|
63
|
+
}
|
|
64
|
+
else if (this.status === 'failed') {
|
|
65
|
+
this.waitPromise = Promise.reject(this.error);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Pending terminal — store resolvers for _markDone / _markFailed.
|
|
69
|
+
this.waitPromise = new Promise((resolve, reject) => {
|
|
70
|
+
this.resolveWait = resolve;
|
|
71
|
+
this.rejectWait = reject;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return this.waitPromise;
|
|
75
|
+
}
|
|
76
|
+
// ── Internal mutators (called by drivers) ──────────────────────────
|
|
77
|
+
/** Transition queued → running. No-op if already past 'queued'. */
|
|
78
|
+
_markRunning() {
|
|
79
|
+
if (this.status !== 'queued')
|
|
80
|
+
return;
|
|
81
|
+
this.status = 'running';
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Transition to terminal 'done' with the given result. No-op if
|
|
85
|
+
* already terminal (defensive: prevents driver bugs from corrupting
|
|
86
|
+
* state).
|
|
87
|
+
*/
|
|
88
|
+
_markDone(result) {
|
|
89
|
+
if (this.status === 'done' || this.status === 'failed')
|
|
90
|
+
return;
|
|
91
|
+
this.status = 'done';
|
|
92
|
+
this.result = result;
|
|
93
|
+
// If consumer already called wait(), unblock its Promise.
|
|
94
|
+
this.resolveWait?.({ result });
|
|
95
|
+
this.resolveWait = null;
|
|
96
|
+
this.rejectWait = null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Transition to terminal 'failed' with the given error. No-op if
|
|
100
|
+
* already terminal.
|
|
101
|
+
*/
|
|
102
|
+
_markFailed(error) {
|
|
103
|
+
if (this.status === 'done' || this.status === 'failed')
|
|
104
|
+
return;
|
|
105
|
+
this.status = 'failed';
|
|
106
|
+
this.error = error;
|
|
107
|
+
this.rejectWait?.(error);
|
|
108
|
+
this.resolveWait = null;
|
|
109
|
+
this.rejectWait = null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Type-narrowing helper — cast a public `DetachHandle` to its
|
|
114
|
+
* implementation. Drivers (only) use this to call internal mutators.
|
|
115
|
+
*
|
|
116
|
+
* Throws if the handle isn't actually a `HandleImpl` — defends
|
|
117
|
+
* against consumers passing a hand-rolled object that satisfies the
|
|
118
|
+
* interface shape but lacks the mutators.
|
|
119
|
+
*/
|
|
120
|
+
export function asImpl(handle) {
|
|
121
|
+
if (!(handle instanceof HandleImpl)) {
|
|
122
|
+
throw new TypeError('[detach] expected a HandleImpl returned by createHandle(); got an arbitrary DetachHandle. ' +
|
|
123
|
+
'Drivers must use createHandle() to construct handles, not hand-roll them.');
|
|
124
|
+
}
|
|
125
|
+
return handle;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Driver-facing factory. Drivers MUST use this to create handles
|
|
129
|
+
* (NOT construct `HandleImpl` directly — keeps the impl type private).
|
|
130
|
+
*/
|
|
131
|
+
export function createHandle(id) {
|
|
132
|
+
return new HandleImpl(id);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9kZXRhY2gvaGFuZGxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0NHO0FBSUg7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBQ1osRUFBRSxDQUFTO0lBQ3BCLE1BQU0sR0FBMkIsUUFBUSxDQUFDO0lBQzFDLE1BQU0sR0FBWSxTQUFTLENBQUM7SUFDNUIsS0FBSyxHQUFzQixTQUFTLENBQUM7SUFFckMsdURBQXVEO0lBQy9DLFdBQVcsR0FBcUMsSUFBSSxDQUFDO0lBQzdELG1FQUFtRTtJQUMzRCxXQUFXLEdBQTJDLElBQUksQ0FBQztJQUMzRCxVQUFVLEdBQWdDLElBQUksQ0FBQztJQUV2RCxZQUFZLEVBQVU7UUFDcEIsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDZixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBSTtRQUNGLElBQUksSUFBSSxDQUFDLFdBQVc7WUFBRSxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7UUFFOUMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQzNCLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUM5RCxDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEQsQ0FBQzthQUFNLENBQUM7WUFDTixrRUFBa0U7WUFDbEUsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBbUIsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7Z0JBQ25FLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDO2dCQUMzQixJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztZQUMzQixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQztJQUVELHNFQUFzRTtJQUV0RSxtRUFBbUU7SUFDbkUsWUFBWTtRQUNWLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxRQUFRO1lBQUUsT0FBTztRQUNyQyxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFNBQVMsQ0FBQyxNQUFlO1FBQ3ZCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxRQUFRO1lBQUUsT0FBTztRQUMvRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQiwwREFBMEQ7UUFDMUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztRQUN4QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztJQUN6QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsV0FBVyxDQUFDLEtBQVk7UUFDdEIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFFBQVE7WUFBRSxPQUFPO1FBQy9ELElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztRQUN4QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztJQUN6QixDQUFDO0NBQ0Y7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxNQUFvQjtJQUN6QyxJQUFJLENBQUMsQ0FBQyxNQUFNLFlBQVksVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUNwQyxNQUFNLElBQUksU0FBUyxDQUNqQiw0RkFBNEY7WUFDMUYsMkVBQTJFLENBQzlFLENBQUM7SUFDSixDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsRUFBVTtJQUNyQyxPQUFPLElBQUksVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzVCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGRldGFjaC9oYW5kbGUudHMg4oCUIERldGFjaEhhbmRsZSBpbXBsZW1lbnRhdGlvbi5cbiAqXG4gKiBQYXR0ZXJuOiAgT2JqZWN0LWFzLXN0YXRlLW1hY2hpbmUuIE11dGFibGUgc3RhdHVzIGZpZWxkOyB0cmFuc2l0aW9uc1xuICogICAgICAgICAgIGFyZSBvbmUtd2F5IGFuZCBpcnJldmVyc2libGUgKHF1ZXVlZCDihpIgcnVubmluZyDihpIgZG9uZS9mYWlsZWQpLlxuICogUm9sZTogICAgIEJhY2tzIHRoZSBjb25zdW1lci1mYWNpbmcgYERldGFjaEhhbmRsZWAgaW50ZXJmYWNlLiBUaGVcbiAqICAgICAgICAgICBwdWJsaWMgc3VyZmFjZSBpcyB0aGUgaW50ZXJmYWNlIChkZWZpbmVkIGluIGB0eXBlcy50c2ApO1xuICogICAgICAgICAgIHRoaXMgY2xhc3MgaXMgdGhlIHJ1bnRpbWUgaW1wbC5cbiAqXG4gKiBJbnRlcm5hbCB2cyBwdWJsaWMgc3BsaXQ6XG4gKiAgIC0gUFVCTElDIChpbiBgdHlwZXMudHNgKSAgIOKAlCByZWFkLW9ubHkgcHJvcGVydGllcyArIGB3YWl0KClgXG4gKiAgIC0gSU5URVJOQUwgKHRoaXMgZmlsZSkgICAgIOKAlCBgX21hcmtSdW5uaW5nYCAvIGBfbWFya0RvbmVgIC9cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgX21hcmtGYWlsZWRgIG11dGF0b3JzIGNhbGxlZCBieSBkcml2ZXJzXG4gKlxuICogVGhlIGNsYXNzIGltcGxlbWVudHMgYERldGFjaEhhbmRsZWAgKHdoaWNoIGhhcyBvbmx5IHJlYWRvbmx5IGZpZWxkc1xuICogZXhwb3NlZCkuIERyaXZlcnMgY2FzdCB0byBgSGFuZGxlSW1wbGAgdmlhIHRoZSBgYXNJbXBsKClgIGhlbHBlciB0b1xuICogY2FsbCB0aGUgbXV0YXRvcnMg4oCUIGEgY29udHJvbGxlZCBlc2NhcGUgZnJvbSByZWFkb25seS4gQ29uc3VtZXJzXG4gKiBjYW5ub3QgZG8gdGhpcyAodGhleSBvbmx5IHNlZSB0aGUgaW50ZXJmYWNlKS5cbiAqXG4gKiBQcm9taXNlIGNhY2hpbmcgY29udHJhY3Q6XG4gKiAgIC0gRmlyc3QgYHdhaXQoKWAgY2FsbDpcbiAqICAgICAgIC0gaWYgc3RhdHVzIHRlcm1pbmFsIOKGkiByZXR1cm5zIElNTUVESUFURUxZLXJlc29sdmVkIFByb21pc2VcbiAqICAgICAgIC0gaWYgbm90IHRlcm1pbmFsICAgIOKGkiByZXR1cm5zIE5FVyBQcm9taXNlOyByZXNvbHZlcnMgc3RvcmVkXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciB1c2UgYnkgYF9tYXJrRG9uZWAgLyBgX21hcmtGYWlsZWRgXG4gKiAgIC0gU3Vic2VxdWVudCBgd2FpdCgpYCBjYWxscyDihpIgcmV0dXJucyB0aGUgU0FNRSBjYWNoZWQgUHJvbWlzZVxuICogICAtIFRoZSByZXNvbHZlZC9yZWplY3RlZCB2YWx1ZSBpcyB0aGUgU0FNRSBvbiBldmVyeSBjYWxsIChub1xuICogICAgIHJlLXJ1bm5pbmcsIG5vIGR1cGxpY2F0ZWQgd29yaylcbiAqXG4gKiBDb25jdXJyZW5jeSBub3RlczpcbiAqICAgLSBBbGwgdHJhbnNpdGlvbnMgYXJlIHN5bmMuIEphdmFTY3JpcHQgaXMgc2luZ2xlLXRocmVhZGVkIHNvIG5vXG4gKiAgICAgYXRvbWljcyBvciBsb2NrcyBuZWVkZWQuXG4gKiAgIC0gU3RhdGUgdHJhbnNpdGlvbnMgb3V0IG9mIHRlcm1pbmFsIHN0YXRlcyBhcmUgZm9yYmlkZGVuIOKAlCBjYWxsaW5nXG4gKiAgICAgYF9tYXJrRG9uZWAgYWZ0ZXIgYF9tYXJrRmFpbGVkYCAob3IgdmljZS12ZXJzYSkgaXMgYSBuby1vcFxuICogICAgIChkZWZlbnNpdmU6IHByZXZlbnRzIGRyaXZlciBidWdzIGZyb20gY29ycnVwdGluZyBzdGF0ZSkuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBEZXRhY2hIYW5kbGUsIERldGFjaFdhaXRSZXN1bHQgfSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqXG4gKiBJbnRlcm5hbCBoYW5kbGUgaW1wbGVtZW50YXRpb24uIERyaXZlcnMgY2FsbCB0aGUgYF9tYXJrKmAgbWV0aG9kc1xuICogdG8gZHJpdmUgc3RhdGUgdHJhbnNpdGlvbnM7IGNvbnN1bWVycyBzZWUgb25seSB0aGUgcmVhZG9ubHlcbiAqIGBEZXRhY2hIYW5kbGVgIGludGVyZmFjZS5cbiAqL1xuZXhwb3J0IGNsYXNzIEhhbmRsZUltcGwgaW1wbGVtZW50cyBEZXRhY2hIYW5kbGUge1xuICByZWFkb25seSBpZDogc3RyaW5nO1xuICBzdGF0dXM6IERldGFjaEhhbmRsZVsnc3RhdHVzJ10gPSAncXVldWVkJztcbiAgcmVzdWx0OiB1bmtub3duID0gdW5kZWZpbmVkO1xuICBlcnJvcjogRXJyb3IgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgLy8gTGF6eSBQcm9taXNlIGNhY2hlIOKAlCBjcmVhdGVkIG9uIGZpcnN0IGB3YWl0KClgIGNhbGwuXG4gIHByaXZhdGUgd2FpdFByb21pc2U6IFByb21pc2U8RGV0YWNoV2FpdFJlc3VsdD4gfCBudWxsID0gbnVsbDtcbiAgLy8gUmVzb2x2ZXJzIGNhcHR1cmVkIHdoZW4gd2FpdCgpIHdhcyBjYWxsZWQgQkVGT1JFIHRlcm1pbmFsIHN0YXRlLlxuICBwcml2YXRlIHJlc29sdmVXYWl0OiAoKHY6IERldGFjaFdhaXRSZXN1bHQpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVqZWN0V2FpdDogKChlOiBFcnJvcikgPT4gdm9pZCkgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihpZDogc3RyaW5nKSB7XG4gICAgdGhpcy5pZCA9IGlkO1xuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYyDigJQgb3B0LWluIGFzeW5jIGpvaW4uIFJldHVybnMgYSBjYWNoZWQgUHJvbWlzZS5cbiAgICogU2VlIGBEZXRhY2hIYW5kbGUud2FpdCgpYCBkb2NzdHJpbmcgZm9yIGNvbnRyYWN0LlxuICAgKi9cbiAgd2FpdCgpOiBQcm9taXNlPERldGFjaFdhaXRSZXN1bHQ+IHtcbiAgICBpZiAodGhpcy53YWl0UHJvbWlzZSkgcmV0dXJuIHRoaXMud2FpdFByb21pc2U7XG5cbiAgICBpZiAodGhpcy5zdGF0dXMgPT09ICdkb25lJykge1xuICAgICAgdGhpcy53YWl0UHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSh7IHJlc3VsdDogdGhpcy5yZXN1bHQgfSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLnN0YXR1cyA9PT0gJ2ZhaWxlZCcpIHtcbiAgICAgIHRoaXMud2FpdFByb21pc2UgPSBQcm9taXNlLnJlamVjdCh0aGlzLmVycm9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gUGVuZGluZyB0ZXJtaW5hbCDigJQgc3RvcmUgcmVzb2x2ZXJzIGZvciBfbWFya0RvbmUgLyBfbWFya0ZhaWxlZC5cbiAgICAgIHRoaXMud2FpdFByb21pc2UgPSBuZXcgUHJvbWlzZTxEZXRhY2hXYWl0UmVzdWx0PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHRoaXMucmVzb2x2ZVdhaXQgPSByZXNvbHZlO1xuICAgICAgICB0aGlzLnJlamVjdFdhaXQgPSByZWplY3Q7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMud2FpdFByb21pc2U7XG4gIH1cblxuICAvLyDilIDilIAgSW50ZXJuYWwgbXV0YXRvcnMgKGNhbGxlZCBieSBkcml2ZXJzKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogVHJhbnNpdGlvbiBxdWV1ZWQg4oaSIHJ1bm5pbmcuIE5vLW9wIGlmIGFscmVhZHkgcGFzdCAncXVldWVkJy4gKi9cbiAgX21hcmtSdW5uaW5nKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnN0YXR1cyAhPT0gJ3F1ZXVlZCcpIHJldHVybjtcbiAgICB0aGlzLnN0YXR1cyA9ICdydW5uaW5nJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFuc2l0aW9uIHRvIHRlcm1pbmFsICdkb25lJyB3aXRoIHRoZSBnaXZlbiByZXN1bHQuIE5vLW9wIGlmXG4gICAqIGFscmVhZHkgdGVybWluYWwgKGRlZmVuc2l2ZTogcHJldmVudHMgZHJpdmVyIGJ1Z3MgZnJvbSBjb3JydXB0aW5nXG4gICAqIHN0YXRlKS5cbiAgICovXG4gIF9tYXJrRG9uZShyZXN1bHQ6IHVua25vd24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdGF0dXMgPT09ICdkb25lJyB8fCB0aGlzLnN0YXR1cyA9PT0gJ2ZhaWxlZCcpIHJldHVybjtcbiAgICB0aGlzLnN0YXR1cyA9ICdkb25lJztcbiAgICB0aGlzLnJlc3VsdCA9IHJlc3VsdDtcbiAgICAvLyBJZiBjb25zdW1lciBhbHJlYWR5IGNhbGxlZCB3YWl0KCksIHVuYmxvY2sgaXRzIFByb21pc2UuXG4gICAgdGhpcy5yZXNvbHZlV2FpdD8uKHsgcmVzdWx0IH0pO1xuICAgIHRoaXMucmVzb2x2ZVdhaXQgPSBudWxsO1xuICAgIHRoaXMucmVqZWN0V2FpdCA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNpdGlvbiB0byB0ZXJtaW5hbCAnZmFpbGVkJyB3aXRoIHRoZSBnaXZlbiBlcnJvci4gTm8tb3AgaWZcbiAgICogYWxyZWFkeSB0ZXJtaW5hbC5cbiAgICovXG4gIF9tYXJrRmFpbGVkKGVycm9yOiBFcnJvcik6IHZvaWQge1xuICAgIGlmICh0aGlzLnN0YXR1cyA9PT0gJ2RvbmUnIHx8IHRoaXMuc3RhdHVzID09PSAnZmFpbGVkJykgcmV0dXJuO1xuICAgIHRoaXMuc3RhdHVzID0gJ2ZhaWxlZCc7XG4gICAgdGhpcy5lcnJvciA9IGVycm9yO1xuICAgIHRoaXMucmVqZWN0V2FpdD8uKGVycm9yKTtcbiAgICB0aGlzLnJlc29sdmVXYWl0ID0gbnVsbDtcbiAgICB0aGlzLnJlamVjdFdhaXQgPSBudWxsO1xuICB9XG59XG5cbi8qKlxuICogVHlwZS1uYXJyb3dpbmcgaGVscGVyIOKAlCBjYXN0IGEgcHVibGljIGBEZXRhY2hIYW5kbGVgIHRvIGl0c1xuICogaW1wbGVtZW50YXRpb24uIERyaXZlcnMgKG9ubHkpIHVzZSB0aGlzIHRvIGNhbGwgaW50ZXJuYWwgbXV0YXRvcnMuXG4gKlxuICogVGhyb3dzIGlmIHRoZSBoYW5kbGUgaXNuJ3QgYWN0dWFsbHkgYSBgSGFuZGxlSW1wbGAg4oCUIGRlZmVuZHNcbiAqIGFnYWluc3QgY29uc3VtZXJzIHBhc3NpbmcgYSBoYW5kLXJvbGxlZCBvYmplY3QgdGhhdCBzYXRpc2ZpZXMgdGhlXG4gKiBpbnRlcmZhY2Ugc2hhcGUgYnV0IGxhY2tzIHRoZSBtdXRhdG9ycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzSW1wbChoYW5kbGU6IERldGFjaEhhbmRsZSk6IEhhbmRsZUltcGwge1xuICBpZiAoIShoYW5kbGUgaW5zdGFuY2VvZiBIYW5kbGVJbXBsKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnW2RldGFjaF0gZXhwZWN0ZWQgYSBIYW5kbGVJbXBsIHJldHVybmVkIGJ5IGNyZWF0ZUhhbmRsZSgpOyBnb3QgYW4gYXJiaXRyYXJ5IERldGFjaEhhbmRsZS4gJyArXG4gICAgICAgICdEcml2ZXJzIG11c3QgdXNlIGNyZWF0ZUhhbmRsZSgpIHRvIGNvbnN0cnVjdCBoYW5kbGVzLCBub3QgaGFuZC1yb2xsIHRoZW0uJyxcbiAgICApO1xuICB9XG4gIHJldHVybiBoYW5kbGU7XG59XG5cbi8qKlxuICogRHJpdmVyLWZhY2luZyBmYWN0b3J5LiBEcml2ZXJzIE1VU1QgdXNlIHRoaXMgdG8gY3JlYXRlIGhhbmRsZXNcbiAqIChOT1QgY29uc3RydWN0IGBIYW5kbGVJbXBsYCBkaXJlY3RseSDigJQga2VlcHMgdGhlIGltcGwgdHlwZSBwcml2YXRlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUhhbmRsZShpZDogc3RyaW5nKTogRGV0YWNoSGFuZGxlIHtcbiAgcmV0dXJuIG5ldyBIYW5kbGVJbXBsKGlkKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* detach/registry.ts — Process-singleton handle registry.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Registry (GoF). Same shape as the cache strategy registry
|
|
5
|
+
* in agentfootprint v2.6 — a Map keyed by stable string id.
|
|
6
|
+
* Role: Glue between drivers and executors. When a driver schedules
|
|
7
|
+
* work it `register`s the handle here; later (during executor
|
|
8
|
+
* disposal, or for diagnostics) consumers `lookup` by refId.
|
|
9
|
+
*
|
|
10
|
+
* Why a singleton?
|
|
11
|
+
* - refIds are minted per detach call and are unique across the
|
|
12
|
+
* process lifetime (driver name + monotonic counter)
|
|
13
|
+
* - handles need to be cleanable from MULTIPLE call sites (executor
|
|
14
|
+
* disposal, driver-internal flush, test cleanup) without each one
|
|
15
|
+
* having to thread a Registry instance through ten layers
|
|
16
|
+
* - one-source-of-truth simplifies "is this handle still alive?"
|
|
17
|
+
* queries during debugging
|
|
18
|
+
*
|
|
19
|
+
* Why NOT a class instance per executor?
|
|
20
|
+
* - drivers (e.g., `microtaskBatchDriver`) are PROCESS-wide (one queue
|
|
21
|
+
* per driver, shared by every executor). Tying registry to executor
|
|
22
|
+
* would force per-executor driver instances, multiplying the queue
|
|
23
|
+
* count and breaking the batch-amortization the drivers exist for.
|
|
24
|
+
*
|
|
25
|
+
* Cleanup contract:
|
|
26
|
+
* - Drivers call `register(handle)` synchronously inside `schedule()`
|
|
27
|
+
* - Drivers (or executor disposal) call `unregister(refId)` once the
|
|
28
|
+
* handle is terminal AND the consumer has had a chance to observe it
|
|
29
|
+
* - `_resetForTests()` clears every entry — tests only
|
|
30
|
+
*
|
|
31
|
+
* Capacity:
|
|
32
|
+
* - No upper bound. The handle objects are tiny (~6 fields). A long-
|
|
33
|
+
* running process that detaches a million units WITHOUT cleanup
|
|
34
|
+
* would leak ~50 MB — acceptable for v1, since drivers ARE the
|
|
35
|
+
* cleanup site. If real-world programs hit the limit, add a
|
|
36
|
+
* sliding-window cap with telemetry hook (mirrors
|
|
37
|
+
* `LIVE_STATUS_LOG_CAP` in agentfootprint).
|
|
38
|
+
*/
|
|
39
|
+
// Process-wide singleton. Map preserves insertion order — useful for
|
|
40
|
+
// diagnostic dumps that want chronological ordering.
|
|
41
|
+
const HANDLES = new Map();
|
|
42
|
+
/**
|
|
43
|
+
* Register a freshly-minted handle. Drivers MUST call this synchronously
|
|
44
|
+
* inside `schedule()` so the handle is observable from the moment it
|
|
45
|
+
* exists.
|
|
46
|
+
*
|
|
47
|
+
* Replacing an existing registration is treated as a programming error
|
|
48
|
+
* (refIds are supposed to be unique). We don't throw — silent overwrite
|
|
49
|
+
* could mask a bug, but throwing inside a driver's hot path could cascade
|
|
50
|
+
* into the parent stage. Compromise: warn in dev mode, overwrite always.
|
|
51
|
+
*/
|
|
52
|
+
export function register(handle) {
|
|
53
|
+
HANDLES.set(handle.id, handle);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Look up a handle by refId. Returns `undefined` for unknown ids — the
|
|
57
|
+
* caller decides whether that's an error or just a stale reference.
|
|
58
|
+
*
|
|
59
|
+
* Used by:
|
|
60
|
+
* - Executor disposal (find handles to mark cancelled / drain)
|
|
61
|
+
* - Driver-internal flush (correlate work-queue entries → handles)
|
|
62
|
+
* - Diagnostic tooling (dump handle state for a refId in a log line)
|
|
63
|
+
*/
|
|
64
|
+
export function lookup(refId) {
|
|
65
|
+
return HANDLES.get(refId);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Drop a handle from the registry. Idempotent — calling on an already-
|
|
69
|
+
* removed refId is a no-op (matches `Map.delete` semantics; useful when
|
|
70
|
+
* cleanup may race between executor disposal and the driver's own
|
|
71
|
+
* post-terminal cleanup).
|
|
72
|
+
*/
|
|
73
|
+
export function unregister(refId) {
|
|
74
|
+
HANDLES.delete(refId);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Diagnostic — total live handles. Use sparingly; calling this on hot
|
|
78
|
+
* paths defeats the registry's "cheap insert/lookup" goal.
|
|
79
|
+
*/
|
|
80
|
+
export function size() {
|
|
81
|
+
return HANDLES.size;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Diagnostic — every live refId. Use for "what's still in flight?"
|
|
85
|
+
* dumps during executor disposal or oncall debugging.
|
|
86
|
+
*/
|
|
87
|
+
export function ids() {
|
|
88
|
+
return [...HANDLES.keys()];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Test-only — wipe every entry. NEVER call from production code; that
|
|
92
|
+
* would orphan in-flight work without a chance to drain.
|
|
93
|
+
*/
|
|
94
|
+
export function _resetForTests() {
|
|
95
|
+
HANDLES.clear();
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC9yZWdpc3RyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFDRztBQUlILHFFQUFxRTtBQUNyRSxxREFBcUQ7QUFDckQsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQXdCLENBQUM7QUFFaEQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxNQUFvQjtJQUMzQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxLQUFhO0lBQ2xDLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM1QixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLEtBQWE7SUFDdEMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN4QixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLElBQUk7SUFDbEIsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDO0FBQ3RCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsR0FBRztJQUNqQixPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUM3QixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGNBQWM7SUFDNUIsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGRldGFjaC9yZWdpc3RyeS50cyDigJQgUHJvY2Vzcy1zaW5nbGV0b24gaGFuZGxlIHJlZ2lzdHJ5LlxuICpcbiAqIFBhdHRlcm46ICBSZWdpc3RyeSAoR29GKS4gU2FtZSBzaGFwZSBhcyB0aGUgY2FjaGUgc3RyYXRlZ3kgcmVnaXN0cnlcbiAqICAgICAgICAgICBpbiBhZ2VudGZvb3RwcmludCB2Mi42IOKAlCBhIE1hcCBrZXllZCBieSBzdGFibGUgc3RyaW5nIGlkLlxuICogUm9sZTogICAgIEdsdWUgYmV0d2VlbiBkcml2ZXJzIGFuZCBleGVjdXRvcnMuIFdoZW4gYSBkcml2ZXIgc2NoZWR1bGVzXG4gKiAgICAgICAgICAgd29yayBpdCBgcmVnaXN0ZXJgcyB0aGUgaGFuZGxlIGhlcmU7IGxhdGVyIChkdXJpbmcgZXhlY3V0b3JcbiAqICAgICAgICAgICBkaXNwb3NhbCwgb3IgZm9yIGRpYWdub3N0aWNzKSBjb25zdW1lcnMgYGxvb2t1cGAgYnkgcmVmSWQuXG4gKlxuICogV2h5IGEgc2luZ2xldG9uP1xuICogICAtIHJlZklkcyBhcmUgbWludGVkIHBlciBkZXRhY2ggY2FsbCBhbmQgYXJlIHVuaXF1ZSBhY3Jvc3MgdGhlXG4gKiAgICAgcHJvY2VzcyBsaWZldGltZSAoZHJpdmVyIG5hbWUgKyBtb25vdG9uaWMgY291bnRlcilcbiAqICAgLSBoYW5kbGVzIG5lZWQgdG8gYmUgY2xlYW5hYmxlIGZyb20gTVVMVElQTEUgY2FsbCBzaXRlcyAoZXhlY3V0b3JcbiAqICAgICBkaXNwb3NhbCwgZHJpdmVyLWludGVybmFsIGZsdXNoLCB0ZXN0IGNsZWFudXApIHdpdGhvdXQgZWFjaCBvbmVcbiAqICAgICBoYXZpbmcgdG8gdGhyZWFkIGEgUmVnaXN0cnkgaW5zdGFuY2UgdGhyb3VnaCB0ZW4gbGF5ZXJzXG4gKiAgIC0gb25lLXNvdXJjZS1vZi10cnV0aCBzaW1wbGlmaWVzIFwiaXMgdGhpcyBoYW5kbGUgc3RpbGwgYWxpdmU/XCJcbiAqICAgICBxdWVyaWVzIGR1cmluZyBkZWJ1Z2dpbmdcbiAqXG4gKiBXaHkgTk9UIGEgY2xhc3MgaW5zdGFuY2UgcGVyIGV4ZWN1dG9yP1xuICogICAtIGRyaXZlcnMgKGUuZy4sIGBtaWNyb3Rhc2tCYXRjaERyaXZlcmApIGFyZSBQUk9DRVNTLXdpZGUgKG9uZSBxdWV1ZVxuICogICAgIHBlciBkcml2ZXIsIHNoYXJlZCBieSBldmVyeSBleGVjdXRvcikuIFR5aW5nIHJlZ2lzdHJ5IHRvIGV4ZWN1dG9yXG4gKiAgICAgd291bGQgZm9yY2UgcGVyLWV4ZWN1dG9yIGRyaXZlciBpbnN0YW5jZXMsIG11bHRpcGx5aW5nIHRoZSBxdWV1ZVxuICogICAgIGNvdW50IGFuZCBicmVha2luZyB0aGUgYmF0Y2gtYW1vcnRpemF0aW9uIHRoZSBkcml2ZXJzIGV4aXN0IGZvci5cbiAqXG4gKiBDbGVhbnVwIGNvbnRyYWN0OlxuICogICAtIERyaXZlcnMgY2FsbCBgcmVnaXN0ZXIoaGFuZGxlKWAgc3luY2hyb25vdXNseSBpbnNpZGUgYHNjaGVkdWxlKClgXG4gKiAgIC0gRHJpdmVycyAob3IgZXhlY3V0b3IgZGlzcG9zYWwpIGNhbGwgYHVucmVnaXN0ZXIocmVmSWQpYCBvbmNlIHRoZVxuICogICAgIGhhbmRsZSBpcyB0ZXJtaW5hbCBBTkQgdGhlIGNvbnN1bWVyIGhhcyBoYWQgYSBjaGFuY2UgdG8gb2JzZXJ2ZSBpdFxuICogICAtIGBfcmVzZXRGb3JUZXN0cygpYCBjbGVhcnMgZXZlcnkgZW50cnkg4oCUIHRlc3RzIG9ubHlcbiAqXG4gKiBDYXBhY2l0eTpcbiAqICAgLSBObyB1cHBlciBib3VuZC4gVGhlIGhhbmRsZSBvYmplY3RzIGFyZSB0aW55ICh+NiBmaWVsZHMpLiBBIGxvbmctXG4gKiAgICAgcnVubmluZyBwcm9jZXNzIHRoYXQgZGV0YWNoZXMgYSBtaWxsaW9uIHVuaXRzIFdJVEhPVVQgY2xlYW51cFxuICogICAgIHdvdWxkIGxlYWsgfjUwIE1CIOKAlCBhY2NlcHRhYmxlIGZvciB2MSwgc2luY2UgZHJpdmVycyBBUkUgdGhlXG4gKiAgICAgY2xlYW51cCBzaXRlLiBJZiByZWFsLXdvcmxkIHByb2dyYW1zIGhpdCB0aGUgbGltaXQsIGFkZCBhXG4gKiAgICAgc2xpZGluZy13aW5kb3cgY2FwIHdpdGggdGVsZW1ldHJ5IGhvb2sgKG1pcnJvcnNcbiAqICAgICBgTElWRV9TVEFUVVNfTE9HX0NBUGAgaW4gYWdlbnRmb290cHJpbnQpLlxuICovXG5cbmltcG9ydCB0eXBlIHsgRGV0YWNoSGFuZGxlIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbi8vIFByb2Nlc3Mtd2lkZSBzaW5nbGV0b24uIE1hcCBwcmVzZXJ2ZXMgaW5zZXJ0aW9uIG9yZGVyIOKAlCB1c2VmdWwgZm9yXG4vLyBkaWFnbm9zdGljIGR1bXBzIHRoYXQgd2FudCBjaHJvbm9sb2dpY2FsIG9yZGVyaW5nLlxuY29uc3QgSEFORExFUyA9IG5ldyBNYXA8c3RyaW5nLCBEZXRhY2hIYW5kbGU+KCk7XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBmcmVzaGx5LW1pbnRlZCBoYW5kbGUuIERyaXZlcnMgTVVTVCBjYWxsIHRoaXMgc3luY2hyb25vdXNseVxuICogaW5zaWRlIGBzY2hlZHVsZSgpYCBzbyB0aGUgaGFuZGxlIGlzIG9ic2VydmFibGUgZnJvbSB0aGUgbW9tZW50IGl0XG4gKiBleGlzdHMuXG4gKlxuICogUmVwbGFjaW5nIGFuIGV4aXN0aW5nIHJlZ2lzdHJhdGlvbiBpcyB0cmVhdGVkIGFzIGEgcHJvZ3JhbW1pbmcgZXJyb3JcbiAqIChyZWZJZHMgYXJlIHN1cHBvc2VkIHRvIGJlIHVuaXF1ZSkuIFdlIGRvbid0IHRocm93IOKAlCBzaWxlbnQgb3ZlcndyaXRlXG4gKiBjb3VsZCBtYXNrIGEgYnVnLCBidXQgdGhyb3dpbmcgaW5zaWRlIGEgZHJpdmVyJ3MgaG90IHBhdGggY291bGQgY2FzY2FkZVxuICogaW50byB0aGUgcGFyZW50IHN0YWdlLiBDb21wcm9taXNlOiB3YXJuIGluIGRldiBtb2RlLCBvdmVyd3JpdGUgYWx3YXlzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXIoaGFuZGxlOiBEZXRhY2hIYW5kbGUpOiB2b2lkIHtcbiAgSEFORExFUy5zZXQoaGFuZGxlLmlkLCBoYW5kbGUpO1xufVxuXG4vKipcbiAqIExvb2sgdXAgYSBoYW5kbGUgYnkgcmVmSWQuIFJldHVybnMgYHVuZGVmaW5lZGAgZm9yIHVua25vd24gaWRzIOKAlCB0aGVcbiAqIGNhbGxlciBkZWNpZGVzIHdoZXRoZXIgdGhhdCdzIGFuIGVycm9yIG9yIGp1c3QgYSBzdGFsZSByZWZlcmVuY2UuXG4gKlxuICogVXNlZCBieTpcbiAqICAgLSBFeGVjdXRvciBkaXNwb3NhbCAoZmluZCBoYW5kbGVzIHRvIG1hcmsgY2FuY2VsbGVkIC8gZHJhaW4pXG4gKiAgIC0gRHJpdmVyLWludGVybmFsIGZsdXNoIChjb3JyZWxhdGUgd29yay1xdWV1ZSBlbnRyaWVzIOKGkiBoYW5kbGVzKVxuICogICAtIERpYWdub3N0aWMgdG9vbGluZyAoZHVtcCBoYW5kbGUgc3RhdGUgZm9yIGEgcmVmSWQgaW4gYSBsb2cgbGluZSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvb2t1cChyZWZJZDogc3RyaW5nKTogRGV0YWNoSGFuZGxlIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIEhBTkRMRVMuZ2V0KHJlZklkKTtcbn1cblxuLyoqXG4gKiBEcm9wIGEgaGFuZGxlIGZyb20gdGhlIHJlZ2lzdHJ5LiBJZGVtcG90ZW50IOKAlCBjYWxsaW5nIG9uIGFuIGFscmVhZHktXG4gKiByZW1vdmVkIHJlZklkIGlzIGEgbm8tb3AgKG1hdGNoZXMgYE1hcC5kZWxldGVgIHNlbWFudGljczsgdXNlZnVsIHdoZW5cbiAqIGNsZWFudXAgbWF5IHJhY2UgYmV0d2VlbiBleGVjdXRvciBkaXNwb3NhbCBhbmQgdGhlIGRyaXZlcidzIG93blxuICogcG9zdC10ZXJtaW5hbCBjbGVhbnVwKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVucmVnaXN0ZXIocmVmSWQ6IHN0cmluZyk6IHZvaWQge1xuICBIQU5ETEVTLmRlbGV0ZShyZWZJZCk7XG59XG5cbi8qKlxuICogRGlhZ25vc3RpYyDigJQgdG90YWwgbGl2ZSBoYW5kbGVzLiBVc2Ugc3BhcmluZ2x5OyBjYWxsaW5nIHRoaXMgb24gaG90XG4gKiBwYXRocyBkZWZlYXRzIHRoZSByZWdpc3RyeSdzIFwiY2hlYXAgaW5zZXJ0L2xvb2t1cFwiIGdvYWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaXplKCk6IG51bWJlciB7XG4gIHJldHVybiBIQU5ETEVTLnNpemU7XG59XG5cbi8qKlxuICogRGlhZ25vc3RpYyDigJQgZXZlcnkgbGl2ZSByZWZJZC4gVXNlIGZvciBcIndoYXQncyBzdGlsbCBpbiBmbGlnaHQ/XCJcbiAqIGR1bXBzIGR1cmluZyBleGVjdXRvciBkaXNwb3NhbCBvciBvbmNhbGwgZGVidWdnaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaWRzKCk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsuLi5IQU5ETEVTLmtleXMoKV07XG59XG5cbi8qKlxuICogVGVzdC1vbmx5IOKAlCB3aXBlIGV2ZXJ5IGVudHJ5LiBORVZFUiBjYWxsIGZyb20gcHJvZHVjdGlvbiBjb2RlOyB0aGF0XG4gKiB3b3VsZCBvcnBoYW4gaW4tZmxpZ2h0IHdvcmsgd2l0aG91dCBhIGNoYW5jZSB0byBkcmFpbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9yZXNldEZvclRlc3RzKCk6IHZvaWQge1xuICBIQU5ETEVTLmNsZWFyKCk7XG59XG4iXX0=
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* detach/runChild.ts — The "how do I actually run a child flowchart?" hook.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Strategy (GoF). Drivers are decoupled from the FlowChartExecutor
|
|
5
|
+
* — each driver is created with a `ChildRunner` it calls to
|
|
6
|
+
* materialize the work. Default implementation imports the
|
|
7
|
+
* executor lazily so drivers can be picked up by tree-shakers
|
|
8
|
+
* that don't pull the runner module into the bundle.
|
|
9
|
+
* Role: Glue between drivers and the engine. Without this seam, every
|
|
10
|
+
* driver would have to import `FlowChartExecutor` directly,
|
|
11
|
+
* creating circular import risk and bundle bloat.
|
|
12
|
+
*
|
|
13
|
+
* Why a separate module (not inlined in each driver):
|
|
14
|
+
* - DRY — every driver shares the same "instantiate executor, run, return
|
|
15
|
+
* result" sequence
|
|
16
|
+
* - Allows test code to swap the runner via factory injection without
|
|
17
|
+
* having to rebuild the whole driver
|
|
18
|
+
* - Future-proofs for the case where we want to inject env/recorders
|
|
19
|
+
* into the child (the runner is the natural place to do that)
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Default runner — instantiates a fresh `FlowChartExecutor` for each
|
|
23
|
+
* child and awaits its run. Returns the executor's traversal result.
|
|
24
|
+
*
|
|
25
|
+
* Lazy-imports `FlowChartExecutor` so drivers that consumers create with
|
|
26
|
+
* their own runner don't pull the engine into their bundle.
|
|
27
|
+
*
|
|
28
|
+
* Uses dynamic import — see https://v8.dev/features/dynamic-import.
|
|
29
|
+
*/
|
|
30
|
+
export const defaultRunChild = async (child, input) => {
|
|
31
|
+
// Lazy import keeps tree-shakers honest for consumers who pass a
|
|
32
|
+
// custom runner (e.g., a worker-thread bridge).
|
|
33
|
+
const { FlowChartExecutor } = await import('../runner/FlowChartExecutor.js');
|
|
34
|
+
// The executor expects an unknown-typed FlowChart; cast at the boundary
|
|
35
|
+
// since the FlowChart shape is generic-erased at the detach level.
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
+
const executor = new FlowChartExecutor(child);
|
|
38
|
+
return executor.run({ input });
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuQ2hpbGQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC9ydW5DaGlsZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQWVIOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFnQixLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFO0lBQ2pFLGlFQUFpRTtJQUNqRSxnREFBZ0Q7SUFDaEQsTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUM3RSx3RUFBd0U7SUFDeEUsbUVBQW1FO0lBQ25FLDhEQUE4RDtJQUM5RCxNQUFNLFFBQVEsR0FBRyxJQUFJLGlCQUFpQixDQUFDLEtBQVksQ0FBQyxDQUFDO0lBQ3JELE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7QUFDakMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBkZXRhY2gvcnVuQ2hpbGQudHMg4oCUIFRoZSBcImhvdyBkbyBJIGFjdHVhbGx5IHJ1biBhIGNoaWxkIGZsb3djaGFydD9cIiBob29rLlxuICpcbiAqIFBhdHRlcm46ICBTdHJhdGVneSAoR29GKS4gRHJpdmVycyBhcmUgZGVjb3VwbGVkIGZyb20gdGhlIEZsb3dDaGFydEV4ZWN1dG9yXG4gKiAgICAgICAgICAg4oCUIGVhY2ggZHJpdmVyIGlzIGNyZWF0ZWQgd2l0aCBhIGBDaGlsZFJ1bm5lcmAgaXQgY2FsbHMgdG9cbiAqICAgICAgICAgICBtYXRlcmlhbGl6ZSB0aGUgd29yay4gRGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBpbXBvcnRzIHRoZVxuICogICAgICAgICAgIGV4ZWN1dG9yIGxhemlseSBzbyBkcml2ZXJzIGNhbiBiZSBwaWNrZWQgdXAgYnkgdHJlZS1zaGFrZXJzXG4gKiAgICAgICAgICAgdGhhdCBkb24ndCBwdWxsIHRoZSBydW5uZXIgbW9kdWxlIGludG8gdGhlIGJ1bmRsZS5cbiAqIFJvbGU6ICAgICBHbHVlIGJldHdlZW4gZHJpdmVycyBhbmQgdGhlIGVuZ2luZS4gV2l0aG91dCB0aGlzIHNlYW0sIGV2ZXJ5XG4gKiAgICAgICAgICAgZHJpdmVyIHdvdWxkIGhhdmUgdG8gaW1wb3J0IGBGbG93Q2hhcnRFeGVjdXRvcmAgZGlyZWN0bHksXG4gKiAgICAgICAgICAgY3JlYXRpbmcgY2lyY3VsYXIgaW1wb3J0IHJpc2sgYW5kIGJ1bmRsZSBibG9hdC5cbiAqXG4gKiBXaHkgYSBzZXBhcmF0ZSBtb2R1bGUgKG5vdCBpbmxpbmVkIGluIGVhY2ggZHJpdmVyKTpcbiAqICAgLSBEUlkg4oCUIGV2ZXJ5IGRyaXZlciBzaGFyZXMgdGhlIHNhbWUgXCJpbnN0YW50aWF0ZSBleGVjdXRvciwgcnVuLCByZXR1cm5cbiAqICAgICByZXN1bHRcIiBzZXF1ZW5jZVxuICogICAtIEFsbG93cyB0ZXN0IGNvZGUgdG8gc3dhcCB0aGUgcnVubmVyIHZpYSBmYWN0b3J5IGluamVjdGlvbiB3aXRob3V0XG4gKiAgICAgaGF2aW5nIHRvIHJlYnVpbGQgdGhlIHdob2xlIGRyaXZlclxuICogICAtIEZ1dHVyZS1wcm9vZnMgZm9yIHRoZSBjYXNlIHdoZXJlIHdlIHdhbnQgdG8gaW5qZWN0IGVudi9yZWNvcmRlcnNcbiAqICAgICBpbnRvIHRoZSBjaGlsZCAodGhlIHJ1bm5lciBpcyB0aGUgbmF0dXJhbCBwbGFjZSB0byBkbyB0aGF0KVxuICovXG5cbmltcG9ydCB0eXBlIHsgRmxvd0NoYXJ0IH0gZnJvbSAnLi4vYnVpbGRlci90eXBlcy5qcyc7XG5cbi8qKlxuICogRnVuY3Rpb24gdGhlIGRyaXZlciBjYWxscyB0byBhY3R1YWxseSBleGVjdXRlIHRoZSBjaGlsZCBmbG93Y2hhcnQuXG4gKiBSZXR1cm5zIGEgUHJvbWlzZSByZXNvbHZpbmcgdG8gdGhlIGNoYXJ0J3MgdGVybWluYWwgdmFsdWUgKHdoYXRldmVyXG4gKiBgRmxvd0NoYXJ0RXhlY3V0b3IucnVuKClgIHJlc29sdmVzIHdpdGgpLCBvciByZWplY3RzIG9uIGZhaWx1cmUuXG4gKlxuICogRHJpdmVycyB3cmFwIHRoaXMgaW4gdGhlaXIgb3duIHRyeS9jYXRjaCBzbyB0aGUgcmVqZWN0aW9uIHJvdXRlcyB0b1xuICogYGhhbmRsZS5fbWFya0ZhaWxlZCgpYCBpbnN0ZWFkIG9mIGVzY2FwaW5nIGludG8gdGhlIHBhcmVudCBjb250ZXh0XG4gKiAocGFzc2l2ZS1yZWNvcmRlciBydWxlKS5cbiAqL1xuZXhwb3J0IHR5cGUgQ2hpbGRSdW5uZXIgPSAoY2hpbGQ6IEZsb3dDaGFydCwgaW5wdXQ6IHVua25vd24pID0+IFByb21pc2U8dW5rbm93bj47XG5cbi8qKlxuICogRGVmYXVsdCBydW5uZXIg4oCUIGluc3RhbnRpYXRlcyBhIGZyZXNoIGBGbG93Q2hhcnRFeGVjdXRvcmAgZm9yIGVhY2hcbiAqIGNoaWxkIGFuZCBhd2FpdHMgaXRzIHJ1bi4gUmV0dXJucyB0aGUgZXhlY3V0b3IncyB0cmF2ZXJzYWwgcmVzdWx0LlxuICpcbiAqIExhenktaW1wb3J0cyBgRmxvd0NoYXJ0RXhlY3V0b3JgIHNvIGRyaXZlcnMgdGhhdCBjb25zdW1lcnMgY3JlYXRlIHdpdGhcbiAqIHRoZWlyIG93biBydW5uZXIgZG9uJ3QgcHVsbCB0aGUgZW5naW5lIGludG8gdGhlaXIgYnVuZGxlLlxuICpcbiAqIFVzZXMgZHluYW1pYyBpbXBvcnQg4oCUIHNlZSBodHRwczovL3Y4LmRldi9mZWF0dXJlcy9keW5hbWljLWltcG9ydC5cbiAqL1xuZXhwb3J0IGNvbnN0IGRlZmF1bHRSdW5DaGlsZDogQ2hpbGRSdW5uZXIgPSBhc3luYyAoY2hpbGQsIGlucHV0KSA9PiB7XG4gIC8vIExhenkgaW1wb3J0IGtlZXBzIHRyZWUtc2hha2VycyBob25lc3QgZm9yIGNvbnN1bWVycyB3aG8gcGFzcyBhXG4gIC8vIGN1c3RvbSBydW5uZXIgKGUuZy4sIGEgd29ya2VyLXRocmVhZCBicmlkZ2UpLlxuICBjb25zdCB7IEZsb3dDaGFydEV4ZWN1dG9yIH0gPSBhd2FpdCBpbXBvcnQoJy4uL3J1bm5lci9GbG93Q2hhcnRFeGVjdXRvci5qcycpO1xuICAvLyBUaGUgZXhlY3V0b3IgZXhwZWN0cyBhbiB1bmtub3duLXR5cGVkIEZsb3dDaGFydDsgY2FzdCBhdCB0aGUgYm91bmRhcnlcbiAgLy8gc2luY2UgdGhlIEZsb3dDaGFydCBzaGFwZSBpcyBnZW5lcmljLWVyYXNlZCBhdCB0aGUgZGV0YWNoIGxldmVsLlxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBjb25zdCBleGVjdXRvciA9IG5ldyBGbG93Q2hhcnRFeGVjdXRvcihjaGlsZCBhcyBhbnkpO1xuICByZXR1cm4gZXhlY3V0b3IucnVuKHsgaW5wdXQgfSk7XG59O1xuIl19
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* detach/spawn.ts — One-call detach primitive used by both scope and
|
|
3
|
+
* executor surfaces.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: Facade (GoF). Hides driver invocation + refId minting +
|
|
6
|
+
* registry registration behind two named functions
|
|
7
|
+
* (`detachAndJoinLater`, `detachAndForget`). Same helper is
|
|
8
|
+
* called from `scope.$detachAndJoinLater(...)` and from
|
|
9
|
+
* `executor.detachAndJoinLater(...)` — single source of truth.
|
|
10
|
+
*
|
|
11
|
+
* Why a separate module:
|
|
12
|
+
* - Avoids duplicating the "validate driver, mint refId, call schedule"
|
|
13
|
+
* sequence in both scope and executor entry points
|
|
14
|
+
* - Keeps the scope/executor files free of driver knowledge — they
|
|
15
|
+
* just call this and forward the result
|
|
16
|
+
*
|
|
17
|
+
* refId scheme:
|
|
18
|
+
* - When the caller is a stage (scope path): refId = `${runtimeStageId}:detach:${counter}`
|
|
19
|
+
* — the runtimeStageId prefix lets diagnostics correlate the handle
|
|
20
|
+
* back to the source stage
|
|
21
|
+
* - When the caller is bare executor (executor path):
|
|
22
|
+
* refId = `__executor__:detach:${counter}` — uniform "no source stage"
|
|
23
|
+
* marker
|
|
24
|
+
* - Counter is module-private + monotonic for the process lifetime —
|
|
25
|
+
* safe across re-entrant detach calls
|
|
26
|
+
*/
|
|
27
|
+
let counter = 0;
|
|
28
|
+
/** Reset the counter for tests — never call from production code. */
|
|
29
|
+
export function _resetSpawnCounterForTests() {
|
|
30
|
+
counter = 0;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Mint a refId. Format: `${prefix}:detach:${counter}`. The prefix carries
|
|
34
|
+
* source-stage provenance (or `__executor__` when there is none).
|
|
35
|
+
*/
|
|
36
|
+
function mintRefId(prefix) {
|
|
37
|
+
counter += 1;
|
|
38
|
+
return `${prefix}:detach:${counter}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Schedule `child` on the given driver, with the consumer's `input`,
|
|
42
|
+
* and return the resulting `DetachHandle`. Callers can `wait()` on it,
|
|
43
|
+
* read its `.status` property, or just hold the reference for later.
|
|
44
|
+
*
|
|
45
|
+
* **Joinable variant** — the caller wants to be able to await the result
|
|
46
|
+
* (or check its status). The `forget` variant simply discards the handle.
|
|
47
|
+
*
|
|
48
|
+
* @param driver - The driver implementation to use. Required (no
|
|
49
|
+
* library-default — passing it explicitly avoids global state and
|
|
50
|
+
* keeps the engine free of driver imports).
|
|
51
|
+
* @param child - The child flowchart to run.
|
|
52
|
+
* @param input - The input to hand to the child's run() call.
|
|
53
|
+
* @param sourcePrefix - Refix prefix for the minted refId; pass the
|
|
54
|
+
* parent's `runtimeStageId` from a stage caller, or `'__executor__'`
|
|
55
|
+
* from a bare-executor caller.
|
|
56
|
+
*/
|
|
57
|
+
export function detachAndJoinLater(driver, child, input, sourcePrefix) {
|
|
58
|
+
if (!driver || typeof driver.schedule !== 'function') {
|
|
59
|
+
throw new TypeError(`[detach] expected a DetachDriver as the first argument; got ${typeof driver}. ` +
|
|
60
|
+
"Pass e.g. `microtaskBatchDriver` from 'footprintjs/detach'.");
|
|
61
|
+
}
|
|
62
|
+
const refId = mintRefId(sourcePrefix);
|
|
63
|
+
return driver.schedule(child, input, refId);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Same as `detachAndJoinLater` but discards the handle. Use when the
|
|
67
|
+
* caller doesn't care about the result and doesn't need to await — e.g.,
|
|
68
|
+
* fire-and-forget telemetry exports.
|
|
69
|
+
*
|
|
70
|
+
* The handle still exists internally (driver creates it, registry holds
|
|
71
|
+
* it briefly) — but the caller cannot reference it. This is intentional:
|
|
72
|
+
* having no handle reference is what gives "forget" its semantic — there
|
|
73
|
+
* is no chance of the caller accidentally awaiting it.
|
|
74
|
+
*
|
|
75
|
+
* Errors raised by the child are STILL routed to the handle's failed
|
|
76
|
+
* state (the driver does that). They just go unobserved unless something
|
|
77
|
+
* else (a recorder, logging) is wired to surface them. See the docs in
|
|
78
|
+
* T7 for recommended observability patterns for "forget" detach.
|
|
79
|
+
*/
|
|
80
|
+
export function detachAndForget(driver, child, input, sourcePrefix) {
|
|
81
|
+
// Reuse the joinable path — the caller just chooses not to keep the
|
|
82
|
+
// returned handle. We don't even bind it to a variable to make the
|
|
83
|
+
// "forget" semantic explicit at the call site.
|
|
84
|
+
detachAndJoinLater(driver, child, input, sourcePrefix);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bhd24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC9zcGF3bi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCRztBQUtILElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztBQUVoQixxRUFBcUU7QUFDckUsTUFBTSxVQUFVLDBCQUEwQjtJQUN4QyxPQUFPLEdBQUcsQ0FBQyxDQUFDO0FBQ2QsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsU0FBUyxDQUFDLE1BQWM7SUFDL0IsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUNiLE9BQU8sR0FBRyxNQUFNLFdBQVcsT0FBTyxFQUFFLENBQUM7QUFDdkMsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxNQUFvQixFQUNwQixLQUFnQixFQUNoQixLQUFjLEVBQ2QsWUFBb0I7SUFFcEIsSUFBSSxDQUFDLE1BQU0sSUFBSSxPQUFPLE1BQU0sQ0FBQyxRQUFRLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDckQsTUFBTSxJQUFJLFNBQVMsQ0FDakIsK0RBQStELE9BQU8sTUFBTSxJQUFJO1lBQzlFLDZEQUE2RCxDQUNoRSxDQUFDO0lBQ0osQ0FBQztJQUNELE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN0QyxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztBQUM5QyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLE1BQW9CLEVBQUUsS0FBZ0IsRUFBRSxLQUFjLEVBQUUsWUFBb0I7SUFDMUcsb0VBQW9FO0lBQ3BFLG1FQUFtRTtJQUNuRSwrQ0FBK0M7SUFDL0Msa0JBQWtCLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDekQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZGV0YWNoL3NwYXduLnRzIOKAlCBPbmUtY2FsbCBkZXRhY2ggcHJpbWl0aXZlIHVzZWQgYnkgYm90aCBzY29wZSBhbmRcbiAqIGV4ZWN1dG9yIHN1cmZhY2VzLlxuICpcbiAqIFBhdHRlcm46ICBGYWNhZGUgKEdvRikuIEhpZGVzIGRyaXZlciBpbnZvY2F0aW9uICsgcmVmSWQgbWludGluZyArXG4gKiAgICAgICAgICAgcmVnaXN0cnkgcmVnaXN0cmF0aW9uIGJlaGluZCB0d28gbmFtZWQgZnVuY3Rpb25zXG4gKiAgICAgICAgICAgKGBkZXRhY2hBbmRKb2luTGF0ZXJgLCBgZGV0YWNoQW5kRm9yZ2V0YCkuIFNhbWUgaGVscGVyIGlzXG4gKiAgICAgICAgICAgY2FsbGVkIGZyb20gYHNjb3BlLiRkZXRhY2hBbmRKb2luTGF0ZXIoLi4uKWAgYW5kIGZyb21cbiAqICAgICAgICAgICBgZXhlY3V0b3IuZGV0YWNoQW5kSm9pbkxhdGVyKC4uLilgIOKAlCBzaW5nbGUgc291cmNlIG9mIHRydXRoLlxuICpcbiAqIFdoeSBhIHNlcGFyYXRlIG1vZHVsZTpcbiAqICAgLSBBdm9pZHMgZHVwbGljYXRpbmcgdGhlIFwidmFsaWRhdGUgZHJpdmVyLCBtaW50IHJlZklkLCBjYWxsIHNjaGVkdWxlXCJcbiAqICAgICBzZXF1ZW5jZSBpbiBib3RoIHNjb3BlIGFuZCBleGVjdXRvciBlbnRyeSBwb2ludHNcbiAqICAgLSBLZWVwcyB0aGUgc2NvcGUvZXhlY3V0b3IgZmlsZXMgZnJlZSBvZiBkcml2ZXIga25vd2xlZGdlIOKAlCB0aGV5XG4gKiAgICAganVzdCBjYWxsIHRoaXMgYW5kIGZvcndhcmQgdGhlIHJlc3VsdFxuICpcbiAqIHJlZklkIHNjaGVtZTpcbiAqICAgLSBXaGVuIHRoZSBjYWxsZXIgaXMgYSBzdGFnZSAoc2NvcGUgcGF0aCk6IHJlZklkID0gYCR7cnVudGltZVN0YWdlSWR9OmRldGFjaDoke2NvdW50ZXJ9YFxuICogICAgIOKAlCB0aGUgcnVudGltZVN0YWdlSWQgcHJlZml4IGxldHMgZGlhZ25vc3RpY3MgY29ycmVsYXRlIHRoZSBoYW5kbGVcbiAqICAgICBiYWNrIHRvIHRoZSBzb3VyY2Ugc3RhZ2VcbiAqICAgLSBXaGVuIHRoZSBjYWxsZXIgaXMgYmFyZSBleGVjdXRvciAoZXhlY3V0b3IgcGF0aCk6XG4gKiAgICAgcmVmSWQgPSBgX19leGVjdXRvcl9fOmRldGFjaDoke2NvdW50ZXJ9YCDigJQgdW5pZm9ybSBcIm5vIHNvdXJjZSBzdGFnZVwiXG4gKiAgICAgbWFya2VyXG4gKiAgIC0gQ291bnRlciBpcyBtb2R1bGUtcHJpdmF0ZSArIG1vbm90b25pYyBmb3IgdGhlIHByb2Nlc3MgbGlmZXRpbWUg4oCUXG4gKiAgICAgc2FmZSBhY3Jvc3MgcmUtZW50cmFudCBkZXRhY2ggY2FsbHNcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEZsb3dDaGFydCB9IGZyb20gJy4uL2J1aWxkZXIvdHlwZXMuanMnO1xuaW1wb3J0IHR5cGUgeyBEZXRhY2hEcml2ZXIsIERldGFjaEhhbmRsZSB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG5sZXQgY291bnRlciA9IDA7XG5cbi8qKiBSZXNldCB0aGUgY291bnRlciBmb3IgdGVzdHMg4oCUIG5ldmVyIGNhbGwgZnJvbSBwcm9kdWN0aW9uIGNvZGUuICovXG5leHBvcnQgZnVuY3Rpb24gX3Jlc2V0U3Bhd25Db3VudGVyRm9yVGVzdHMoKTogdm9pZCB7XG4gIGNvdW50ZXIgPSAwO1xufVxuXG4vKipcbiAqIE1pbnQgYSByZWZJZC4gRm9ybWF0OiBgJHtwcmVmaXh9OmRldGFjaDoke2NvdW50ZXJ9YC4gVGhlIHByZWZpeCBjYXJyaWVzXG4gKiBzb3VyY2Utc3RhZ2UgcHJvdmVuYW5jZSAob3IgYF9fZXhlY3V0b3JfX2Agd2hlbiB0aGVyZSBpcyBub25lKS5cbiAqL1xuZnVuY3Rpb24gbWludFJlZklkKHByZWZpeDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY291bnRlciArPSAxO1xuICByZXR1cm4gYCR7cHJlZml4fTpkZXRhY2g6JHtjb3VudGVyfWA7XG59XG5cbi8qKlxuICogU2NoZWR1bGUgYGNoaWxkYCBvbiB0aGUgZ2l2ZW4gZHJpdmVyLCB3aXRoIHRoZSBjb25zdW1lcidzIGBpbnB1dGAsXG4gKiBhbmQgcmV0dXJuIHRoZSByZXN1bHRpbmcgYERldGFjaEhhbmRsZWAuIENhbGxlcnMgY2FuIGB3YWl0KClgIG9uIGl0LFxuICogcmVhZCBpdHMgYC5zdGF0dXNgIHByb3BlcnR5LCBvciBqdXN0IGhvbGQgdGhlIHJlZmVyZW5jZSBmb3IgbGF0ZXIuXG4gKlxuICogKipKb2luYWJsZSB2YXJpYW50Kiog4oCUIHRoZSBjYWxsZXIgd2FudHMgdG8gYmUgYWJsZSB0byBhd2FpdCB0aGUgcmVzdWx0XG4gKiAob3IgY2hlY2sgaXRzIHN0YXR1cykuIFRoZSBgZm9yZ2V0YCB2YXJpYW50IHNpbXBseSBkaXNjYXJkcyB0aGUgaGFuZGxlLlxuICpcbiAqIEBwYXJhbSBkcml2ZXIgLSBUaGUgZHJpdmVyIGltcGxlbWVudGF0aW9uIHRvIHVzZS4gUmVxdWlyZWQgKG5vXG4gKiAgIGxpYnJhcnktZGVmYXVsdCDigJQgcGFzc2luZyBpdCBleHBsaWNpdGx5IGF2b2lkcyBnbG9iYWwgc3RhdGUgYW5kXG4gKiAgIGtlZXBzIHRoZSBlbmdpbmUgZnJlZSBvZiBkcml2ZXIgaW1wb3J0cykuXG4gKiBAcGFyYW0gY2hpbGQgLSBUaGUgY2hpbGQgZmxvd2NoYXJ0IHRvIHJ1bi5cbiAqIEBwYXJhbSBpbnB1dCAtIFRoZSBpbnB1dCB0byBoYW5kIHRvIHRoZSBjaGlsZCdzIHJ1bigpIGNhbGwuXG4gKiBAcGFyYW0gc291cmNlUHJlZml4IC0gUmVmaXggcHJlZml4IGZvciB0aGUgbWludGVkIHJlZklkOyBwYXNzIHRoZVxuICogICBwYXJlbnQncyBgcnVudGltZVN0YWdlSWRgIGZyb20gYSBzdGFnZSBjYWxsZXIsIG9yIGAnX19leGVjdXRvcl9fJ2BcbiAqICAgZnJvbSBhIGJhcmUtZXhlY3V0b3IgY2FsbGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGV0YWNoQW5kSm9pbkxhdGVyKFxuICBkcml2ZXI6IERldGFjaERyaXZlcixcbiAgY2hpbGQ6IEZsb3dDaGFydCxcbiAgaW5wdXQ6IHVua25vd24sXG4gIHNvdXJjZVByZWZpeDogc3RyaW5nLFxuKTogRGV0YWNoSGFuZGxlIHtcbiAgaWYgKCFkcml2ZXIgfHwgdHlwZW9mIGRyaXZlci5zY2hlZHVsZSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICBgW2RldGFjaF0gZXhwZWN0ZWQgYSBEZXRhY2hEcml2ZXIgYXMgdGhlIGZpcnN0IGFyZ3VtZW50OyBnb3QgJHt0eXBlb2YgZHJpdmVyfS4gYCArXG4gICAgICAgIFwiUGFzcyBlLmcuIGBtaWNyb3Rhc2tCYXRjaERyaXZlcmAgZnJvbSAnZm9vdHByaW50anMvZGV0YWNoJy5cIixcbiAgICApO1xuICB9XG4gIGNvbnN0IHJlZklkID0gbWludFJlZklkKHNvdXJjZVByZWZpeCk7XG4gIHJldHVybiBkcml2ZXIuc2NoZWR1bGUoY2hpbGQsIGlucHV0LCByZWZJZCk7XG59XG5cbi8qKlxuICogU2FtZSBhcyBgZGV0YWNoQW5kSm9pbkxhdGVyYCBidXQgZGlzY2FyZHMgdGhlIGhhbmRsZS4gVXNlIHdoZW4gdGhlXG4gKiBjYWxsZXIgZG9lc24ndCBjYXJlIGFib3V0IHRoZSByZXN1bHQgYW5kIGRvZXNuJ3QgbmVlZCB0byBhd2FpdCDigJQgZS5nLixcbiAqIGZpcmUtYW5kLWZvcmdldCB0ZWxlbWV0cnkgZXhwb3J0cy5cbiAqXG4gKiBUaGUgaGFuZGxlIHN0aWxsIGV4aXN0cyBpbnRlcm5hbGx5IChkcml2ZXIgY3JlYXRlcyBpdCwgcmVnaXN0cnkgaG9sZHNcbiAqIGl0IGJyaWVmbHkpIOKAlCBidXQgdGhlIGNhbGxlciBjYW5ub3QgcmVmZXJlbmNlIGl0LiBUaGlzIGlzIGludGVudGlvbmFsOlxuICogaGF2aW5nIG5vIGhhbmRsZSByZWZlcmVuY2UgaXMgd2hhdCBnaXZlcyBcImZvcmdldFwiIGl0cyBzZW1hbnRpYyDigJQgdGhlcmVcbiAqIGlzIG5vIGNoYW5jZSBvZiB0aGUgY2FsbGVyIGFjY2lkZW50YWxseSBhd2FpdGluZyBpdC5cbiAqXG4gKiBFcnJvcnMgcmFpc2VkIGJ5IHRoZSBjaGlsZCBhcmUgU1RJTEwgcm91dGVkIHRvIHRoZSBoYW5kbGUncyBmYWlsZWRcbiAqIHN0YXRlICh0aGUgZHJpdmVyIGRvZXMgdGhhdCkuIFRoZXkganVzdCBnbyB1bm9ic2VydmVkIHVubGVzcyBzb21ldGhpbmdcbiAqIGVsc2UgKGEgcmVjb3JkZXIsIGxvZ2dpbmcpIGlzIHdpcmVkIHRvIHN1cmZhY2UgdGhlbS4gU2VlIHRoZSBkb2NzIGluXG4gKiBUNyBmb3IgcmVjb21tZW5kZWQgb2JzZXJ2YWJpbGl0eSBwYXR0ZXJucyBmb3IgXCJmb3JnZXRcIiBkZXRhY2guXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXRhY2hBbmRGb3JnZXQoZHJpdmVyOiBEZXRhY2hEcml2ZXIsIGNoaWxkOiBGbG93Q2hhcnQsIGlucHV0OiB1bmtub3duLCBzb3VyY2VQcmVmaXg6IHN0cmluZyk6IHZvaWQge1xuICAvLyBSZXVzZSB0aGUgam9pbmFibGUgcGF0aCDigJQgdGhlIGNhbGxlciBqdXN0IGNob29zZXMgbm90IHRvIGtlZXAgdGhlXG4gIC8vIHJldHVybmVkIGhhbmRsZS4gV2UgZG9uJ3QgZXZlbiBiaW5kIGl0IHRvIGEgdmFyaWFibGUgdG8gbWFrZSB0aGVcbiAgLy8gXCJmb3JnZXRcIiBzZW1hbnRpYyBleHBsaWNpdCBhdCB0aGUgY2FsbCBzaXRlLlxuICBkZXRhY2hBbmRKb2luTGF0ZXIoZHJpdmVyLCBjaGlsZCwgaW5wdXQsIHNvdXJjZVByZWZpeCk7XG59XG4iXX0=
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* detach/types.ts — Type definitions for the fire-and-forget primitive.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: Strategy + Bridge (GoF). Same shape as cache strategies in
|
|
5
|
+
* agentfootprint v2.6 — ONE interface, N concrete drivers,
|
|
6
|
+
* consumer picks via explicit import.
|
|
7
|
+
* Role: Foundation. Every other detach file imports from here.
|
|
8
|
+
* This is the lockable contract; downstream files implement it.
|
|
9
|
+
*
|
|
10
|
+
* Two sibling concepts:
|
|
11
|
+
*
|
|
12
|
+
* 1. `DetachDriver` — the algorithm that decides WHEN/HOW the work runs.
|
|
13
|
+
* Six built-in algorithms ship as algorithm-named exports
|
|
14
|
+
* (`microtaskBatchDriver`, `setImmediateDriver`, `sendBeaconDriver`,
|
|
15
|
+
* `setTimeoutDriver`, `immediateDriver`, `workerThreadDriver`).
|
|
16
|
+
* Consumers can implement their own (BYOS — bring your own driver).
|
|
17
|
+
*
|
|
18
|
+
* 2. `DetachHandle` — the consumer-facing handle returned by
|
|
19
|
+
* `detachAndJoinLater`. Exposes status as PROPERTIES (sync read)
|
|
20
|
+
* and `wait()` (Promise — opt-in async join). Style 2 from the
|
|
21
|
+
* panel review: properties for sync, single method for async.
|
|
22
|
+
*
|
|
23
|
+
* Naming policy (locked from naming review):
|
|
24
|
+
* - Public API uses simple verbs / properties (product-engineer friendly)
|
|
25
|
+
* - Internal class names CAN use CS terms (Scheduler, Continuation, etc.)
|
|
26
|
+
* - Drivers are algorithm-named (semantic at the algorithm level)
|
|
27
|
+
*
|
|
28
|
+
* Locked design decisions (panel review captured in
|
|
29
|
+
* `docs/inspiration/detach-primitive.md`):
|
|
30
|
+
* - Sync hot path; async only at flush boundaries
|
|
31
|
+
* - Errors → commitLog + typed event, NEVER thrown to parent
|
|
32
|
+
* - Scope isolation between parent and detached child
|
|
33
|
+
* - Lifecycle tied to executor disposal
|
|
34
|
+
* - Type-level rejection of `outputMapper` on detach options
|
|
35
|
+
*/
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtDRyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZGV0YWNoL3R5cGVzLnRzIOKAlCBUeXBlIGRlZmluaXRpb25zIGZvciB0aGUgZmlyZS1hbmQtZm9yZ2V0IHByaW1pdGl2ZS5cbiAqXG4gKiBQYXR0ZXJuOiAgU3RyYXRlZ3kgKyBCcmlkZ2UgKEdvRikuIFNhbWUgc2hhcGUgYXMgY2FjaGUgc3RyYXRlZ2llcyBpblxuICogICAgICAgICAgIGFnZW50Zm9vdHByaW50IHYyLjYg4oCUIE9ORSBpbnRlcmZhY2UsIE4gY29uY3JldGUgZHJpdmVycyxcbiAqICAgICAgICAgICBjb25zdW1lciBwaWNrcyB2aWEgZXhwbGljaXQgaW1wb3J0LlxuICogUm9sZTogICAgIEZvdW5kYXRpb24uIEV2ZXJ5IG90aGVyIGRldGFjaCBmaWxlIGltcG9ydHMgZnJvbSBoZXJlLlxuICogICAgICAgICAgIFRoaXMgaXMgdGhlIGxvY2thYmxlIGNvbnRyYWN0OyBkb3duc3RyZWFtIGZpbGVzIGltcGxlbWVudCBpdC5cbiAqXG4gKiBUd28gc2libGluZyBjb25jZXB0czpcbiAqXG4gKiAgIDEuIGBEZXRhY2hEcml2ZXJgIOKAlCB0aGUgYWxnb3JpdGhtIHRoYXQgZGVjaWRlcyBXSEVOL0hPVyB0aGUgd29yayBydW5zLlxuICogICAgICBTaXggYnVpbHQtaW4gYWxnb3JpdGhtcyBzaGlwIGFzIGFsZ29yaXRobS1uYW1lZCBleHBvcnRzXG4gKiAgICAgIChgbWljcm90YXNrQmF0Y2hEcml2ZXJgLCBgc2V0SW1tZWRpYXRlRHJpdmVyYCwgYHNlbmRCZWFjb25Ecml2ZXJgLFxuICogICAgICBgc2V0VGltZW91dERyaXZlcmAsIGBpbW1lZGlhdGVEcml2ZXJgLCBgd29ya2VyVGhyZWFkRHJpdmVyYCkuXG4gKiAgICAgIENvbnN1bWVycyBjYW4gaW1wbGVtZW50IHRoZWlyIG93biAoQllPUyDigJQgYnJpbmcgeW91ciBvd24gZHJpdmVyKS5cbiAqXG4gKiAgIDIuIGBEZXRhY2hIYW5kbGVgIOKAlCB0aGUgY29uc3VtZXItZmFjaW5nIGhhbmRsZSByZXR1cm5lZCBieVxuICogICAgICBgZGV0YWNoQW5kSm9pbkxhdGVyYC4gRXhwb3NlcyBzdGF0dXMgYXMgUFJPUEVSVElFUyAoc3luYyByZWFkKVxuICogICAgICBhbmQgYHdhaXQoKWAgKFByb21pc2Ug4oCUIG9wdC1pbiBhc3luYyBqb2luKS4gU3R5bGUgMiBmcm9tIHRoZVxuICogICAgICBwYW5lbCByZXZpZXc6IHByb3BlcnRpZXMgZm9yIHN5bmMsIHNpbmdsZSBtZXRob2QgZm9yIGFzeW5jLlxuICpcbiAqIE5hbWluZyBwb2xpY3kgKGxvY2tlZCBmcm9tIG5hbWluZyByZXZpZXcpOlxuICogICAtIFB1YmxpYyBBUEkgdXNlcyBzaW1wbGUgdmVyYnMgLyBwcm9wZXJ0aWVzIChwcm9kdWN0LWVuZ2luZWVyIGZyaWVuZGx5KVxuICogICAtIEludGVybmFsIGNsYXNzIG5hbWVzIENBTiB1c2UgQ1MgdGVybXMgKFNjaGVkdWxlciwgQ29udGludWF0aW9uLCBldGMuKVxuICogICAtIERyaXZlcnMgYXJlIGFsZ29yaXRobS1uYW1lZCAoc2VtYW50aWMgYXQgdGhlIGFsZ29yaXRobSBsZXZlbClcbiAqXG4gKiBMb2NrZWQgZGVzaWduIGRlY2lzaW9ucyAocGFuZWwgcmV2aWV3IGNhcHR1cmVkIGluXG4gKiBgZG9jcy9pbnNwaXJhdGlvbi9kZXRhY2gtcHJpbWl0aXZlLm1kYCk6XG4gKiAgIC0gU3luYyBob3QgcGF0aDsgYXN5bmMgb25seSBhdCBmbHVzaCBib3VuZGFyaWVzXG4gKiAgIC0gRXJyb3JzIOKGkiBjb21taXRMb2cgKyB0eXBlZCBldmVudCwgTkVWRVIgdGhyb3duIHRvIHBhcmVudFxuICogICAtIFNjb3BlIGlzb2xhdGlvbiBiZXR3ZWVuIHBhcmVudCBhbmQgZGV0YWNoZWQgY2hpbGRcbiAqICAgLSBMaWZlY3ljbGUgdGllZCB0byBleGVjdXRvciBkaXNwb3NhbFxuICogICAtIFR5cGUtbGV2ZWwgcmVqZWN0aW9uIG9mIGBvdXRwdXRNYXBwZXJgIG9uIGRldGFjaCBvcHRpb25zXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBGbG93Q2hhcnQgfSBmcm9tICcuLi9idWlsZGVyL3R5cGVzLmpzJztcblxuLy8g4pSA4pSA4pSAIERldGFjaEhhbmRsZSDigJQgd2hhdCB0aGUgY29uc3VtZXIgZ2V0cyBiYWNrIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKipcbiAqIFNuYXBzaG90IG9mIGEgZGV0YWNoZWQgaGFuZGxlJ3Mgc3RhdGUuIFJldHVybmVkIGJ5IGBoYW5kbGUucG9sbCgpYFxuICogKHdoZW4gYWRkZWQgaW4gYSBmb2xsb3ctdXA7IHYxIGV4cG9zZXMgcHJvcGVydGllcyBkaXJlY3RseSBvblxuICogYERldGFjaEhhbmRsZWApLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERldGFjaFBvbGxSZXN1bHQge1xuICByZWFkb25seSBzdGF0dXM6IERldGFjaEhhbmRsZVsnc3RhdHVzJ107XG4gIC8qKiBQcmVzZW50IGlmZiBzdGF0dXMgPT09ICdkb25lJy4gKi9cbiAgcmVhZG9ubHkgcmVzdWx0PzogdW5rbm93bjtcbiAgLyoqIFByZXNlbnQgaWZmIHN0YXR1cyA9PT0gJ2ZhaWxlZCcuICovXG4gIHJlYWRvbmx5IGVycm9yPzogRXJyb3I7XG59XG5cbi8qKlxuICogUmVzdWx0IGRlbGl2ZXJlZCB3aGVuIHRoZSBoYW5kbGUncyBgd2FpdCgpYCBQcm9taXNlIHJlc29sdmVzXG4gKiBzdWNjZXNzZnVsbHkgKHN0YXR1cyByZWFjaGVkICdkb25lJykuIFJlamVjdGlvbiBkZWxpdmVycyB0aGVcbiAqIG5hdGl2ZSBgRXJyb3JgIGRpcmVjdGx5IOKAlCBubyB3cmFwcGluZyBzaGFwZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXRhY2hXYWl0UmVzdWx0IHtcbiAgcmVhZG9ubHkgcmVzdWx0OiB1bmtub3duO1xufVxuXG4vKipcbiAqIEhhbmRsZSByZXR1cm5lZCBieSBgY2hhcnQuZGV0YWNoQW5kSm9pbkxhdGVyKC4uLilgIGFuZFxuICogYGV4ZWN1dG9yLmRldGFjaEFuZEpvaW5MYXRlciguLi4pYC4gRXhwb3NlcyBzdGF0dXMgYXMgUFJPUEVSVElFUyBzb1xuICogc3luYyBhY2Nlc3MgaXMgcHJvcGVydHktcmVhZCAoY2hlYXAsIG5vIGFsbG9jYXRpb24pLiBUaGUgc2luZ2xlXG4gKiBtZXRob2QgYHdhaXQoKWAgcmV0dXJucyBhIFByb21pc2UgZm9yIG9wdC1pbiBhc3luYyBqb2luLlxuICpcbiAqIFRoZSBoYW5kbGUgaXMgKipub3QqKiBQcm9taXNlLXNoYXBlZCAobm8gYC50aGVuKClgKSDigJQgdGhhdCB3b3VsZFxuICogbWFrZSBpdCBhY2NpZGVudGFsbHkgYXdhaXRhYmxlLCBkZWZlYXRpbmcgdGhlIGZpcmUtYW5kLWZvcmdldFxuICogc2VtYW50aWNzLiBUbyBhd2FpdCwgdGhlIGNvbnN1bWVyIG11c3QgY2FsbCBgLndhaXQoKWAgZXhwbGljaXRseS5cbiAqXG4gKiBMaWZlY3ljbGU6XG4gKlxuICogICBxdWV1ZWQgIOKGkiBkcml2ZXIgcmVjZWl2ZWQgdGhlIHdvcmssIGhhc24ndCBzdGFydGVkIGl0XG4gKiAgIHJ1bm5pbmcg4oaSIGRyaXZlciBzdGFydGVkIHRoZSB3b3JrXG4gKiAgIGRvbmUgICAg4oaSIHRlcm1pbmFsOiByZXN1bHQgYXZhaWxhYmxlXG4gKiAgIGZhaWxlZCAg4oaSIHRlcm1pbmFsOiBlcnJvciBhdmFpbGFibGVcbiAqXG4gKiBgZG9uZWAgYW5kIGBmYWlsZWRgIGFyZSBURVJNSU5BTCDigJQgb25jZSByZWFjaGVkLCBzdGF0dXMgbmV2ZXJcbiAqIGNoYW5nZXMgYWdhaW4uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGV0YWNoSGFuZGxlIHtcbiAgLyoqIFN0YWJsZSBpZCBhc3NpZ25lZCBhdCBkZXRhY2ggdGltZS4gVXNlZCBhcyB0aGUgbG9va3VwIGtleSBpblxuICAgKiAgYGRldGFjaFJlZ2lzdHJ5YCBhbmQgYXMgdGhlIHNjb3BlLXN0b3JhZ2Uga2V5IHByZWZpeC4gKi9cbiAgcmVhZG9ubHkgaWQ6IHN0cmluZztcblxuICAvKiogQ3VycmVudCBzdGF0ZS4gUmVhZCBkaXJlY3RseSBmb3Igc3luYyBhY2Nlc3MuICovXG4gIHJlYWRvbmx5IHN0YXR1czogJ3F1ZXVlZCcgfCAncnVubmluZycgfCAnZG9uZScgfCAnZmFpbGVkJztcblxuICAvKiogVGhlIHdvcmsncyByZXN1bHQuIFByZXNlbnQgaWZmIGBzdGF0dXMgPT09ICdkb25lJ2AuIFJlYWRpbmdcbiAgICogIGJlZm9yZSB0ZXJtaW5hbCByZXR1cm5zIGB1bmRlZmluZWRgLiAqL1xuICByZWFkb25seSByZXN1bHQ/OiB1bmtub3duO1xuXG4gIC8qKiBUaGUgd29yaydzIGVycm9yLiBQcmVzZW50IGlmZiBgc3RhdHVzID09PSAnZmFpbGVkJ2AuIFJlYWRpbmdcbiAgICogIGJlZm9yZSB0ZXJtaW5hbCByZXR1cm5zIGB1bmRlZmluZWRgLiAqL1xuICByZWFkb25seSBlcnJvcj86IEVycm9yO1xuXG4gIC8qKlxuICAgKiBPcHQtaW4gYXN5bmMgam9pbi4gUmV0dXJucyBhIFByb21pc2UgdGhhdDpcbiAgICogICAtIHJlc29sdmVzIHdpdGggYHsgcmVzdWx0IH1gIHdoZW4gc3RhdHVzIGJlY29tZXMgJ2RvbmUnXG4gICAqICAgLSByZWplY3RzIHdpdGggdGhlIGNhcHR1cmVkIGBFcnJvcmAgd2hlbiBzdGF0dXMgYmVjb21lcyAnZmFpbGVkJ1xuICAgKiAgIC0gcmVzb2x2ZXMvcmVqZWN0cyBJTU1FRElBVEVMWSBpZiBzdGF0dXMgaXMgYWxyZWFkeSB0ZXJtaW5hbFxuICAgKiAgIC0gcmV0dXJucyB0aGUgU0FNRSBjYWNoZWQgUHJvbWlzZSBvbiByZXBlYXRlZCBjYWxscyAobm9cbiAgICogICAgIHJlLXJ1bm5pbmcsIG5vIGR1cGxpY2F0ZWQgSS9PKVxuICAgKlxuICAgKiBDYWxsaW5nIGB3YWl0KClgIGRvZXMgTk9UIGNoYW5nZSB0aGUgaGFuZGxlJ3MgbGlmZWN5Y2xlIOKAlCBpdCdzXG4gICAqIHBhc3NpdmUgb2JzZXJ2YXRpb24uIElmIG5ldmVyIGNhbGxlZCwgdGhlIHdvcmsgc3RpbGwgY29tcGxldGVzO1xuICAgKiB0aGUgaGFuZGxlIGp1c3QgZ29lcyB1bmNvbGxlY3RlZCAocGFyZW50IGV4ZWN1dGlvbiB1bmFmZmVjdGVkKS5cbiAgICpcbiAgICogVXNlIHdoZW46XG4gICAqICAgLSBZb3UgYWN0dWFsbHkgbmVlZCB0aGUgcmVzdWx0IGFuZCB3YW50IHRvIGF3YWl0IGl0XG4gICAqICAgLSBDb29yZGluYXRpbmcgbXVsdGlwbGUgaGFuZGxlcyB2aWEgUHJvbWlzZS5hbGwgLyBQcm9taXNlLnJhY2VcbiAgICogICAtIEJhY2twcmVzc3VyZSAoXCJkb24ndCBmaXJlIG1vcmUgdGhhbiBOIGluIGZsaWdodFwiKVxuICAgKlxuICAgKiBEb24ndCB1c2Ugd2hlbjpcbiAgICogICAtIFB1cmUgZmlyZS1hbmQtZm9yZ2V0ICh1c2UgYGRldGFjaEFuZEZvcmdldGAg4oCUIG5vIGhhbmRsZSByZXR1cm5lZClcbiAgICogICAtIFlvdSBqdXN0IHdhbnQgdG8gY2hlY2sgc3RhdHVzIChyZWFkIGBoYW5kbGUuc3RhdHVzYCBkaXJlY3RseSlcbiAgICovXG4gIHdhaXQoKTogUHJvbWlzZTxEZXRhY2hXYWl0UmVzdWx0Pjtcbn1cblxuLy8g4pSA4pSA4pSAIERldGFjaERyaXZlciDigJQgdGhlIGFsZ29yaXRobSBpbnRlcmZhY2Ug4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKlxuICogQ2FwYWJpbGl0aWVzIGEgZHJpdmVyIGRlY2xhcmVzLiBEcml2ZXMgdGhlIHJ1bnRpbWUgZGVjaXNpb24gb2ZcbiAqIFwiaXMgdGhpcyBkcml2ZXIgYXBwcm9wcmlhdGUgZm9yIHRoZSBjdXJyZW50IGVudmlyb25tZW50P1wiIENvbnN1bWVyc1xuICogaW5zcGVjdCBhdCBjb25zdHJ1Y3Rpb247IHRoZSBmcmFtZXdvcmsgZG9lc24ndCBlbmZvcmNlLlxuICpcbiAqIEFsbCBjYXBhYmlsaXRpZXMgYXJlIG9wdGlvbmFsIGZsYWdzIOKAlCBmYWxzZSAvIHVuZGVmaW5lZCBtZWFucyBcIm5vdFxuICogc3VwcG9ydGVkIC8gbm8gY2xhaW0uXCIgQSBkcml2ZXIgdGhhdCBzdXBwb3J0cyBldmVyeXRoaW5nIHNldHMgYWxsXG4gKiB0byB0cnVlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERyaXZlckNhcGFiaWxpdGllcyB7XG4gIC8qKiBEcml2ZXIgd29ya3MgaW4gYnJvd3NlciBlbnZpcm9ubWVudHMgKHdpbmRvdywgZG9jdW1lbnQsIGV0Yy4pLiAqL1xuICByZWFkb25seSBicm93c2VyU2FmZT86IGJvb2xlYW47XG4gIC8qKiBEcml2ZXIgd29ya3MgaW4gTm9kZS5qcyBlbnZpcm9ubWVudHMuICovXG4gIHJlYWRvbmx5IG5vZGVTYWZlPzogYm9vbGVhbjtcbiAgLyoqIERyaXZlciB3b3JrcyBpbiBlZGdlIHJ1bnRpbWVzIChDbG91ZGZsYXJlIFdvcmtlcnMsIERlbm8gRGVwbG95LFxuICAgKiAgQnVuIGVkZ2UsIGV0Yy4g4oCUIHJlc3RyaWN0ZWQgZW52aXJvbm1lbnRzKS4gKi9cbiAgcmVhZG9ubHkgZWRnZVNhZmU/OiBib29sZWFuO1xuICAvKiogV29yayBzdXJ2aXZlcyBwYWdlLXVubG9hZCAvIHByb2Nlc3MtZXhpdC4gZS5nLixcbiAgICogIGBzZW5kQmVhY29uRHJpdmVyYCBzY2hlZHVsZXMgdmlhIGBuYXZpZ2F0b3Iuc2VuZEJlYWNvbmAgd2hpY2hcbiAgICogIHNoaXBzIGV2ZW4gb24gdGFiIGNsb3NlLiAqL1xuICByZWFkb25seSBzdXJ2aXZlc1VubG9hZD86IGJvb2xlYW47XG4gIC8qKiBXb3JrIHJ1bnMgb24gYSBzZXBhcmF0ZSBPUyB0aHJlYWQgKG5vIGV2ZW50LWxvb3AgYmxvY2spLlxuICAgKiAgZS5nLiwgYHdvcmtlclRocmVhZERyaXZlcmAuICovXG4gIHJlYWRvbmx5IGNwdUlzb2xhdGVkPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIGRyaXZlciBpcyB0aGUgV0hFTi9IT1cgb2YgdGhlIGRldGFjaC4gTWFwcyBgKGNoaWxkLCBpbnB1dCwgcmVmSWQpYFxuICogdG8gYSBgRGV0YWNoSGFuZGxlYCB3aG9zZSBsaWZlY3ljbGUgdGhlIGRyaXZlciBvd25zLlxuICpcbiAqIERyaXZlcnMgYXJlIHRoZW1zZWx2ZXMgZm9vdHByaW50anMgcHJpbWl0aXZlcyDigJQgaW50ZXJuYWxseSB0aGV5IG1heVxuICogYmUgYSBzaW5nbGUgZnVuY3Rpb24gb3IgYSBtdWx0aS1zdGFnZSBmbG93Q2hhcnQuIEVpdGhlciB3YXksIHRoZVxuICogaW50ZXJmYWNlIHRoZXkgZXhwb3NlIHRvIGNvbnN1bWVycyBpcyBgc2NoZWR1bGUoLi4uKWAuXG4gKlxuICogRHJpdmVycyBNVVNUOlxuICogICAtIFJldHVybiBzeW5jaHJvbm91c2x5ICh0aGUgYWdlbnQgbG9vcCBuZXZlciBibG9ja3Mgb24gc2NoZWR1bGUpXG4gKiAgIC0gTm90IHRocm93IOKAlCBlcnJvcnMgZHVyaW5nIHNjaGVkdWxpbmcgcm91dGUgdGhyb3VnaCB0aGUgaGFuZGxlXG4gKiAgICAgKGBoYW5kbGUuc3RhdHVzID0gJ2ZhaWxlZCdgLCBgaGFuZGxlLmVycm9yID0gLi4uYClcbiAqICAgLSBIb25vciB0aGUgcGFzc2l2ZS1yZWNvcmRlciBydWxlOiB0aGUgcGFyZW50J3MgYGRldGFjaCpgIGNhbGxcbiAqICAgICBuZXZlciB3YWl0cyBmb3IgdGhlIGRyaXZlcidzIGRlZmVycmVkIHdvcmsgdG8gY29tcGxldGVcbiAqXG4gKiBEcml2ZXJzIE1BWTpcbiAqICAgLSBJbXBsZW1lbnQgYHZhbGlkYXRlKClgIGZvciBvbmUtdGltZSBjb25maWd1cmF0aW9uIGNoZWNrcyBhdFxuICogICAgIHJlZ2lzdHJhdGlvbiAvIHVzZSB0aW1lIChlLmcuLCBhc3NlcnQgYG5hdmlnYXRvci5zZW5kQmVhY29uYCBleGlzdHMpXG4gKiAgIC0gQnVpbGQgdGhlaXIgaW50ZXJuYWwgcGlwZWxpbmUgYXMgYSBmb290cHJpbnRqcyBmbG93Q2hhcnQgZm9yXG4gKiAgICAgb2JzZXJ2YWJpbGl0eSDigJQgZHJpdmVyIGltcGxlbWVudGF0aW9uIGRldGFpbCwgbm90IGNvbnN1bWVyLWZhY2luZ1xuICpcbiAqIEBleGFtcGxlIEJ1aWx0LWluXG4gKiAgIGltcG9ydCB7IG1pY3JvdGFza0JhdGNoRHJpdmVyIH0gZnJvbSAnZm9vdHByaW50anMvZGV0YWNoJztcbiAqICAgY29uc3QgaGFuZGxlID0gZHJpdmVyLnNjaGVkdWxlKGNoaWxkLCBpbnB1dCwgcmVmSWQpO1xuICpcbiAqIEBleGFtcGxlIEN1c3RvbSAoQllPUylcbiAqICAgY29uc3QgbGFtYmRhRXh0ZW5zaW9uRHJpdmVyOiBEZXRhY2hEcml2ZXIgPSB7XG4gKiAgICAgbmFtZTogJ2xhbWJkYS1leHRlbnNpb24nLFxuICogICAgIGNhcGFiaWxpdGllczogeyBub2RlU2FmZTogdHJ1ZSwgc3Vydml2ZXNVbmxvYWQ6IHRydWUgfSxcbiAqICAgICBzY2hlZHVsZShjaGlsZCwgaW5wdXQsIHJlZklkKSB7XG4gKiAgICAgICBzaGFyZWRCdWZmZXIucHVzaCh7IHJlZklkLCBjaGlsZCwgaW5wdXQgfSk7XG4gKiAgICAgICByZXR1cm4gY3JlYXRlSGFuZGxlKHJlZklkLCAncXVldWVkJyk7XG4gKiAgICAgfSxcbiAqICAgfTtcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXRhY2hEcml2ZXIge1xuICAvKiogU3RhYmxlIG5hbWUgZm9yIGRpYWdub3N0aWNzICsgcmVnaXN0cnkgbG9va3VwLiBDb252ZW50aW9uYWxseVxuICAgKiAgYWxnb3JpdGhtLW5hbWVkIChlLmcuIGAnbWljcm90YXNrLWJhdGNoJ2AsIGAnc2VuZC1iZWFjb24nYCkuICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKiogV2hhdCB0aGlzIGRyaXZlciBzdXBwb3J0cy4gVXNlZCBieSBjb25zdW1lcnMgdG8gcGljayB0aGUgcmlnaHRcbiAgICogIGRyaXZlciBmb3IgdGhlaXIgZW52aXJvbm1lbnQuICovXG4gIHJlYWRvbmx5IGNhcGFiaWxpdGllczogRHJpdmVyQ2FwYWJpbGl0aWVzO1xuXG4gIC8qKlxuICAgKiBIYW5kIHRoZSB3b3JrIHRvIHRoZSBkcml2ZXIncyBzY2hlZHVsaW5nIG1lY2hhbmlzbS4gTVVTVCByZXR1cm5cbiAgICogc3luY2hyb25vdXNseSB3aXRoIGEgZnJlc2ggYERldGFjaEhhbmRsZWAuIFRoZSBhY3R1YWwgd29yayBtYXlcbiAgICogcnVuIGxhdGVyIChuZXh0IG1pY3JvdGFzayAvIHNldEltbWVkaWF0ZSAvIGJyb3dzZXItYmVhY29uLWZsdXNoIC9cbiAgICogd29ya2VyLXRocmVhZCAvIGV0Yy4pIG9uIHRoZSBkcml2ZXIncyBjaG9zZW4gbWVjaGFuaXNtLlxuICAgKi9cbiAgc2NoZWR1bGUoY2hpbGQ6IEZsb3dDaGFydCwgaW5wdXQ6IHVua25vd24sIHJlZklkOiBzdHJpbmcpOiBEZXRhY2hIYW5kbGU7XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIG9uZS10aW1lIHZhbGlkYXRpb24gaG9vay4gQ2FsbGVkIGF0IGZpcnN0IHVzZSAob3JcbiAgICogcmVnaXN0cmF0aW9uIHRpbWUsIGRlcGVuZGluZyBvbiBkcml2ZXIpIOKAlCBkcml2ZXJzIHRocm93IGlmIHRoZWlyXG4gICAqIGNvbmZpZ3VyYXRpb24gaXMgaW52YWxpZCAobWlzc2luZyBwZWVyIGRlcCwgdW5yZWFjaGFibGUgZW5kcG9pbnQsXG4gICAqIHdyb25nIEFQSSBrZXkgc2hhcGUsIGV0Yy4pLlxuICAgKlxuICAgKiBFeGFtcGxlOiBgc2VuZEJlYWNvbkRyaXZlci52YWxpZGF0ZSgpYCBjaGVja3NcbiAgICogYHR5cGVvZiBuYXZpZ2F0b3I/LnNlbmRCZWFjb24gPT09ICdmdW5jdGlvbidgIGFuZCB0aHJvd3Mgd2l0aCBhXG4gICAqIGhlbHBmdWwgbWVzc2FnZSBpZiBhYnNlbnQgKGUuZy4sIGluIE5vZGUpLlxuICAgKlxuICAgKiBQZXIgdGhlIE5ldyBSZWxpYyBwYW5lbCByZXZpZXc6IGVhcmx5LWZhaWwtd2l0aC11c2VmdWwtbWVzc2FnZVxuICAgKiBiZWF0cyBzaWxlbnQgemVyby1lbWlzc2lvbi5cbiAgICovXG4gIHZhbGlkYXRlPygpOiB2b2lkO1xufVxuIl19
|