footprintjs 10.0.1 → 10.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.
- package/AGENTS.md +2 -1
- package/CLAUDE.md +61 -7
- package/README.md +136 -312
- package/dist/esm/index.d.ts +62 -2
- package/dist/esm/index.js +13 -6
- package/dist/esm/lib/attempt/anySignal.d.ts +19 -0
- package/dist/esm/lib/attempt/anySignal.js +39 -0
- package/dist/esm/lib/attempt/call.d.ts +88 -0
- package/dist/esm/lib/attempt/call.js +129 -0
- package/dist/esm/lib/attempt/category.d.ts +37 -0
- package/dist/esm/lib/attempt/category.js +131 -0
- package/dist/esm/lib/attempt/correlation.d.ts +95 -0
- package/dist/esm/lib/attempt/correlation.js +178 -0
- package/dist/esm/lib/attempt/deadline.d.ts +44 -0
- package/dist/esm/lib/attempt/deadline.js +101 -0
- package/dist/esm/lib/attempt/decision.d.ts +52 -0
- package/dist/esm/lib/attempt/decision.js +134 -0
- package/dist/esm/lib/attempt/effect.d.ts +76 -0
- package/dist/esm/lib/attempt/effect.js +160 -0
- package/dist/esm/lib/attempt/errors.d.ts +41 -0
- package/dist/esm/lib/attempt/errors.js +44 -0
- package/dist/esm/lib/attempt/index.d.ts +18 -0
- package/dist/esm/lib/attempt/index.js +15 -0
- package/dist/esm/lib/attempt/name.d.ts +21 -0
- package/dist/esm/lib/attempt/name.js +43 -0
- package/dist/esm/lib/attempt/observed.d.ts +66 -0
- package/dist/esm/lib/attempt/observed.js +171 -0
- package/dist/esm/lib/attempt/policy.d.ts +45 -0
- package/dist/esm/lib/attempt/policy.js +83 -0
- package/dist/esm/lib/attempt/record.d.ts +11 -0
- package/dist/esm/lib/attempt/record.js +24 -0
- package/dist/esm/lib/attempt/retryLoopContext.d.ts +18 -0
- package/dist/esm/lib/attempt/retryLoopContext.js +24 -0
- package/dist/esm/lib/attempt/retryLoopTypes.d.ts +18 -0
- package/dist/esm/lib/attempt/retryLoopTypes.js +2 -0
- package/dist/esm/lib/attempt/runner.d.ts +157 -0
- package/dist/esm/lib/attempt/runner.js +523 -0
- package/dist/esm/lib/attempt/standalone.d.ts +47 -0
- package/dist/esm/lib/attempt/standalone.js +126 -0
- package/dist/esm/lib/attempt/types.d.ts +453 -0
- package/dist/esm/lib/attempt/types.js +16 -0
- package/dist/esm/lib/budget/index.d.ts +9 -0
- package/dist/esm/lib/budget/index.js +9 -0
- package/dist/esm/lib/budget/timeBudget.d.ts +136 -0
- package/dist/esm/lib/budget/timeBudget.js +666 -0
- package/dist/esm/lib/builder/FlowChartBuilder.d.ts +88 -3
- package/dist/esm/lib/builder/FlowChartBuilder.js +199 -9
- package/dist/esm/lib/builder/retryLoop.d.ts +56 -0
- package/dist/esm/lib/builder/retryLoop.js +283 -0
- package/dist/esm/lib/builder/types.d.ts +35 -1
- package/dist/esm/lib/builder/types.js +1 -1
- package/dist/esm/lib/decide/decide.js +2 -2
- package/dist/esm/lib/decide/index.d.ts +1 -1
- package/dist/esm/lib/decide/index.js +2 -2
- package/dist/esm/lib/decide/types.d.ts +3 -0
- package/dist/esm/lib/decide/types.js +1 -8
- package/dist/esm/lib/engine/graph/StageNode.d.ts +11 -1
- package/dist/esm/lib/engine/graph/StageNode.js +1 -1
- package/dist/esm/lib/engine/graph/prefixNodeTree.js +5 -1
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +36 -6
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +9 -5
- package/dist/esm/lib/engine/handlers/ResumeEntry.js +3 -1
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +6 -5
- package/dist/esm/lib/engine/handlers/StageRunner.d.ts +8 -1
- package/dist/esm/lib/engine/handlers/StageRunner.js +36 -9
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +24 -5
- package/dist/esm/lib/engine/handlers/commitStage.d.ts +7 -0
- package/dist/esm/lib/engine/handlers/commitStage.js +22 -4
- package/dist/esm/lib/engine/handlers/stageError.d.ts +9 -0
- package/dist/esm/lib/engine/handlers/stageError.js +23 -1
- package/dist/esm/lib/engine/index.d.ts +2 -2
- package/dist/esm/lib/engine/index.js +1 -1
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +68 -40
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +61 -9
- package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
- package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
- package/dist/esm/lib/engine/narrative/formatting/sentences.d.ts +23 -0
- package/dist/esm/lib/engine/narrative/formatting/sentences.js +127 -1
- package/dist/esm/lib/engine/narrative/index.d.ts +2 -2
- package/dist/esm/lib/engine/narrative/index.js +1 -1
- package/dist/esm/lib/engine/narrative/narrativeTypes.d.ts +27 -21
- package/dist/esm/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
- package/dist/esm/lib/engine/narrative/recorders/index.d.ts +1 -1
- package/dist/esm/lib/engine/narrative/recorders/index.js +1 -1
- package/dist/esm/lib/engine/narrative/types.d.ts +74 -5
- package/dist/esm/lib/engine/narrative/types.js +1 -1
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +194 -118
- package/dist/esm/lib/engine/traversalContext.d.ts +7 -2
- package/dist/esm/lib/engine/traversalContext.js +6 -3
- package/dist/esm/lib/engine/types.d.ts +52 -57
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/errors/terminalFailure.d.ts +29 -0
- package/dist/esm/lib/errors/terminalFailure.js +60 -0
- package/dist/esm/lib/{decide → filter}/evaluator.d.ts +7 -2
- package/dist/esm/lib/filter/evaluator.js +135 -0
- package/dist/esm/lib/ids/idempotencyKey.d.ts +14 -0
- package/dist/esm/lib/ids/idempotencyKey.js +24 -0
- package/dist/esm/lib/memory/StageContext.d.ts +123 -3
- package/dist/esm/lib/memory/StageContext.js +245 -4
- package/dist/esm/lib/memory/attention.d.ts +26 -0
- package/dist/esm/lib/memory/attention.js +171 -0
- package/dist/esm/lib/memory/borrowedMutation.d.ts +8 -0
- package/dist/esm/lib/memory/borrowedMutation.js +14 -1
- package/dist/esm/lib/memory/frameTypes.d.ts +38 -0
- package/dist/esm/lib/memory/frameTypes.js +3 -1
- package/dist/esm/lib/memory/redaction.d.ts +12 -0
- package/dist/esm/lib/memory/redaction.js +54 -5
- package/dist/esm/lib/pause/record.js +10 -1
- package/dist/esm/lib/pause/types.d.ts +19 -0
- package/dist/esm/lib/pause/types.js +17 -1
- package/dist/esm/lib/reactive/createTypedScope.js +3 -1
- package/dist/esm/lib/reactive/types.d.ts +36 -4
- package/dist/esm/lib/reactive/types.js +3 -1
- package/dist/esm/lib/recorder/AttemptRecorder.d.ts +141 -0
- package/dist/esm/lib/recorder/AttemptRecorder.js +412 -0
- package/dist/esm/lib/recorder/ControlDepRecorder.d.ts +36 -2
- package/dist/esm/lib/recorder/ControlDepRecorder.js +50 -2
- package/dist/esm/lib/recorder/EmitRecorder.d.ts +3 -0
- package/dist/esm/lib/recorder/EmitRecorder.js +1 -1
- package/dist/esm/lib/recorder/InOutRecorder.d.ts +37 -1
- package/dist/esm/lib/recorder/InOutRecorder.js +75 -6
- package/dist/esm/lib/recorder/QualityRecorder.d.ts +32 -5
- package/dist/esm/lib/recorder/QualityRecorder.js +87 -29
- package/dist/esm/lib/recorder/TopologyRecorder.d.ts +35 -5
- package/dist/esm/lib/recorder/TopologyRecorder.js +76 -2
- package/dist/esm/lib/recorder/attemptMetricRows.d.ts +11 -0
- package/dist/esm/lib/recorder/attemptMetricRows.js +202 -0
- package/dist/esm/lib/recorder/attemptMetrics.d.ts +7 -0
- package/dist/esm/lib/recorder/attemptMetrics.js +165 -0
- package/dist/esm/lib/recorder/attemptMetricsTypes.d.ts +114 -0
- package/dist/esm/lib/recorder/attemptMetricsTypes.js +2 -0
- package/dist/esm/lib/recorder/attemptOTel.d.ts +78 -0
- package/dist/esm/lib/recorder/attemptOTel.js +107 -0
- package/dist/esm/lib/recorder/attemptSeries.d.ts +81 -0
- package/dist/esm/lib/recorder/attemptSeries.js +103 -0
- package/dist/esm/lib/recorder/hooks.d.ts +9 -0
- package/dist/esm/lib/recorder/hooks.js +4 -1
- package/dist/esm/lib/runner/DeferredObserverTier.js +13 -1
- package/dist/esm/lib/runner/ExecutionRuntime.d.ts +54 -6
- package/dist/esm/lib/runner/ExecutionRuntime.js +57 -5
- package/dist/esm/lib/runner/FlowChartExecutor.d.ts +46 -2
- package/dist/esm/lib/runner/FlowChartExecutor.js +330 -101
- package/dist/esm/lib/runner/RunnableChart.d.ts +6 -0
- package/dist/esm/lib/runner/RunnableChart.js +5 -1
- package/dist/esm/lib/runner/attach.d.ts +2 -1
- package/dist/esm/lib/runner/attach.js +8 -2
- package/dist/esm/lib/runner/checkpoint.js +3 -1
- package/dist/esm/lib/runner/deadline.d.ts +42 -0
- package/dist/esm/lib/runner/deadline.js +90 -0
- package/dist/esm/lib/runner/index.d.ts +3 -1
- package/dist/esm/lib/runner/index.js +2 -1
- package/dist/esm/lib/runner/options.d.ts +17 -0
- package/dist/esm/lib/runner/options.js +3 -1
- package/dist/esm/lib/runner/recordSink.d.ts +128 -0
- package/dist/esm/lib/runner/recordSink.js +296 -0
- package/dist/esm/lib/runner/resume.d.ts +3 -0
- package/dist/esm/lib/runner/resume.js +22 -2
- package/dist/esm/lib/runner/snapshot.d.ts +2 -2
- package/dist/esm/lib/runner/snapshot.js +6 -2
- package/dist/esm/lib/scope/ScopeFacade.d.ts +118 -4
- package/dist/esm/lib/scope/ScopeFacade.js +304 -7
- package/dist/esm/lib/scope/recorders/DebugRecorder.d.ts +17 -3
- package/dist/esm/lib/scope/recorders/DebugRecorder.js +79 -13
- package/dist/esm/lib/scope/recorders/MetricRecorder.d.ts +10 -0
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +15 -2
- package/dist/esm/lib/scope/runtime.d.ts +3 -0
- package/dist/esm/lib/scope/runtime.js +1 -1
- package/dist/esm/lib/scope/types.d.ts +6 -0
- package/dist/esm/lib/scope/types.js +1 -1
- package/dist/esm/lib/sinks/fileSink.d.ts +135 -0
- package/dist/esm/lib/sinks/fileSink.js +387 -0
- package/dist/esm/recorders.d.ts +8 -2
- package/dist/esm/recorders.js +7 -1
- package/dist/esm/sinks.d.ts +23 -0
- package/dist/esm/sinks.js +23 -0
- package/dist/esm/trace.d.ts +2 -2
- package/dist/esm/trace.js +1 -1
- package/dist/index.js +77 -60
- package/dist/lib/attempt/anySignal.js +43 -0
- package/dist/lib/attempt/call.js +134 -0
- package/dist/lib/attempt/category.js +136 -0
- package/dist/lib/attempt/correlation.js +186 -0
- package/dist/lib/attempt/deadline.js +112 -0
- package/dist/lib/attempt/decision.js +139 -0
- package/dist/lib/attempt/effect.js +174 -0
- package/dist/lib/attempt/errors.js +49 -0
- package/dist/lib/attempt/index.js +26 -0
- package/dist/lib/attempt/name.js +48 -0
- package/dist/lib/attempt/observed.js +177 -0
- package/dist/lib/attempt/policy.js +92 -0
- package/dist/lib/attempt/record.js +29 -0
- package/dist/lib/attempt/retryLoopContext.js +31 -0
- package/dist/lib/attempt/retryLoopTypes.js +3 -0
- package/dist/lib/attempt/runner.js +530 -0
- package/dist/lib/attempt/standalone.js +130 -0
- package/dist/lib/attempt/types.js +17 -0
- package/dist/lib/budget/index.js +17 -0
- package/dist/lib/budget/timeBudget.js +674 -0
- package/dist/lib/builder/FlowChartBuilder.js +199 -9
- package/dist/lib/builder/retryLoop.js +287 -0
- package/dist/lib/builder/types.js +1 -1
- package/dist/lib/decide/decide.js +2 -2
- package/dist/lib/decide/index.js +2 -2
- package/dist/lib/decide/types.js +1 -8
- package/dist/lib/engine/graph/StageNode.js +1 -1
- package/dist/lib/engine/graph/prefixNodeTree.js +5 -1
- package/dist/lib/engine/handlers/ChildrenExecutor.js +36 -6
- package/dist/lib/engine/handlers/DeciderHandler.js +7 -3
- package/dist/lib/engine/handlers/ResumeEntry.js +3 -1
- package/dist/lib/engine/handlers/SelectorHandler.js +4 -3
- package/dist/lib/engine/handlers/StageRunner.js +36 -9
- package/dist/lib/engine/handlers/SubflowExecutor.js +24 -5
- package/dist/lib/engine/handlers/commitStage.js +24 -5
- package/dist/lib/engine/handlers/stageError.js +26 -2
- package/dist/lib/engine/index.js +1 -1
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +67 -39
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +60 -8
- package/dist/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
- package/dist/lib/engine/narrative/formatting/sentences.js +131 -2
- package/dist/lib/engine/narrative/index.js +1 -1
- package/dist/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
- package/dist/lib/engine/narrative/recorders/index.js +1 -1
- package/dist/lib/engine/narrative/types.js +1 -1
- package/dist/lib/engine/traversal/FlowchartTraverser.js +192 -116
- package/dist/lib/engine/traversalContext.js +6 -3
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/errors/terminalFailure.js +64 -0
- package/dist/lib/filter/evaluator.js +139 -0
- package/dist/lib/ids/idempotencyKey.js +28 -0
- package/dist/lib/memory/StageContext.js +246 -5
- package/dist/lib/memory/attention.js +175 -0
- package/dist/lib/memory/borrowedMutation.js +16 -2
- package/dist/lib/memory/frameTypes.js +3 -1
- package/dist/lib/memory/redaction.js +54 -5
- package/dist/lib/pause/record.js +10 -1
- package/dist/lib/pause/types.js +17 -1
- package/dist/lib/reactive/createTypedScope.js +3 -1
- package/dist/lib/reactive/types.js +3 -1
- package/dist/lib/recorder/AttemptRecorder.js +417 -0
- package/dist/lib/recorder/ControlDepRecorder.js +50 -2
- package/dist/lib/recorder/EmitRecorder.js +1 -1
- package/dist/lib/recorder/InOutRecorder.js +75 -6
- package/dist/lib/recorder/QualityRecorder.js +87 -29
- package/dist/lib/recorder/TopologyRecorder.js +76 -2
- package/dist/lib/recorder/attemptMetricRows.js +209 -0
- package/dist/lib/recorder/attemptMetrics.js +174 -0
- package/dist/lib/recorder/attemptMetricsTypes.js +3 -0
- package/dist/lib/recorder/attemptOTel.js +111 -0
- package/dist/lib/recorder/attemptSeries.js +113 -0
- package/dist/lib/recorder/hooks.js +4 -1
- package/dist/lib/runner/DeferredObserverTier.js +13 -1
- package/dist/lib/runner/ExecutionRuntime.js +57 -5
- package/dist/lib/runner/FlowChartExecutor.js +330 -101
- package/dist/lib/runner/RunnableChart.js +5 -1
- package/dist/lib/runner/attach.js +8 -2
- package/dist/lib/runner/checkpoint.js +3 -1
- package/dist/lib/runner/deadline.js +94 -0
- package/dist/lib/runner/index.js +4 -2
- package/dist/lib/runner/options.js +3 -1
- package/dist/lib/runner/recordSink.js +302 -0
- package/dist/lib/runner/resume.js +22 -2
- package/dist/lib/runner/snapshot.js +6 -2
- package/dist/lib/scope/ScopeFacade.js +303 -6
- package/dist/lib/scope/recorders/DebugRecorder.js +79 -13
- package/dist/lib/scope/recorders/MetricRecorder.js +15 -2
- package/dist/lib/scope/runtime.js +1 -1
- package/dist/lib/scope/types.js +1 -1
- package/dist/lib/sinks/fileSink.js +392 -0
- package/dist/recorders.js +10 -2
- package/dist/sinks.js +32 -0
- package/dist/trace.js +1 -1
- package/dist/types/index.d.ts +62 -2
- package/dist/types/lib/attempt/anySignal.d.ts +19 -0
- package/dist/types/lib/attempt/call.d.ts +88 -0
- package/dist/types/lib/attempt/category.d.ts +37 -0
- package/dist/types/lib/attempt/correlation.d.ts +95 -0
- package/dist/types/lib/attempt/deadline.d.ts +44 -0
- package/dist/types/lib/attempt/decision.d.ts +52 -0
- package/dist/types/lib/attempt/effect.d.ts +76 -0
- package/dist/types/lib/attempt/errors.d.ts +41 -0
- package/dist/types/lib/attempt/index.d.ts +18 -0
- package/dist/types/lib/attempt/name.d.ts +21 -0
- package/dist/types/lib/attempt/observed.d.ts +66 -0
- package/dist/types/lib/attempt/policy.d.ts +45 -0
- package/dist/types/lib/attempt/record.d.ts +11 -0
- package/dist/types/lib/attempt/retryLoopContext.d.ts +18 -0
- package/dist/types/lib/attempt/retryLoopTypes.d.ts +18 -0
- package/dist/types/lib/attempt/runner.d.ts +157 -0
- package/dist/types/lib/attempt/standalone.d.ts +47 -0
- package/dist/types/lib/attempt/types.d.ts +453 -0
- package/dist/types/lib/budget/index.d.ts +9 -0
- package/dist/types/lib/budget/timeBudget.d.ts +136 -0
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +88 -3
- package/dist/types/lib/builder/retryLoop.d.ts +56 -0
- package/dist/types/lib/builder/types.d.ts +35 -1
- package/dist/types/lib/decide/index.d.ts +1 -1
- package/dist/types/lib/decide/types.d.ts +3 -0
- package/dist/types/lib/engine/graph/StageNode.d.ts +11 -1
- package/dist/types/lib/engine/handlers/StageRunner.d.ts +8 -1
- package/dist/types/lib/engine/handlers/commitStage.d.ts +7 -0
- package/dist/types/lib/engine/handlers/stageError.d.ts +9 -0
- package/dist/types/lib/engine/index.d.ts +2 -2
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
- package/dist/types/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
- package/dist/types/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
- package/dist/types/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
- package/dist/types/lib/engine/narrative/formatting/sentences.d.ts +23 -0
- package/dist/types/lib/engine/narrative/index.d.ts +2 -2
- package/dist/types/lib/engine/narrative/narrativeTypes.d.ts +27 -21
- package/dist/types/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
- package/dist/types/lib/engine/narrative/recorders/index.d.ts +1 -1
- package/dist/types/lib/engine/narrative/types.d.ts +74 -5
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
- package/dist/types/lib/engine/traversalContext.d.ts +7 -2
- package/dist/types/lib/engine/types.d.ts +52 -57
- package/dist/types/lib/errors/terminalFailure.d.ts +29 -0
- package/dist/types/lib/{decide → filter}/evaluator.d.ts +7 -2
- package/dist/types/lib/ids/idempotencyKey.d.ts +14 -0
- package/dist/types/lib/memory/StageContext.d.ts +123 -3
- package/dist/types/lib/memory/attention.d.ts +26 -0
- package/dist/types/lib/memory/borrowedMutation.d.ts +8 -0
- package/dist/types/lib/memory/frameTypes.d.ts +38 -0
- package/dist/types/lib/memory/redaction.d.ts +12 -0
- package/dist/types/lib/pause/types.d.ts +19 -0
- package/dist/types/lib/reactive/types.d.ts +36 -4
- package/dist/types/lib/recorder/AttemptRecorder.d.ts +141 -0
- package/dist/types/lib/recorder/ControlDepRecorder.d.ts +36 -2
- package/dist/types/lib/recorder/EmitRecorder.d.ts +3 -0
- package/dist/types/lib/recorder/InOutRecorder.d.ts +37 -1
- package/dist/types/lib/recorder/QualityRecorder.d.ts +32 -5
- package/dist/types/lib/recorder/TopologyRecorder.d.ts +35 -5
- package/dist/types/lib/recorder/attemptMetricRows.d.ts +11 -0
- package/dist/types/lib/recorder/attemptMetrics.d.ts +7 -0
- package/dist/types/lib/recorder/attemptMetricsTypes.d.ts +114 -0
- package/dist/types/lib/recorder/attemptOTel.d.ts +78 -0
- package/dist/types/lib/recorder/attemptSeries.d.ts +81 -0
- package/dist/types/lib/recorder/hooks.d.ts +9 -0
- package/dist/types/lib/runner/ExecutionRuntime.d.ts +54 -6
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +46 -2
- package/dist/types/lib/runner/RunnableChart.d.ts +6 -0
- package/dist/types/lib/runner/attach.d.ts +2 -1
- package/dist/types/lib/runner/deadline.d.ts +42 -0
- package/dist/types/lib/runner/index.d.ts +3 -1
- package/dist/types/lib/runner/options.d.ts +17 -0
- package/dist/types/lib/runner/recordSink.d.ts +128 -0
- package/dist/types/lib/runner/resume.d.ts +3 -0
- package/dist/types/lib/runner/snapshot.d.ts +2 -2
- package/dist/types/lib/scope/ScopeFacade.d.ts +118 -4
- package/dist/types/lib/scope/recorders/DebugRecorder.d.ts +17 -3
- package/dist/types/lib/scope/recorders/MetricRecorder.d.ts +10 -0
- package/dist/types/lib/scope/runtime.d.ts +3 -0
- package/dist/types/lib/scope/types.d.ts +6 -0
- package/dist/types/lib/sinks/fileSink.d.ts +135 -0
- package/dist/types/recorders.d.ts +8 -2
- package/dist/types/sinks.d.ts +23 -0
- package/dist/types/trace.d.ts +2 -2
- package/package.json +20 -6
- package/dist/esm/lib/decide/evaluator.js +0 -130
- package/dist/lib/decide/evaluator.js +0 -134
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/observed.ts — an attempt the library did NOT run: an outside system's own retry (an SDK's), reported by an
|
|
3
|
+
* adapter through `AttemptContext.observed` (design §3.6, packet P2). Same record shape, kind `'observed'`.
|
|
4
|
+
*
|
|
5
|
+
* WHY: the incident behind this design was four 40 s attempts inside an SDK that the record called "one stage, one
|
|
6
|
+
* error". The best fix is one loop — the SDK's retries off, the call under `scope.$call`. Where an SDK must keep its
|
|
7
|
+
* retries, its adapter reports each one here, so the record says what happened rather than nothing.
|
|
8
|
+
*
|
|
9
|
+
* THREE LAWS.
|
|
10
|
+
* - A report is read, never trusted. Only the named fields are read, each ONCE (a getter cannot answer twice);
|
|
11
|
+
* a name is held to the one name rule (`name.ts`); numbers must be what they say. Anything else on the
|
|
12
|
+
* object — a request body, headers — is never read, so it can never reach a record ({@link readObservedReport}).
|
|
13
|
+
* - The error is served under the run's redaction rule (the owner's `serve`), like every attempt's error; the
|
|
14
|
+
* record keeps its named fields, and no hook is handed the adapter's error object (`raw` is dropped: the
|
|
15
|
+
* library never threw it, and an SDK error can carry its request).
|
|
16
|
+
* - An observed attempt never changes control flow. Its `decision` is the ONE rule table read over what the
|
|
17
|
+
* report states, under the default policy (every error retryable, no deadline) — the library's reading of the
|
|
18
|
+
* SDK's attempt, never the SDK's own decision, which the record cannot know. A report without `of` stands for
|
|
19
|
+
* the SDK's whole call: it is its last attempt, so a failure reads `exhausted`.
|
|
20
|
+
*
|
|
21
|
+
* SERIES. Reports are grouped by {@link ObservedSeriesBook}, owned by whoever owns the attempt they were reported
|
|
22
|
+
* on: a growing attempt number continues its target's series; a number that does not grow opens a new one (the
|
|
23
|
+
* SDK started another call).
|
|
24
|
+
*/
|
|
25
|
+
import type { StructuredErrorInfo } from '../errors/errorInfo.js';
|
|
26
|
+
import type { AttemptOutcome, AttemptRecord } from './types.js';
|
|
27
|
+
/** A report as read: every field once, validated, defaults applied. */
|
|
28
|
+
export interface ObservedReport {
|
|
29
|
+
readonly target: string;
|
|
30
|
+
readonly source: string;
|
|
31
|
+
readonly attempt: number;
|
|
32
|
+
readonly of?: number;
|
|
33
|
+
readonly outcome: Exclude<AttemptOutcome, 'paused'>;
|
|
34
|
+
readonly durationMs: number;
|
|
35
|
+
readonly startedAt?: number;
|
|
36
|
+
readonly error?: unknown;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Read an adapter's report: the named fields only, each once. A malformed report is refused with a `TypeError`
|
|
40
|
+
* naming the field (never its value).
|
|
41
|
+
*/
|
|
42
|
+
export declare function readObservedReport(report: unknown): ObservedReport;
|
|
43
|
+
/** What turns a report into a record — the owner's series, clock and served-error rule. */
|
|
44
|
+
export interface ObservedRecordInit {
|
|
45
|
+
readonly series: string;
|
|
46
|
+
readonly now: () => number;
|
|
47
|
+
readonly serve: (error: unknown) => StructuredErrorInfo;
|
|
48
|
+
}
|
|
49
|
+
/** The frozen record of a report, and the served error (with `raw`) the `onAttempt` hook carries. */
|
|
50
|
+
export declare function observedRecord(report: ObservedReport, init: ObservedRecordInit): {
|
|
51
|
+
record: AttemptRecord;
|
|
52
|
+
structuredError?: StructuredErrorInfo;
|
|
53
|
+
};
|
|
54
|
+
/** How many distinct target/source pairs one attempt's book remembers — past it, each report opens its own series. */
|
|
55
|
+
export declare const MAX_OPEN_OBSERVED_SERIES = 256;
|
|
56
|
+
/**
|
|
57
|
+
* Groups one attempt's observed reports into series. A report continues the open series of its target and source
|
|
58
|
+
* while its attempt number grows; otherwise it opens a new one through `open` (the owner's next call-level series).
|
|
59
|
+
* Bounded: it remembers at most {@link MAX_OPEN_OBSERVED_SERIES} names.
|
|
60
|
+
*/
|
|
61
|
+
export declare class ObservedSeriesBook {
|
|
62
|
+
private readonly openSeries;
|
|
63
|
+
private readonly open;
|
|
64
|
+
constructor(openSeries: () => string);
|
|
65
|
+
seriesFor(report: Pick<ObservedReport, 'target' | 'source' | 'attempt'>): string;
|
|
66
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/policy.ts — the ONE reading of a `RetryPolicy`'s ceiling, and the ONE rule for a valid policy.
|
|
3
|
+
*
|
|
4
|
+
* `attemptCeiling` is how many attempts a policy allows. Three readers ask it, so they can never disagree about a
|
|
5
|
+
* stage: the engine's gate (`FlowchartTraverser · executeStage` — does this stage retry at all?), the runner
|
|
6
|
+
* (`runAttempts` — every record's `of`) and the rule table (`retryRules` — rule 4's threshold).
|
|
7
|
+
*
|
|
8
|
+
* `retryPolicyProblem` says why a declared policy is refused. Two doors ask it, with the same words: the builder
|
|
9
|
+
* at build (`FlowChartBuilder · applyRetryPolicy`), and the traverser for a StageNode a stage returns at run time
|
|
10
|
+
* (`FlowchartTraverser · admitDynamicNodes`), which the builder never saw.
|
|
11
|
+
*/
|
|
12
|
+
import type { RetryPolicy } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* The attempts a policy allows: its whole number (a fraction is floored, as the 9.15 loop read it), and never
|
|
15
|
+
* fewer than one. Anything that is not a finite number of at least one — `NaN`, `Infinity`, `0`, a negative, a
|
|
16
|
+
* non-number — is `1`: a broken ceiling never loops.
|
|
17
|
+
*/
|
|
18
|
+
export declare function attemptCeiling(attempts: unknown): number;
|
|
19
|
+
/**
|
|
20
|
+
* Why `retry` is refused, or `undefined` when it is a valid policy: `attempts` must be a whole number ≥ 1, a
|
|
21
|
+
* declared `timeoutMs` a finite number > 0, and a declared `maxBackoffMs` a finite number ≥ 0. `attempts: 1` is
|
|
22
|
+
* valid on purpose — a policy declared but switched off (or, with a `timeoutMs`, a timeout with no retry).
|
|
23
|
+
*/
|
|
24
|
+
export declare function retryPolicyProblem(retry: Pick<RetryPolicy, 'attempts' | 'timeoutMs' | 'maxBackoffMs'>): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The ceiling a policy puts on ONE wait (`maxBackoffMs`): a finite number ≥ 0, else none. The runner caps every
|
|
27
|
+
* wait at it (`waitAfter`), and the static budget check counts each wait at it — one reading, so the check's bound
|
|
28
|
+
* is the runner's law.
|
|
29
|
+
*/
|
|
30
|
+
export declare function backoffCeilingMs(maxBackoffMs: unknown): number | undefined;
|
|
31
|
+
/** A wait the policy's `backoffMs` answered (already defended, `resolveBackoffMs`), capped at its declared ceiling. */
|
|
32
|
+
export declare function cappedWaitMs(waitMs: number, maxBackoffMs: unknown): number;
|
|
33
|
+
/**
|
|
34
|
+
* The cap a policy puts on one attempt: a finite number > 0, else none. The one reading the engine's gate and the
|
|
35
|
+
* runner share (the builder refuses any other declared value, `retryPolicyProblem`).
|
|
36
|
+
*/
|
|
37
|
+
export declare function attemptTimeoutMs(timeoutMs: unknown): number | undefined;
|
|
38
|
+
/** The policy of a call made with none: one attempt — still recorded (a single call is evidence too). */
|
|
39
|
+
export declare const SINGLE_CALL: RetryPolicy;
|
|
40
|
+
/**
|
|
41
|
+
* A `$call` / `attempt()` policy as the caller handed it: absent means {@link SINGLE_CALL}; anything else must be a
|
|
42
|
+
* valid `RetryPolicy` (`retryPolicyProblem`) or it is refused with a `TypeError` naming `where` — at the call,
|
|
43
|
+
* before anything runs.
|
|
44
|
+
*/
|
|
45
|
+
export declare function admitCallPolicy(where: string, policy: unknown): RetryPolicy;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/record.ts — how an `AttemptRecord` holds what it holds: frozen to its leaves, and an error only as the run
|
|
3
|
+
* SERVES it, named fields only. One owner, so a record the runner makes (`runner.ts`) and a record an adapter
|
|
4
|
+
* reports (`observed.ts`) can never differ in what they keep.
|
|
5
|
+
*/
|
|
6
|
+
import type { StructuredErrorInfo } from '../errors/errorInfo.js';
|
|
7
|
+
import type { AttemptError } from './types.js';
|
|
8
|
+
/** The record's copy of a served error: its named fields only — never `raw`, never an extra own key. */
|
|
9
|
+
export declare function recordedError(served: StructuredErrorInfo): AttemptError;
|
|
10
|
+
/** Freeze a record built of plain objects and arrays, to its leaves. */
|
|
11
|
+
export declare function freezeDeep<T>(value: T): T;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Internal one-call port: the builder declares logical identity; the call owner stamps it before dispatch. */
|
|
2
|
+
import type { RetryLoopCall } from './retryLoopTypes.js';
|
|
3
|
+
import type { AttemptRecord } from './types.js';
|
|
4
|
+
export interface RetryLoopCallPort {
|
|
5
|
+
readonly identity: RetryLoopCall;
|
|
6
|
+
readonly record: (record: AttemptRecord) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function registerRetryLoopCall(target: object, port: RetryLoopCallPort): () => void;
|
|
9
|
+
/** Claimed once, so nested calls made by the user's callback do not inherit the outer call's logical identity. */
|
|
10
|
+
export declare function takeRetryLoopCall(target: object): RetryLoopCallPort | undefined;
|
|
11
|
+
export interface RetryLoopBudget {
|
|
12
|
+
readonly passes?: number;
|
|
13
|
+
readonly role: 'callback' | 'control' | 'wait';
|
|
14
|
+
readonly timeoutMs?: number;
|
|
15
|
+
readonly waitMs?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function declareRetryLoopBudget(node: object, budget: RetryLoopBudget): void;
|
|
18
|
+
export declare function retryLoopBudget(node: object): RetryLoopBudget | undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Logical identity of an explicit retry workflow. Physical attempt identities remain unchanged. */
|
|
2
|
+
export interface RetryLoopIdentity {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly series: string;
|
|
5
|
+
readonly attempt: number;
|
|
6
|
+
readonly of: number;
|
|
7
|
+
}
|
|
8
|
+
/** The role of one physical call inside a logical pass. */
|
|
9
|
+
export interface RetryLoopCall extends RetryLoopIdentity {
|
|
10
|
+
readonly phase: 'attempt' | 'reconcile';
|
|
11
|
+
}
|
|
12
|
+
/** The explicit chart decision, after reconciliation; never rewrites a physical call's outcome. */
|
|
13
|
+
export interface RetryLoopDecision extends RetryLoopIdentity {
|
|
14
|
+
readonly effect: 'applied' | 'none' | 'unknown';
|
|
15
|
+
readonly reconciled: boolean;
|
|
16
|
+
readonly next: 'retry' | 'done' | 'stop';
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/runner.ts — `runAttempts`, THE retry loop (design §3.1, law 1: one runner, one record).
|
|
3
|
+
*
|
|
4
|
+
* Runs a function under a policy and records every try: one frozen `AttemptRecord` per attempt, carrying its
|
|
5
|
+
* timing, outcome, failure category and the retry-or-stop decision (`attempt/decision.ts`), and one
|
|
6
|
+
* `AttemptSummary` when the series ends. The engine's stage retry (`FlowchartTraverser · executeStage`) runs on
|
|
7
|
+
* it; later packets run in-stage calls and standalone `attempt()` on it too.
|
|
8
|
+
*
|
|
9
|
+
* The loop, per attempt n — for a failed attempt, the 9.15 loop's order, step for step:
|
|
10
|
+
*
|
|
11
|
+
* start → run(n) → outcome (ok | failed | aborted [it threw the run's abort reason] | paused [a PauseSignal])
|
|
12
|
+
* → decide over the inputs, first match wins (`retryRules`) — retryOn is asked here (rule 5)
|
|
13
|
+
* → the run's signal aborted inside retryOn? decide again: rule 3 stops the series here, before the
|
|
14
|
+
* discard and before backoffMs, as the 9.15 abort check did
|
|
15
|
+
* → retry: between(n) — the discard — and THEN backoffMs(n), the wait's length
|
|
16
|
+
* → the error's served form and category, read after retryOn and backoffMs ran → the record
|
|
17
|
+
* → onEnd(summary) only when the series ends here
|
|
18
|
+
* → onAttempt(record, served error)
|
|
19
|
+
* → done: return the value · stop: rethrow the attempt's OWN error
|
|
20
|
+
* → retry: onRetry(n, of, delay, served error) → wait (cut short by the signal) → aborted? stop
|
|
21
|
+
*
|
|
22
|
+
* WHAT IT PRESERVES (the 9.15 loop's behaviour, moved here unchanged): the function runs the same number of
|
|
23
|
+
* times; `retryOn` is asked only for a failed, non-final attempt; `backoffMs` only when a retry follows, after
|
|
24
|
+
* the discard; a throwing predicate is "do not retry", a throwing or non-finite backoff is "no wait"; a pause is
|
|
25
|
+
* never retried; the attempt's own error is rethrown, never a wrapper; and a failed attempt's order —
|
|
26
|
+
* `retryOn` → the abort check → the discard (`between`) → `backoffMs` → the served error → the retry event →
|
|
27
|
+
* the wait → the abort check. So an abort inside `retryOn` stops before the discard and never asks `backoffMs`;
|
|
28
|
+
* an abort inside `backoffMs` comes after the discard, still fires the retry event, then ends at the wait; and
|
|
29
|
+
* the served error shows what `retryOn` did to the thrown value. The one difference: when the run's signal has
|
|
30
|
+
* ALREADY aborted as the attempt fails, the series stops without asking `retryOn` (the abort decides first —
|
|
31
|
+
* rule 3 before rule 5).
|
|
32
|
+
*
|
|
33
|
+
* WHAT IT ADDS: the record and the summary. A record is frozen to its leaves and holds only clone-safe data —
|
|
34
|
+
* the error as the run SERVES it (`serve`, the redaction rule's form) without `raw`. The hook gets the served
|
|
35
|
+
* `StructuredErrorInfo` whole, `raw` included, as `onStageRetry` always has. A record never rewrites what the
|
|
36
|
+
* attempt did: an attempt that threw its own error is `failed`, with its category, even when the run aborted
|
|
37
|
+
* around it — the abort is the series' stop reason (`reason: 'aborted'`); a throwing `retryOn` is `declined`
|
|
38
|
+
* with `retryOnThrew: true`, apart from a real `false`.
|
|
39
|
+
*
|
|
40
|
+
* TIME (P1b). Each attempt runs under `min(policy.timeoutMs, time left before options.deadline)` and gets an
|
|
41
|
+
* `AttemptContext` — its signal, composed from the run's and its own cap's timer (`LiveAttempt`). The cap's timer
|
|
42
|
+
* aborts with an `AttemptTimeoutError`; the run's deadline aborts the run's signal with a branded reason
|
|
43
|
+
* (`attempt/deadline.ts`). Either way the attempt is `'timeout'`, never `'aborted'`: the deadline is not a
|
|
44
|
+
* cancellation, so rule 3 does not match and rule 6 (`timeLeftAfterWaitMs ≤ 0`) stops a series whose next wait
|
|
45
|
+
* would outlast it. Under a deadline rule 6 needs the wait's length, so `backoffMs(n, error)` is asked DURING the
|
|
46
|
+
* decision — before the discard; without one the 9.15 order above holds unchanged. No attempt starts at or past
|
|
47
|
+
* the deadline: a wait the deadline cut ends the series `no-time-left`, recording no further attempt.
|
|
48
|
+
*
|
|
49
|
+
* THE FENCE. The moment an attempt ends without an answer — its signal aborts (synchronously, before any listener
|
|
50
|
+
* the function added) or it throws — `onAbandon(n)` fires once, and the engine closes that attempt's scope: the
|
|
51
|
+
* function may still be running, and nothing it does afterwards may land beside a later attempt.
|
|
52
|
+
*
|
|
53
|
+
* ONE async frame with ONE await per attempt: the engine relies on that to keep a retried stage's microtask
|
|
54
|
+
* shape, so parallel siblings settle in the order they always did. The engine races the attempt's signal itself,
|
|
55
|
+
* at the stage boundary (`raced: true`); any other caller gets the race here, so the series never waits on an
|
|
56
|
+
* attempt past its cap.
|
|
57
|
+
*
|
|
58
|
+
* CALLS (P2). The same loop runs a call a stage makes (`attempt/call.ts · runCall`, kind `'call'`, its `target` on
|
|
59
|
+
* every record) and the standalone `attempt()`. An attempt's cap is the DEADLINE of every call made inside it, so
|
|
60
|
+
* the cap's reason is branded a time limit (`attempt/deadline.ts · markTimeLimit`): a call cut by its stage
|
|
61
|
+
* attempt's cap timed out, it was not cancelled. `attemptEndsAt` says when an attempt must end; an `interrupt()`
|
|
62
|
+
* thrown inside a call is a pause, like a `PauseSignal` — never retried.
|
|
63
|
+
*/
|
|
64
|
+
import type { StructuredErrorInfo } from '../errors/errorInfo.js';
|
|
65
|
+
import type { EffectTarget } from './effect.js';
|
|
66
|
+
import type { AttemptCategory, AttemptContext, AttemptKind, AttemptRecord, AttemptSummary, ObservedAttempt, RetryPolicy } from './types.js';
|
|
67
|
+
/** What a series reports, and the engine's between-attempt step. Every member is optional. */
|
|
68
|
+
export interface AttemptRunOptions {
|
|
69
|
+
/** The series every record names — for a stage attempt, its execution's `runtimeStageId`. */
|
|
70
|
+
readonly series: string;
|
|
71
|
+
/** Default `'stage'`. */
|
|
72
|
+
readonly kind?: AttemptKind;
|
|
73
|
+
/** The outside target every record names — a call's (`$call`, `attempt()`); absent for a stage attempt. */
|
|
74
|
+
readonly target?: string;
|
|
75
|
+
/**
|
|
76
|
+
* The run's signal. Once it has aborted (other than at the deadline), rule 3 stops the series
|
|
77
|
+
* (`reason: 'aborted'`); it cuts a wait short. An attempt that threw its reason is recorded `'aborted'` — or
|
|
78
|
+
* `'timeout'` when the reason is the deadline's (`attempt/deadline.ts`).
|
|
79
|
+
*/
|
|
80
|
+
readonly signal?: AbortSignal;
|
|
81
|
+
/**
|
|
82
|
+
* The run's deadline, epoch milliseconds. Every attempt is capped by the time left; rule 6 stops a series whose
|
|
83
|
+
* next wait would outlast it (`no-time-left`). Absent (or not finite) = no deadline: the time left is `Infinity`.
|
|
84
|
+
*/
|
|
85
|
+
readonly deadline?: number;
|
|
86
|
+
/** The clock, epoch milliseconds. Default `Date.now`. */
|
|
87
|
+
readonly now?: () => number;
|
|
88
|
+
/** The served form of a failed attempt's error. Default `extractErrorInfo` (no redaction rule). */
|
|
89
|
+
readonly serve?: (error: unknown) => StructuredErrorInfo;
|
|
90
|
+
/** Between a failed attempt and the next, before `backoffMs`: the engine discards the attempt's staged writes. */
|
|
91
|
+
readonly between?: (attempt: number) => void;
|
|
92
|
+
/** Every attempt, at its end, with its served error (`undefined` for `'ok'` and `'paused'`). */
|
|
93
|
+
readonly onAttempt?: (record: AttemptRecord, structuredError: StructuredErrorInfo | undefined) => void;
|
|
94
|
+
/** A failed attempt that WILL be retried — after `between` and `onAttempt`, before the wait. */
|
|
95
|
+
readonly onRetry?: (attempt: number, of: number, delayMs: number, structuredError: StructuredErrorInfo) => void;
|
|
96
|
+
/** The series ended: called once, before the last `onAttempt` (or after a wait the run's signal cut). */
|
|
97
|
+
readonly onEnd?: (summary: AttemptSummary) => void;
|
|
98
|
+
/** @internal Native owner only: the exact escaping value and category, before its stage serves the error. */
|
|
99
|
+
readonly onFailure?: (error: unknown, category: AttemptCategory) => void;
|
|
100
|
+
/** `retryOn` threw — the attempt is treated as declined; the engine logs the throw here. */
|
|
101
|
+
readonly onRetryOnThrew?: (thrown: unknown) => void;
|
|
102
|
+
/**
|
|
103
|
+
* The attempt ended without an answer — called SYNCHRONOUSLY the moment its signal aborts (its cap, the deadline,
|
|
104
|
+
* a cancellation), else as soon as it failed. Whatever the abandoned function does afterwards is not this
|
|
105
|
+
* series': the engine fences its scope here. Once per attempt; never for `'ok'` or `'paused'` — except an attempt
|
|
106
|
+
* that STARTED under an already-aborted signal, fenced once its synchronous part has run (nobody waits for it).
|
|
107
|
+
*/
|
|
108
|
+
readonly onAbandon?: (attempt: number) => void;
|
|
109
|
+
/**
|
|
110
|
+
* The caller races `run`'s promise against the attempt's signal itself — the engine does, at the stage boundary
|
|
111
|
+
* (`StageRunner`), so a stage keeps its one await per attempt. Otherwise the runner races it: the series never
|
|
112
|
+
* waits on an attempt past its cap.
|
|
113
|
+
*/
|
|
114
|
+
readonly raced?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* What an attempt's `observed(report)` does (P2) — the owner of the attempt records the report: `runCall` hands
|
|
117
|
+
* a call's reports to the scope, `attempt()` keeps its own. `ended` says the attempt had already ended when the
|
|
118
|
+
* report came (the owner drops it). Absent — a stage attempt's context, whose `observed` the scope's
|
|
119
|
+
* `$attempt()` replaces — `observed` is refused with a `TypeError`.
|
|
120
|
+
*/
|
|
121
|
+
readonly observe?: (report: ObservedAttempt, at: {
|
|
122
|
+
readonly attempt: number;
|
|
123
|
+
readonly ended: boolean;
|
|
124
|
+
}) => void;
|
|
125
|
+
/**
|
|
126
|
+
* The outside system the target touches (P3, design §3.3). Every record then says what its attempt did to it
|
|
127
|
+
* (`effect`) and names the system and the RECORDED key; every attempt's context carries the REAL key. A series
|
|
128
|
+
* that ends without an answer after any attempt of unknown effect fails with `UnknownEffectError` (its `cause` the attempt's own error) —
|
|
129
|
+
* except a pause, which stays a pause. A touching series that may retry without a key is refused before anything
|
|
130
|
+
* runs: the law's last door.
|
|
131
|
+
*/
|
|
132
|
+
readonly effect?: EffectTarget;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* When the attempt behind `context` must end, epoch milliseconds — its start plus its cap (`min(timeoutMs, time
|
|
136
|
+
* left)`, so never past the run's deadline) — or `undefined` for an uncapped attempt. A call made inside the
|
|
137
|
+
* attempt runs under it as its deadline (`attempt/call.ts`). Only the runner's own contexts are known.
|
|
138
|
+
*/
|
|
139
|
+
export declare function attemptEndsAt(context: AttemptContext | undefined): number | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* Run `run` until it succeeds or the policy stops it; resolve with its value or reject with the LAST attempt's
|
|
142
|
+
* own error. `run(n)` is called with the attempt number, 1-based.
|
|
143
|
+
*/
|
|
144
|
+
export declare function runAttempts<T>(run: (attempt: number, context: AttemptContext) => Promise<T> | T, policy: RetryPolicy, options: AttemptRunOptions): Promise<T>;
|
|
145
|
+
/**
|
|
146
|
+
* Resolve a policy's `backoffMs` for the attempt that just failed (1-based) and its error. Anything that is not a finite,
|
|
147
|
+
* positive number — a missing dial, a negative value, a `NaN` from a consumer's arithmetic, or a throwing
|
|
148
|
+
* function — becomes `0`, i.e. retry immediately. A backoff dial must never be able to crash a run or park it
|
|
149
|
+
* forever.
|
|
150
|
+
*/
|
|
151
|
+
export declare function resolveBackoffMs(backoffMs: RetryPolicy['backoffMs'], attempt: number, error?: unknown): number;
|
|
152
|
+
/**
|
|
153
|
+
* Await `ms`, cut short by an abort. Resolves either way — the caller re-checks `signal.aborted` and rethrows
|
|
154
|
+
* the attempt's own error, so a cancelled run never sits out a long backoff and never loses the failure that
|
|
155
|
+
* caused it. The timer and the listener are always cleaned up.
|
|
156
|
+
*/
|
|
157
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/standalone.ts — `attempt(fn, policy?, options?)`: the attempt runner with no scope and no run (design §3.6,
|
|
3
|
+
* packet P2).
|
|
4
|
+
*
|
|
5
|
+
* The same loop, the same record (law 1) for code that is not a stage — a provider decorator, a client wrapper, a
|
|
6
|
+
* script. There is no run, so there is no execution tree and no hook: every record goes to `options.onAttempt`, the
|
|
7
|
+
* caller's own, as each attempt ends. There is no redaction rule either: the record holds the error's named fields
|
|
8
|
+
* (never the thrown value), and the caller's callback decides what to keep.
|
|
9
|
+
*
|
|
10
|
+
* Time and cancellation are the caller's: `deadline` caps every attempt by the time left (and a wait that would
|
|
11
|
+
* outlast it is never started — `no-time-left`); `signal` cancels. A deadline already past, or a signal already
|
|
12
|
+
* aborted, starts no attempt and records nothing.
|
|
13
|
+
*
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const res = await attempt((t) => fetch(url, { signal: t.signal }), { attempts: 3, timeoutMs: 5_000 }, {
|
|
16
|
+
* target: 'inventory.lookup',
|
|
17
|
+
* deadline: Date.now() + 20_000,
|
|
18
|
+
* onAttempt: (record) => log.info(record),
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { AttemptContext, AttemptRecord, RetryPolicy } from './types.js';
|
|
23
|
+
/** How a standalone attempt series is named, timed and reported. */
|
|
24
|
+
export interface AttemptOptions {
|
|
25
|
+
/** The outside target — a name from code (1–128 characters, no control character), stamped on every record. */
|
|
26
|
+
readonly target?: string;
|
|
27
|
+
/**
|
|
28
|
+
* The series every record names — the caller's name for this one operation (an order id, a request id), so two
|
|
29
|
+
* operations can be told apart. Default: the target, else `'attempt'`.
|
|
30
|
+
*/
|
|
31
|
+
readonly series?: string;
|
|
32
|
+
/** The deadline, epoch milliseconds: every attempt is capped by the time left before it. */
|
|
33
|
+
readonly deadline?: number;
|
|
34
|
+
/** Cancels the series: the attempt in flight is cut (`aborted`), a wait ends, and no attempt follows. */
|
|
35
|
+
readonly signal?: AbortSignal;
|
|
36
|
+
/**
|
|
37
|
+
* Every attempt, at its end — the only place a standalone record goes. A throw from it is isolated: it never
|
|
38
|
+
* changes the call's outcome (dev mode warns).
|
|
39
|
+
*/
|
|
40
|
+
readonly onAttempt?: (record: AttemptRecord) => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Run `fn` under `policy` (none = one attempt, still recorded) and resolve with its answer, or reject with the LAST
|
|
44
|
+
* attempt's own error. `fn` gets the attempt's `AttemptContext`: pass `signal` to the work, read `timeLeftMs()`,
|
|
45
|
+
* and report an SDK's own retries with `observed()`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function attempt<T>(fn: (attempt: AttemptContext) => Promise<T> | T, policy?: RetryPolicy, options?: AttemptOptions): Promise<T>;
|