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,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/errors.ts — the errors the attempt contract throws (design §3.3).
|
|
3
|
+
*
|
|
4
|
+
* - `AttemptTimeoutError` — the attempt's OWN timer ended it (`RetryPolicy.timeoutMs` / the run's deadline). A
|
|
5
|
+
* timeout is the absence of an answer, not a failure of the outside system (law 4); `errorCategory` reads it
|
|
6
|
+
* as `'timeout'`.
|
|
7
|
+
* - `UnknownEffectError` — a side-effecting target's last attempt ended with no answer, so nobody knows whether
|
|
8
|
+
* the effect happened. "Reconcile, do not retry blindly" is on the error, not in prose.
|
|
9
|
+
*
|
|
10
|
+
* The idempotency key is a VALUE: it rides the error as a field (a redaction rule selects it by name) and is
|
|
11
|
+
* never spelled in a message.
|
|
12
|
+
*/
|
|
13
|
+
/** The attempt's own time cap ran out before it answered. */
|
|
14
|
+
export declare class AttemptTimeoutError extends Error {
|
|
15
|
+
/** The attempt that ran out of time, 1-based. */
|
|
16
|
+
readonly attempt: number;
|
|
17
|
+
/** The cap it ran under, in milliseconds. */
|
|
18
|
+
readonly timeoutMs: number;
|
|
19
|
+
constructor(attempt: number, timeoutMs: number, options?: {
|
|
20
|
+
readonly cause?: unknown;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** What an `UnknownEffectError` names. */
|
|
24
|
+
export interface UnknownEffectInit {
|
|
25
|
+
/** The outside system the stage touches — a name, never a value. */
|
|
26
|
+
readonly system: string;
|
|
27
|
+
/** The key the effect was attempted under — a value, kept as a field and never put in the message. */
|
|
28
|
+
readonly idempotencyKey?: string;
|
|
29
|
+
/** How many attempts ran. */
|
|
30
|
+
readonly attempts: number;
|
|
31
|
+
/** The last attempt's own error. */
|
|
32
|
+
readonly cause?: unknown;
|
|
33
|
+
}
|
|
34
|
+
/** A side-effecting target's last attempt ended with no answer: whether the effect happened is unknown. */
|
|
35
|
+
export declare class UnknownEffectError extends Error {
|
|
36
|
+
readonly system: string;
|
|
37
|
+
/** Absent (not `undefined`) when no key was given — `declare`, so no class field is emitted for it. */
|
|
38
|
+
readonly idempotencyKey?: string;
|
|
39
|
+
readonly attempts: number;
|
|
40
|
+
constructor(init: UnknownEffectInit);
|
|
41
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/errors.ts — the errors the attempt contract throws (design §3.3).
|
|
3
|
+
*
|
|
4
|
+
* - `AttemptTimeoutError` — the attempt's OWN timer ended it (`RetryPolicy.timeoutMs` / the run's deadline). A
|
|
5
|
+
* timeout is the absence of an answer, not a failure of the outside system (law 4); `errorCategory` reads it
|
|
6
|
+
* as `'timeout'`.
|
|
7
|
+
* - `UnknownEffectError` — a side-effecting target's last attempt ended with no answer, so nobody knows whether
|
|
8
|
+
* the effect happened. "Reconcile, do not retry blindly" is on the error, not in prose.
|
|
9
|
+
*
|
|
10
|
+
* The idempotency key is a VALUE: it rides the error as a field (a redaction rule selects it by name) and is
|
|
11
|
+
* never spelled in a message.
|
|
12
|
+
*/
|
|
13
|
+
/** The attempt's own time cap ran out before it answered. */
|
|
14
|
+
export class AttemptTimeoutError extends Error {
|
|
15
|
+
/** The attempt that ran out of time, 1-based. */
|
|
16
|
+
attempt;
|
|
17
|
+
/** The cap it ran under, in milliseconds. */
|
|
18
|
+
timeoutMs;
|
|
19
|
+
constructor(attempt, timeoutMs, options) {
|
|
20
|
+
super(`attempt ${attempt} ran out of its ${timeoutMs}ms before it answered`);
|
|
21
|
+
this.name = 'AttemptTimeoutError';
|
|
22
|
+
this.attempt = attempt;
|
|
23
|
+
this.timeoutMs = timeoutMs;
|
|
24
|
+
if (options && Object.prototype.hasOwnProperty.call(options, 'cause'))
|
|
25
|
+
this.cause = options.cause;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** A side-effecting target's last attempt ended with no answer: whether the effect happened is unknown. */
|
|
29
|
+
export class UnknownEffectError extends Error {
|
|
30
|
+
system;
|
|
31
|
+
attempts;
|
|
32
|
+
constructor(init) {
|
|
33
|
+
super(`"${init.system}": the effect of attempt ${init.attempts} is unknown — reconcile with the system ` +
|
|
34
|
+
'(look the operation up by its idempotency key) before trying again');
|
|
35
|
+
this.name = 'UnknownEffectError';
|
|
36
|
+
this.system = init.system;
|
|
37
|
+
if (init.idempotencyKey !== undefined)
|
|
38
|
+
this.idempotencyKey = init.idempotencyKey;
|
|
39
|
+
this.attempts = init.attempts;
|
|
40
|
+
if (Object.prototype.hasOwnProperty.call(init, 'cause'))
|
|
41
|
+
this.cause = init.cause;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9hdHRlbXB0L2Vycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7R0FXRztBQUVILDZEQUE2RDtBQUM3RCxNQUFNLE9BQU8sbUJBQW9CLFNBQVEsS0FBSztJQUM1QyxpREFBaUQ7SUFDeEMsT0FBTyxDQUFTO0lBQ3pCLDZDQUE2QztJQUNwQyxTQUFTLENBQVM7SUFFM0IsWUFBWSxPQUFlLEVBQUUsU0FBaUIsRUFBRSxPQUFzQztRQUNwRixLQUFLLENBQUMsV0FBVyxPQUFPLG1CQUFtQixTQUFTLHVCQUF1QixDQUFDLENBQUM7UUFDN0UsSUFBSSxDQUFDLElBQUksR0FBRyxxQkFBcUIsQ0FBQztRQUNsQyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLE9BQU8sSUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQztZQUFFLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztJQUNwRyxDQUFDO0NBQ0Y7QUFjRCwyR0FBMkc7QUFDM0csTUFBTSxPQUFPLGtCQUFtQixTQUFRLEtBQUs7SUFDbEMsTUFBTSxDQUFTO0lBR2YsUUFBUSxDQUFTO0lBRTFCLFlBQVksSUFBdUI7UUFDakMsS0FBSyxDQUNILElBQUksSUFBSSxDQUFDLE1BQU0sNEJBQTRCLElBQUksQ0FBQyxRQUFRLDBDQUEwQztZQUNoRyxvRUFBb0UsQ0FDdkUsQ0FBQztRQUNGLElBQUksQ0FBQyxJQUFJLEdBQUcsb0JBQW9CLENBQUM7UUFDakMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQzFCLElBQUksSUFBSSxDQUFDLGNBQWMsS0FBSyxTQUFTO1lBQUUsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDO1FBQ2pGLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUM5QixJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDO1lBQUUsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ25GLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYXR0ZW1wdC9lcnJvcnMudHMg4oCUIHRoZSBlcnJvcnMgdGhlIGF0dGVtcHQgY29udHJhY3QgdGhyb3dzIChkZXNpZ24gwqczLjMpLlxuICpcbiAqIC0gYEF0dGVtcHRUaW1lb3V0RXJyb3JgIOKAlCB0aGUgYXR0ZW1wdCdzIE9XTiB0aW1lciBlbmRlZCBpdCAoYFJldHJ5UG9saWN5LnRpbWVvdXRNc2AgLyB0aGUgcnVuJ3MgZGVhZGxpbmUpLiBBXG4gKiAgIHRpbWVvdXQgaXMgdGhlIGFic2VuY2Ugb2YgYW4gYW5zd2VyLCBub3QgYSBmYWlsdXJlIG9mIHRoZSBvdXRzaWRlIHN5c3RlbSAobGF3IDQpOyBgZXJyb3JDYXRlZ29yeWAgcmVhZHMgaXRcbiAqICAgYXMgYCd0aW1lb3V0J2AuXG4gKiAtIGBVbmtub3duRWZmZWN0RXJyb3JgIOKAlCBhIHNpZGUtZWZmZWN0aW5nIHRhcmdldCdzIGxhc3QgYXR0ZW1wdCBlbmRlZCB3aXRoIG5vIGFuc3dlciwgc28gbm9ib2R5IGtub3dzIHdoZXRoZXJcbiAqICAgdGhlIGVmZmVjdCBoYXBwZW5lZC4gXCJSZWNvbmNpbGUsIGRvIG5vdCByZXRyeSBibGluZGx5XCIgaXMgb24gdGhlIGVycm9yLCBub3QgaW4gcHJvc2UuXG4gKlxuICogVGhlIGlkZW1wb3RlbmN5IGtleSBpcyBhIFZBTFVFOiBpdCByaWRlcyB0aGUgZXJyb3IgYXMgYSBmaWVsZCAoYSByZWRhY3Rpb24gcnVsZSBzZWxlY3RzIGl0IGJ5IG5hbWUpIGFuZCBpc1xuICogbmV2ZXIgc3BlbGxlZCBpbiBhIG1lc3NhZ2UuXG4gKi9cblxuLyoqIFRoZSBhdHRlbXB0J3Mgb3duIHRpbWUgY2FwIHJhbiBvdXQgYmVmb3JlIGl0IGFuc3dlcmVkLiAqL1xuZXhwb3J0IGNsYXNzIEF0dGVtcHRUaW1lb3V0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIC8qKiBUaGUgYXR0ZW1wdCB0aGF0IHJhbiBvdXQgb2YgdGltZSwgMS1iYXNlZC4gKi9cbiAgcmVhZG9ubHkgYXR0ZW1wdDogbnVtYmVyO1xuICAvKiogVGhlIGNhcCBpdCByYW4gdW5kZXIsIGluIG1pbGxpc2Vjb25kcy4gKi9cbiAgcmVhZG9ubHkgdGltZW91dE1zOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoYXR0ZW1wdDogbnVtYmVyLCB0aW1lb3V0TXM6IG51bWJlciwgb3B0aW9ucz86IHsgcmVhZG9ubHkgY2F1c2U/OiB1bmtub3duIH0pIHtcbiAgICBzdXBlcihgYXR0ZW1wdCAke2F0dGVtcHR9IHJhbiBvdXQgb2YgaXRzICR7dGltZW91dE1zfW1zIGJlZm9yZSBpdCBhbnN3ZXJlZGApO1xuICAgIHRoaXMubmFtZSA9ICdBdHRlbXB0VGltZW91dEVycm9yJztcbiAgICB0aGlzLmF0dGVtcHQgPSBhdHRlbXB0O1xuICAgIHRoaXMudGltZW91dE1zID0gdGltZW91dE1zO1xuICAgIGlmIChvcHRpb25zICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvcHRpb25zLCAnY2F1c2UnKSkgdGhpcy5jYXVzZSA9IG9wdGlvbnMuY2F1c2U7XG4gIH1cbn1cblxuLyoqIFdoYXQgYW4gYFVua25vd25FZmZlY3RFcnJvcmAgbmFtZXMuICovXG5leHBvcnQgaW50ZXJmYWNlIFVua25vd25FZmZlY3RJbml0IHtcbiAgLyoqIFRoZSBvdXRzaWRlIHN5c3RlbSB0aGUgc3RhZ2UgdG91Y2hlcyDigJQgYSBuYW1lLCBuZXZlciBhIHZhbHVlLiAqL1xuICByZWFkb25seSBzeXN0ZW06IHN0cmluZztcbiAgLyoqIFRoZSBrZXkgdGhlIGVmZmVjdCB3YXMgYXR0ZW1wdGVkIHVuZGVyIOKAlCBhIHZhbHVlLCBrZXB0IGFzIGEgZmllbGQgYW5kIG5ldmVyIHB1dCBpbiB0aGUgbWVzc2FnZS4gKi9cbiAgcmVhZG9ubHkgaWRlbXBvdGVuY3lLZXk/OiBzdHJpbmc7XG4gIC8qKiBIb3cgbWFueSBhdHRlbXB0cyByYW4uICovXG4gIHJlYWRvbmx5IGF0dGVtcHRzOiBudW1iZXI7XG4gIC8qKiBUaGUgbGFzdCBhdHRlbXB0J3Mgb3duIGVycm9yLiAqL1xuICByZWFkb25seSBjYXVzZT86IHVua25vd247XG59XG5cbi8qKiBBIHNpZGUtZWZmZWN0aW5nIHRhcmdldCdzIGxhc3QgYXR0ZW1wdCBlbmRlZCB3aXRoIG5vIGFuc3dlcjogd2hldGhlciB0aGUgZWZmZWN0IGhhcHBlbmVkIGlzIHVua25vd24uICovXG5leHBvcnQgY2xhc3MgVW5rbm93bkVmZmVjdEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICByZWFkb25seSBzeXN0ZW06IHN0cmluZztcbiAgLyoqIEFic2VudCAobm90IGB1bmRlZmluZWRgKSB3aGVuIG5vIGtleSB3YXMgZ2l2ZW4g4oCUIGBkZWNsYXJlYCwgc28gbm8gY2xhc3MgZmllbGQgaXMgZW1pdHRlZCBmb3IgaXQuICovXG4gIGRlY2xhcmUgcmVhZG9ubHkgaWRlbXBvdGVuY3lLZXk/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGF0dGVtcHRzOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoaW5pdDogVW5rbm93bkVmZmVjdEluaXQpIHtcbiAgICBzdXBlcihcbiAgICAgIGBcIiR7aW5pdC5zeXN0ZW19XCI6IHRoZSBlZmZlY3Qgb2YgYXR0ZW1wdCAke2luaXQuYXR0ZW1wdHN9IGlzIHVua25vd24g4oCUIHJlY29uY2lsZSB3aXRoIHRoZSBzeXN0ZW0gYCArXG4gICAgICAgICcobG9vayB0aGUgb3BlcmF0aW9uIHVwIGJ5IGl0cyBpZGVtcG90ZW5jeSBrZXkpIGJlZm9yZSB0cnlpbmcgYWdhaW4nLFxuICAgICk7XG4gICAgdGhpcy5uYW1lID0gJ1Vua25vd25FZmZlY3RFcnJvcic7XG4gICAgdGhpcy5zeXN0ZW0gPSBpbml0LnN5c3RlbTtcbiAgICBpZiAoaW5pdC5pZGVtcG90ZW5jeUtleSAhPT0gdW5kZWZpbmVkKSB0aGlzLmlkZW1wb3RlbmN5S2V5ID0gaW5pdC5pZGVtcG90ZW5jeUtleTtcbiAgICB0aGlzLmF0dGVtcHRzID0gaW5pdC5hdHRlbXB0cztcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGluaXQsICdjYXVzZScpKSB0aGlzLmNhdXNlID0gaW5pdC5jYXVzZTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/ — one runner, one record: every attempt the library runs is an `AttemptRecord` with the
|
|
3
|
+
* retry-or-stop decision that followed it (design docs/design/2026-10-time-and-failure-evidence.md).
|
|
4
|
+
*
|
|
5
|
+
* Public: the record's vocabulary, the one failure classifier, the one rule table, the two errors, and `attempt()`
|
|
6
|
+
* — the runner for code that is not a stage (P2). The loop itself (`runAttempts`), `runCall`, the evidence builder
|
|
7
|
+
* and `anySignal` are the engine's. `RetryPolicy` is declared in
|
|
8
|
+
* `./types.ts` and published through the builder's barrel, where it always was.
|
|
9
|
+
*/
|
|
10
|
+
export { errorCategory } from './category.js';
|
|
11
|
+
export type { ParsedTraceparent, TraceparentFields, TraceparentRefusal } from './correlation.js';
|
|
12
|
+
export { formatTraceparent, parseTraceparent, TraceparentError } from './correlation.js';
|
|
13
|
+
export { retryRules } from './decision.js';
|
|
14
|
+
export type { UnknownEffectInit } from './errors.js';
|
|
15
|
+
export { AttemptTimeoutError, UnknownEffectError } from './errors.js';
|
|
16
|
+
export type { AttemptOptions } from './standalone.js';
|
|
17
|
+
export { attempt } from './standalone.js';
|
|
18
|
+
export type { AttemptCategory, AttemptContext, AttemptEffect, AttemptError, AttemptInputs, AttemptKind, AttemptNext, AttemptOutcome, AttemptReason, AttemptRecord, AttemptSummary, CallOptions, IdempotencyKeyContext, LateWrite, ObservedAttempt, RunCorrelation, StageTouches, } from './types.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/ — one runner, one record: every attempt the library runs is an `AttemptRecord` with the
|
|
3
|
+
* retry-or-stop decision that followed it (design docs/design/2026-10-time-and-failure-evidence.md).
|
|
4
|
+
*
|
|
5
|
+
* Public: the record's vocabulary, the one failure classifier, the one rule table, the two errors, and `attempt()`
|
|
6
|
+
* — the runner for code that is not a stage (P2). The loop itself (`runAttempts`), `runCall`, the evidence builder
|
|
7
|
+
* and `anySignal` are the engine's. `RetryPolicy` is declared in
|
|
8
|
+
* `./types.ts` and published through the builder's barrel, where it always was.
|
|
9
|
+
*/
|
|
10
|
+
export { errorCategory } from './category.js';
|
|
11
|
+
export { formatTraceparent, parseTraceparent, TraceparentError } from './correlation.js';
|
|
12
|
+
export { retryRules } from './decision.js';
|
|
13
|
+
export { AttemptTimeoutError, UnknownEffectError } from './errors.js';
|
|
14
|
+
export { attempt } from './standalone.js';
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2F0dGVtcHQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0dBUUc7QUFFSCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTlDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3pGLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFM0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXRFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYXR0ZW1wdC8g4oCUIG9uZSBydW5uZXIsIG9uZSByZWNvcmQ6IGV2ZXJ5IGF0dGVtcHQgdGhlIGxpYnJhcnkgcnVucyBpcyBhbiBgQXR0ZW1wdFJlY29yZGAgd2l0aCB0aGVcbiAqIHJldHJ5LW9yLXN0b3AgZGVjaXNpb24gdGhhdCBmb2xsb3dlZCBpdCAoZGVzaWduIGRvY3MvZGVzaWduLzIwMjYtMTAtdGltZS1hbmQtZmFpbHVyZS1ldmlkZW5jZS5tZCkuXG4gKlxuICogUHVibGljOiB0aGUgcmVjb3JkJ3Mgdm9jYWJ1bGFyeSwgdGhlIG9uZSBmYWlsdXJlIGNsYXNzaWZpZXIsIHRoZSBvbmUgcnVsZSB0YWJsZSwgdGhlIHR3byBlcnJvcnMsIGFuZCBgYXR0ZW1wdCgpYFxuICog4oCUIHRoZSBydW5uZXIgZm9yIGNvZGUgdGhhdCBpcyBub3QgYSBzdGFnZSAoUDIpLiBUaGUgbG9vcCBpdHNlbGYgKGBydW5BdHRlbXB0c2ApLCBgcnVuQ2FsbGAsIHRoZSBldmlkZW5jZSBidWlsZGVyXG4gKiBhbmQgYGFueVNpZ25hbGAgYXJlIHRoZSBlbmdpbmUncy4gYFJldHJ5UG9saWN5YCBpcyBkZWNsYXJlZCBpblxuICogYC4vdHlwZXMudHNgIGFuZCBwdWJsaXNoZWQgdGhyb3VnaCB0aGUgYnVpbGRlcidzIGJhcnJlbCwgd2hlcmUgaXQgYWx3YXlzIHdhcy5cbiAqL1xuXG5leHBvcnQgeyBlcnJvckNhdGVnb3J5IH0gZnJvbSAnLi9jYXRlZ29yeS5qcyc7XG5leHBvcnQgdHlwZSB7IFBhcnNlZFRyYWNlcGFyZW50LCBUcmFjZXBhcmVudEZpZWxkcywgVHJhY2VwYXJlbnRSZWZ1c2FsIH0gZnJvbSAnLi9jb3JyZWxhdGlvbi5qcyc7XG5leHBvcnQgeyBmb3JtYXRUcmFjZXBhcmVudCwgcGFyc2VUcmFjZXBhcmVudCwgVHJhY2VwYXJlbnRFcnJvciB9IGZyb20gJy4vY29ycmVsYXRpb24uanMnO1xuZXhwb3J0IHsgcmV0cnlSdWxlcyB9IGZyb20gJy4vZGVjaXNpb24uanMnO1xuZXhwb3J0IHR5cGUgeyBVbmtub3duRWZmZWN0SW5pdCB9IGZyb20gJy4vZXJyb3JzLmpzJztcbmV4cG9ydCB7IEF0dGVtcHRUaW1lb3V0RXJyb3IsIFVua25vd25FZmZlY3RFcnJvciB9IGZyb20gJy4vZXJyb3JzLmpzJztcbmV4cG9ydCB0eXBlIHsgQXR0ZW1wdE9wdGlvbnMgfSBmcm9tICcuL3N0YW5kYWxvbmUuanMnO1xuZXhwb3J0IHsgYXR0ZW1wdCB9IGZyb20gJy4vc3RhbmRhbG9uZS5qcyc7XG5leHBvcnQgdHlwZSB7XG4gIEF0dGVtcHRDYXRlZ29yeSxcbiAgQXR0ZW1wdENvbnRleHQsXG4gIEF0dGVtcHRFZmZlY3QsXG4gIEF0dGVtcHRFcnJvcixcbiAgQXR0ZW1wdElucHV0cyxcbiAgQXR0ZW1wdEtpbmQsXG4gIEF0dGVtcHROZXh0LFxuICBBdHRlbXB0T3V0Y29tZSxcbiAgQXR0ZW1wdFJlYXNvbixcbiAgQXR0ZW1wdFJlY29yZCxcbiAgQXR0ZW1wdFN1bW1hcnksXG4gIENhbGxPcHRpb25zLFxuICBJZGVtcG90ZW5jeUtleUNvbnRleHQsXG4gIExhdGVXcml0ZSxcbiAgT2JzZXJ2ZWRBdHRlbXB0LFxuICBSdW5Db3JyZWxhdGlvbixcbiAgU3RhZ2VUb3VjaGVzLFxufSBmcm9tICcuL3R5cGVzLmpzJztcbiJdfQ==
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/name.ts — the ONE rule for a name an attempt record carries (design §3.6, threat model, packet P2): the
|
|
3
|
+
* target of a `$call` / `attempt()`, a standalone series, and an observed report's target and source.
|
|
4
|
+
*
|
|
5
|
+
* A target is a NAME from code — `'stripe.quotes.create'` — never from a model and never a value. It rides every
|
|
6
|
+
* record, narrative line, recorder row and metric key exactly as given, so a name is refused unless it is a string
|
|
7
|
+
* of 1–{@link MAX_NAME_LENGTH} characters, not blank, with no control (C0, DEL, C1), format (zero-width, bidi
|
|
8
|
+
* overrides), surrogate, line/paragraph-separator, private-use or noncharacter code point:
|
|
9
|
+
* - an empty or blank name names nothing;
|
|
10
|
+
* - an overlong one is a value, or a flood of one;
|
|
11
|
+
* - a control or separator character forges a narrative line or a log record, and a bidi override hides what a
|
|
12
|
+
* line says.
|
|
13
|
+
* The refusal names the FIELD, never the value (P4's precedent): a rejected name may be exactly what must not be
|
|
14
|
+
* echoed. A `TypeError`, because a malformed name is the caller's code breaking its contract.
|
|
15
|
+
*/
|
|
16
|
+
/** The longest name an attempt record carries. */
|
|
17
|
+
export declare const MAX_NAME_LENGTH = 128;
|
|
18
|
+
/** Why `value` is not a name, or `undefined` when it is one. */
|
|
19
|
+
export declare function attemptNameProblem(value: unknown): string | undefined;
|
|
20
|
+
/** `value` as a name, or a `TypeError` that names `where` and `field` (never the value). */
|
|
21
|
+
export declare function admitAttemptName(where: string, field: string, value: unknown): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attempt/name.ts — the ONE rule for a name an attempt record carries (design §3.6, threat model, packet P2): the
|
|
3
|
+
* target of a `$call` / `attempt()`, a standalone series, and an observed report's target and source.
|
|
4
|
+
*
|
|
5
|
+
* A target is a NAME from code — `'stripe.quotes.create'` — never from a model and never a value. It rides every
|
|
6
|
+
* record, narrative line, recorder row and metric key exactly as given, so a name is refused unless it is a string
|
|
7
|
+
* of 1–{@link MAX_NAME_LENGTH} characters, not blank, with no control (C0, DEL, C1), format (zero-width, bidi
|
|
8
|
+
* overrides), surrogate, line/paragraph-separator, private-use or noncharacter code point:
|
|
9
|
+
* - an empty or blank name names nothing;
|
|
10
|
+
* - an overlong one is a value, or a flood of one;
|
|
11
|
+
* - a control or separator character forges a narrative line or a log record, and a bidi override hides what a
|
|
12
|
+
* line says.
|
|
13
|
+
* The refusal names the FIELD, never the value (P4's precedent): a rejected name may be exactly what must not be
|
|
14
|
+
* echoed. A `TypeError`, because a malformed name is the caller's code breaking its contract.
|
|
15
|
+
*/
|
|
16
|
+
/** The longest name an attempt record carries. */
|
|
17
|
+
export const MAX_NAME_LENGTH = 128;
|
|
18
|
+
/**
|
|
19
|
+
* Control, format, surrogate, line/paragraph-separator, private-use and noncharacter code points — none may sit in a
|
|
20
|
+
* name.
|
|
21
|
+
*/
|
|
22
|
+
const FORBIDDEN = /[\p{Cc}\p{Cf}\p{Cs}\p{Zl}\p{Zp}\p{Co}\p{Noncharacter_Code_Point}]/u;
|
|
23
|
+
/** Why `value` is not a name, or `undefined` when it is one. */
|
|
24
|
+
export function attemptNameProblem(value) {
|
|
25
|
+
if (typeof value !== 'string')
|
|
26
|
+
return 'must be a string';
|
|
27
|
+
if (value.trim().length === 0)
|
|
28
|
+
return 'must not be empty or blank';
|
|
29
|
+
if (value.length > MAX_NAME_LENGTH)
|
|
30
|
+
return `must be at most ${MAX_NAME_LENGTH} characters`;
|
|
31
|
+
if (FORBIDDEN.test(value))
|
|
32
|
+
return 'must not contain control, format or line-separator characters';
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
/** `value` as a name, or a `TypeError` that names `where` and `field` (never the value). */
|
|
36
|
+
export function admitAttemptName(where, field, value) {
|
|
37
|
+
const problem = attemptNameProblem(value);
|
|
38
|
+
if (problem !== undefined) {
|
|
39
|
+
throw new TypeError(`${where}: ${field} ${problem} — it is a name from code, never a value`);
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFtZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvYXR0ZW1wdC9uYW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBRUgsa0RBQWtEO0FBQ2xELE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxHQUFHLENBQUM7QUFFbkM7OztHQUdHO0FBQ0gsTUFBTSxTQUFTLEdBQUcsb0VBQW9FLENBQUM7QUFFdkYsZ0VBQWdFO0FBQ2hFLE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxLQUFjO0lBQy9DLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtRQUFFLE9BQU8sa0JBQWtCLENBQUM7SUFDekQsSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLDRCQUE0QixDQUFDO0lBQ25FLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxlQUFlO1FBQUUsT0FBTyxtQkFBbUIsZUFBZSxhQUFhLENBQUM7SUFDM0YsSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sK0RBQStELENBQUM7SUFDbEcsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVELDRGQUE0RjtBQUM1RixNQUFNLFVBQVUsZ0JBQWdCLENBQUMsS0FBYSxFQUFFLEtBQWEsRUFBRSxLQUFjO0lBQzNFLE1BQU0sT0FBTyxHQUFHLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzFDLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzFCLE1BQU0sSUFBSSxTQUFTLENBQUMsR0FBRyxLQUFLLEtBQUssS0FBSyxJQUFJLE9BQU8sMENBQTBDLENBQUMsQ0FBQztJQUMvRixDQUFDO0lBQ0QsT0FBTyxLQUFlLENBQUM7QUFDekIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYXR0ZW1wdC9uYW1lLnRzIOKAlCB0aGUgT05FIHJ1bGUgZm9yIGEgbmFtZSBhbiBhdHRlbXB0IHJlY29yZCBjYXJyaWVzIChkZXNpZ24gwqczLjYsIHRocmVhdCBtb2RlbCwgcGFja2V0IFAyKTogdGhlXG4gKiB0YXJnZXQgb2YgYSBgJGNhbGxgIC8gYGF0dGVtcHQoKWAsIGEgc3RhbmRhbG9uZSBzZXJpZXMsIGFuZCBhbiBvYnNlcnZlZCByZXBvcnQncyB0YXJnZXQgYW5kIHNvdXJjZS5cbiAqXG4gKiBBIHRhcmdldCBpcyBhIE5BTUUgZnJvbSBjb2RlIOKAlCBgJ3N0cmlwZS5xdW90ZXMuY3JlYXRlJ2Ag4oCUIG5ldmVyIGZyb20gYSBtb2RlbCBhbmQgbmV2ZXIgYSB2YWx1ZS4gSXQgcmlkZXMgZXZlcnlcbiAqIHJlY29yZCwgbmFycmF0aXZlIGxpbmUsIHJlY29yZGVyIHJvdyBhbmQgbWV0cmljIGtleSBleGFjdGx5IGFzIGdpdmVuLCBzbyBhIG5hbWUgaXMgcmVmdXNlZCB1bmxlc3MgaXQgaXMgYSBzdHJpbmdcbiAqIG9mIDHigJN7QGxpbmsgTUFYX05BTUVfTEVOR1RIfSBjaGFyYWN0ZXJzLCBub3QgYmxhbmssIHdpdGggbm8gY29udHJvbCAoQzAsIERFTCwgQzEpLCBmb3JtYXQgKHplcm8td2lkdGgsIGJpZGlcbiAqIG92ZXJyaWRlcyksIHN1cnJvZ2F0ZSwgbGluZS9wYXJhZ3JhcGgtc2VwYXJhdG9yLCBwcml2YXRlLXVzZSBvciBub25jaGFyYWN0ZXIgY29kZSBwb2ludDpcbiAqICAgLSBhbiBlbXB0eSBvciBibGFuayBuYW1lIG5hbWVzIG5vdGhpbmc7XG4gKiAgIC0gYW4gb3Zlcmxvbmcgb25lIGlzIGEgdmFsdWUsIG9yIGEgZmxvb2Qgb2Ygb25lO1xuICogICAtIGEgY29udHJvbCBvciBzZXBhcmF0b3IgY2hhcmFjdGVyIGZvcmdlcyBhIG5hcnJhdGl2ZSBsaW5lIG9yIGEgbG9nIHJlY29yZCwgYW5kIGEgYmlkaSBvdmVycmlkZSBoaWRlcyB3aGF0IGFcbiAqICAgICBsaW5lIHNheXMuXG4gKiBUaGUgcmVmdXNhbCBuYW1lcyB0aGUgRklFTEQsIG5ldmVyIHRoZSB2YWx1ZSAoUDQncyBwcmVjZWRlbnQpOiBhIHJlamVjdGVkIG5hbWUgbWF5IGJlIGV4YWN0bHkgd2hhdCBtdXN0IG5vdCBiZVxuICogZWNob2VkLiBBIGBUeXBlRXJyb3JgLCBiZWNhdXNlIGEgbWFsZm9ybWVkIG5hbWUgaXMgdGhlIGNhbGxlcidzIGNvZGUgYnJlYWtpbmcgaXRzIGNvbnRyYWN0LlxuICovXG5cbi8qKiBUaGUgbG9uZ2VzdCBuYW1lIGFuIGF0dGVtcHQgcmVjb3JkIGNhcnJpZXMuICovXG5leHBvcnQgY29uc3QgTUFYX05BTUVfTEVOR1RIID0gMTI4O1xuXG4vKipcbiAqIENvbnRyb2wsIGZvcm1hdCwgc3Vycm9nYXRlLCBsaW5lL3BhcmFncmFwaC1zZXBhcmF0b3IsIHByaXZhdGUtdXNlIGFuZCBub25jaGFyYWN0ZXIgY29kZSBwb2ludHMg4oCUIG5vbmUgbWF5IHNpdCBpbiBhXG4gKiBuYW1lLlxuICovXG5jb25zdCBGT1JCSURERU4gPSAvW1xccHtDY31cXHB7Q2Z9XFxwe0NzfVxccHtabH1cXHB7WnB9XFxwe0NvfVxccHtOb25jaGFyYWN0ZXJfQ29kZV9Qb2ludH1dL3U7XG5cbi8qKiBXaHkgYHZhbHVlYCBpcyBub3QgYSBuYW1lLCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGlzIG9uZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdHRlbXB0TmFtZVByb2JsZW0odmFsdWU6IHVua25vd24pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykgcmV0dXJuICdtdXN0IGJlIGEgc3RyaW5nJztcbiAgaWYgKHZhbHVlLnRyaW0oKS5sZW5ndGggPT09IDApIHJldHVybiAnbXVzdCBub3QgYmUgZW1wdHkgb3IgYmxhbmsnO1xuICBpZiAodmFsdWUubGVuZ3RoID4gTUFYX05BTUVfTEVOR1RIKSByZXR1cm4gYG11c3QgYmUgYXQgbW9zdCAke01BWF9OQU1FX0xFTkdUSH0gY2hhcmFjdGVyc2A7XG4gIGlmIChGT1JCSURERU4udGVzdCh2YWx1ZSkpIHJldHVybiAnbXVzdCBub3QgY29udGFpbiBjb250cm9sLCBmb3JtYXQgb3IgbGluZS1zZXBhcmF0b3IgY2hhcmFjdGVycyc7XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKiBgdmFsdWVgIGFzIGEgbmFtZSwgb3IgYSBgVHlwZUVycm9yYCB0aGF0IG5hbWVzIGB3aGVyZWAgYW5kIGBmaWVsZGAgKG5ldmVyIHRoZSB2YWx1ZSkuICovXG5leHBvcnQgZnVuY3Rpb24gYWRtaXRBdHRlbXB0TmFtZSh3aGVyZTogc3RyaW5nLCBmaWVsZDogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XG4gIGNvbnN0IHByb2JsZW0gPSBhdHRlbXB0TmFtZVByb2JsZW0odmFsdWUpO1xuICBpZiAocHJvYmxlbSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgJHt3aGVyZX06ICR7ZmllbGR9ICR7cHJvYmxlbX0g4oCUIGl0IGlzIGEgbmFtZSBmcm9tIGNvZGUsIG5ldmVyIGEgdmFsdWVgKTtcbiAgfVxuICByZXR1cm4gdmFsdWUgYXMgc3RyaW5nO1xufVxuIl19
|
|
@@ -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,171 @@
|
|
|
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 { errorCategory } from './category.js';
|
|
26
|
+
import { decideAttempt, retryRules } from './decision.js';
|
|
27
|
+
import { admitAttemptName } from './name.js';
|
|
28
|
+
import { freezeDeep, recordedError } from './record.js';
|
|
29
|
+
/** The outcomes a report may state — an SDK cannot pause a flowchart. */
|
|
30
|
+
const OUTCOMES = new Set(['ok', 'failed', 'timeout', 'aborted']);
|
|
31
|
+
const WHERE = 'observed()';
|
|
32
|
+
/**
|
|
33
|
+
* Read an adapter's report: the named fields only, each once. A malformed report is refused with a `TypeError`
|
|
34
|
+
* naming the field (never its value).
|
|
35
|
+
*/
|
|
36
|
+
export function readObservedReport(report) {
|
|
37
|
+
if (report === null || typeof report !== 'object')
|
|
38
|
+
throw new TypeError(`${WHERE}: the report must be an object`);
|
|
39
|
+
const field = (name) => {
|
|
40
|
+
try {
|
|
41
|
+
return report[name];
|
|
42
|
+
}
|
|
43
|
+
catch (cause) {
|
|
44
|
+
throw new TypeError(`${WHERE}: the report's ${name} could not be read`, { cause });
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const target = admitAttemptName(WHERE, 'target', field('target'));
|
|
48
|
+
const rawSource = field('source');
|
|
49
|
+
const source = rawSource === undefined ? 'sdk' : admitAttemptName(WHERE, 'source', rawSource);
|
|
50
|
+
const rawAttempt = field('attempt');
|
|
51
|
+
const attempt = rawAttempt === undefined ? 1 : count('attempt', rawAttempt);
|
|
52
|
+
const rawOf = field('of');
|
|
53
|
+
const of = rawOf === undefined ? undefined : count('of', rawOf);
|
|
54
|
+
if (of !== undefined && of < attempt)
|
|
55
|
+
throw new TypeError(`${WHERE}: of must be at least attempt`);
|
|
56
|
+
const outcome = field('outcome');
|
|
57
|
+
if (typeof outcome !== 'string' || !OUTCOMES.has(outcome)) {
|
|
58
|
+
throw new TypeError(`${WHERE}: outcome must be one of 'ok', 'failed', 'timeout', 'aborted'`);
|
|
59
|
+
}
|
|
60
|
+
const durationMs = field('durationMs');
|
|
61
|
+
if (typeof durationMs !== 'number' || !Number.isFinite(durationMs) || durationMs < 0) {
|
|
62
|
+
throw new TypeError(`${WHERE}: durationMs must be a finite number >= 0`);
|
|
63
|
+
}
|
|
64
|
+
const startedAt = field('startedAt');
|
|
65
|
+
if (startedAt !== undefined && (typeof startedAt !== 'number' || !Number.isFinite(startedAt))) {
|
|
66
|
+
throw new TypeError(`${WHERE}: startedAt must be a finite number (epoch ms)`);
|
|
67
|
+
}
|
|
68
|
+
const error = field('error');
|
|
69
|
+
return {
|
|
70
|
+
target,
|
|
71
|
+
source,
|
|
72
|
+
attempt,
|
|
73
|
+
...(of !== undefined && { of }),
|
|
74
|
+
outcome: outcome,
|
|
75
|
+
durationMs,
|
|
76
|
+
...(startedAt !== undefined && { startedAt: startedAt }),
|
|
77
|
+
...(error !== undefined && { error }),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function count(name, value) {
|
|
81
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 1) {
|
|
82
|
+
throw new TypeError(`${WHERE}: ${name} must be a whole number >= 1`);
|
|
83
|
+
}
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
/** The frozen record of a report, and the served error (with `raw`) the `onAttempt` hook carries. */
|
|
87
|
+
export function observedRecord(report, init) {
|
|
88
|
+
const failed = report.outcome !== 'ok';
|
|
89
|
+
const category = failed ? errorCategory(report.error, report.outcome) : undefined;
|
|
90
|
+
const served = failed && report.error !== undefined ? withoutRaw(init.serve(report.error)) : undefined;
|
|
91
|
+
const decision = decideAttempt(retryRules({ attempts: report.of ?? report.attempt }), (key) => readInput(report, category, key));
|
|
92
|
+
const record = freezeDeep({
|
|
93
|
+
series: init.series,
|
|
94
|
+
kind: 'observed',
|
|
95
|
+
target: report.target,
|
|
96
|
+
source: report.source,
|
|
97
|
+
attempt: report.attempt,
|
|
98
|
+
...(report.of !== undefined && { of: report.of }),
|
|
99
|
+
startedAt: report.startedAt ?? init.now() - report.durationMs,
|
|
100
|
+
durationMs: report.durationMs,
|
|
101
|
+
outcome: report.outcome,
|
|
102
|
+
...(category !== undefined && { category }),
|
|
103
|
+
decision: decision.evidence,
|
|
104
|
+
next: decision.next,
|
|
105
|
+
reason: decision.reason,
|
|
106
|
+
...(served !== undefined && { error: recordedError(served) }),
|
|
107
|
+
});
|
|
108
|
+
return { record, ...(served !== undefined && { structuredError: served }) };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The served error without `raw`: the library never threw an adapter's error, and an SDK error can carry its
|
|
112
|
+
* request (headers, body) — so no hook is handed the value itself, only its served, named fields.
|
|
113
|
+
*/
|
|
114
|
+
function withoutRaw(served) {
|
|
115
|
+
return { ...served, raw: undefined };
|
|
116
|
+
}
|
|
117
|
+
/** The rule table's inputs as the report states them, under the default policy (no deadline, every error retryable). */
|
|
118
|
+
function readInput(report, category, key) {
|
|
119
|
+
switch (key) {
|
|
120
|
+
case 'outcome':
|
|
121
|
+
return report.outcome;
|
|
122
|
+
case 'category':
|
|
123
|
+
return category;
|
|
124
|
+
case 'aborted':
|
|
125
|
+
return report.outcome === 'aborted';
|
|
126
|
+
case 'attempt':
|
|
127
|
+
return report.attempt;
|
|
128
|
+
case 'of':
|
|
129
|
+
return report.of ?? report.attempt;
|
|
130
|
+
case 'timeLeftMs':
|
|
131
|
+
case 'timeLeftAfterWaitMs':
|
|
132
|
+
return Infinity;
|
|
133
|
+
case 'delayMs':
|
|
134
|
+
return 0;
|
|
135
|
+
case 'retryOn':
|
|
136
|
+
return true;
|
|
137
|
+
case 'keyPresent':
|
|
138
|
+
return false;
|
|
139
|
+
default:
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** How many distinct target/source pairs one attempt's book remembers — past it, each report opens its own series. */
|
|
144
|
+
export const MAX_OPEN_OBSERVED_SERIES = 256;
|
|
145
|
+
/**
|
|
146
|
+
* Groups one attempt's observed reports into series. A report continues the open series of its target and source
|
|
147
|
+
* while its attempt number grows; otherwise it opens a new one through `open` (the owner's next call-level series).
|
|
148
|
+
* Bounded: it remembers at most {@link MAX_OPEN_OBSERVED_SERIES} names.
|
|
149
|
+
*/
|
|
150
|
+
export class ObservedSeriesBook {
|
|
151
|
+
openSeries;
|
|
152
|
+
open = new Map();
|
|
153
|
+
constructor(openSeries) {
|
|
154
|
+
this.openSeries = openSeries;
|
|
155
|
+
}
|
|
156
|
+
seriesFor(report) {
|
|
157
|
+
// Names hold no control character, so NUL cannot occur in either: the key is unambiguous.
|
|
158
|
+
const key = `${report.source}\u0000${report.target}`;
|
|
159
|
+
const current = this.open.get(key);
|
|
160
|
+
if (current !== undefined && report.attempt > current.last) {
|
|
161
|
+
current.last = report.attempt;
|
|
162
|
+
return current.series;
|
|
163
|
+
}
|
|
164
|
+
const series = this.openSeries();
|
|
165
|
+
if (current !== undefined || this.open.size < MAX_OPEN_OBSERVED_SERIES) {
|
|
166
|
+
this.open.set(key, { series, last: report.attempt });
|
|
167
|
+
}
|
|
168
|
+
return series;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JzZXJ2ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2F0dGVtcHQvb2JzZXJ2ZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJHO0FBR0gsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDN0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFHeEQseUVBQXlFO0FBQ3pFLE1BQU0sUUFBUSxHQUF3QixJQUFJLEdBQUcsQ0FBaUIsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBRXRHLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQztBQWMzQjs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsTUFBZTtJQUNoRCxJQUFJLE1BQU0sS0FBSyxJQUFJLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUTtRQUFFLE1BQU0sSUFBSSxTQUFTLENBQUMsR0FBRyxLQUFLLGdDQUFnQyxDQUFDLENBQUM7SUFDakgsTUFBTSxLQUFLLEdBQUcsQ0FBQyxJQUFZLEVBQVcsRUFBRTtRQUN0QyxJQUFJLENBQUM7WUFDSCxPQUFRLE1BQWtDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkQsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLElBQUksU0FBUyxDQUFDLEdBQUcsS0FBSyxrQkFBa0IsSUFBSSxvQkFBb0IsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDckYsQ0FBQztJQUNILENBQUMsQ0FBQztJQUNGLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFD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QUFDO1FBQ3ZELENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGF0dGVtcHQvb2JzZXJ2ZWQudHMg4oCUIGFuIGF0dGVtcHQgdGhlIGxpYnJhcnkgZGlkIE5PVCBydW46IGFuIG91dHNpZGUgc3lzdGVtJ3Mgb3duIHJldHJ5IChhbiBTREsncyksIHJlcG9ydGVkIGJ5IGFuXG4gKiBhZGFwdGVyIHRocm91Z2ggYEF0dGVtcHRDb250ZXh0Lm9ic2VydmVkYCAoZGVzaWduIMKnMy42LCBwYWNrZXQgUDIpLiBTYW1lIHJlY29yZCBzaGFwZSwga2luZCBgJ29ic2VydmVkJ2AuXG4gKlxuICogV0hZOiB0aGUgaW5jaWRlbnQgYmVoaW5kIHRoaXMgZGVzaWduIHdhcyBmb3VyIDQwIHMgYXR0ZW1wdHMgaW5zaWRlIGFuIFNESyB0aGF0IHRoZSByZWNvcmQgY2FsbGVkIFwib25lIHN0YWdlLCBvbmVcbiAqIGVycm9yXCIuIFRoZSBiZXN0IGZpeCBpcyBvbmUgbG9vcCDigJQgdGhlIFNESydzIHJldHJpZXMgb2ZmLCB0aGUgY2FsbCB1bmRlciBgc2NvcGUuJGNhbGxgLiBXaGVyZSBhbiBTREsgbXVzdCBrZWVwIGl0c1xuICogcmV0cmllcywgaXRzIGFkYXB0ZXIgcmVwb3J0cyBlYWNoIG9uZSBoZXJlLCBzbyB0aGUgcmVjb3JkIHNheXMgd2hhdCBoYXBwZW5lZCByYXRoZXIgdGhhbiBub3RoaW5nLlxuICpcbiAqIFRIUkVFIExBV1MuXG4gKiAgIC0gQSByZXBvcnQgaXMgcmVhZCwgbmV2ZXIgdHJ1c3RlZC4gT25seSB0aGUgbmFtZWQgZmllbGRzIGFyZSByZWFkLCBlYWNoIE9OQ0UgKGEgZ2V0dGVyIGNhbm5vdCBhbnN3ZXIgdHdpY2UpO1xuICogICAgIGEgbmFtZSBpcyBoZWxkIHRvIHRoZSBvbmUgbmFtZSBydWxlIChgbmFtZS50c2ApOyBudW1iZXJzIG11c3QgYmUgd2hhdCB0aGV5IHNheS4gQW55dGhpbmcgZWxzZSBvbiB0aGVcbiAqICAgICBvYmplY3Qg4oCUIGEgcmVxdWVzdCBib2R5LCBoZWFkZXJzIOKAlCBpcyBuZXZlciByZWFkLCBzbyBpdCBjYW4gbmV2ZXIgcmVhY2ggYSByZWNvcmQgKHtAbGluayByZWFkT2JzZXJ2ZWRSZXBvcnR9KS5cbiAqICAgLSBUaGUgZXJyb3IgaXMgc2VydmVkIHVuZGVyIHRoZSBydW4ncyByZWRhY3Rpb24gcnVsZSAodGhlIG93bmVyJ3MgYHNlcnZlYCksIGxpa2UgZXZlcnkgYXR0ZW1wdCdzIGVycm9yOyB0aGVcbiAqICAgICByZWNvcmQga2VlcHMgaXRzIG5hbWVkIGZpZWxkcywgYW5kIG5vIGhvb2sgaXMgaGFuZGVkIHRoZSBhZGFwdGVyJ3MgZXJyb3Igb2JqZWN0IChgcmF3YCBpcyBkcm9wcGVkOiB0aGVcbiAqICAgICBsaWJyYXJ5IG5ldmVyIHRocmV3IGl0LCBhbmQgYW4gU0RLIGVycm9yIGNhbiBjYXJyeSBpdHMgcmVxdWVzdCkuXG4gKiAgIC0gQW4gb2JzZXJ2ZWQgYXR0ZW1wdCBuZXZlciBjaGFuZ2VzIGNvbnRyb2wgZmxvdy4gSXRzIGBkZWNpc2lvbmAgaXMgdGhlIE9ORSBydWxlIHRhYmxlIHJlYWQgb3ZlciB3aGF0IHRoZVxuICogICAgIHJlcG9ydCBzdGF0ZXMsIHVuZGVyIHRoZSBkZWZhdWx0IHBvbGljeSAoZXZlcnkgZXJyb3IgcmV0cnlhYmxlLCBubyBkZWFkbGluZSkg4oCUIHRoZSBsaWJyYXJ5J3MgcmVhZGluZyBvZiB0aGVcbiAqICAgICBTREsncyBhdHRlbXB0LCBuZXZlciB0aGUgU0RLJ3Mgb3duIGRlY2lzaW9uLCB3aGljaCB0aGUgcmVjb3JkIGNhbm5vdCBrbm93LiBBIHJlcG9ydCB3aXRob3V0IGBvZmAgc3RhbmRzIGZvclxuICogICAgIHRoZSBTREsncyB3aG9sZSBjYWxsOiBpdCBpcyBpdHMgbGFzdCBhdHRlbXB0LCBzbyBhIGZhaWx1cmUgcmVhZHMgYGV4aGF1c3RlZGAuXG4gKlxuICogU0VSSUVTLiBSZXBvcnRzIGFyZSBncm91cGVkIGJ5IHtAbGluayBPYnNlcnZlZFNlcmllc0Jvb2t9LCBvd25lZCBieSB3aG9ldmVyIG93bnMgdGhlIGF0dGVtcHQgdGhleSB3ZXJlIHJlcG9ydGVkXG4gKiBvbjogYSBncm93aW5nIGF0dGVtcHQgbnVtYmVyIGNvbnRpbnVlcyBpdHMgdGFyZ2V0J3Mgc2VyaWVzOyBhIG51bWJlciB0aGF0IGRvZXMgbm90IGdyb3cgb3BlbnMgYSBuZXcgb25lICh0aGVcbiAqIFNESyBzdGFydGVkIGFub3RoZXIgY2FsbCkuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBTdHJ1Y3R1cmVkRXJyb3JJbmZvIH0gZnJvbSAnLi4vZXJyb3JzL2Vycm9ySW5mby5qcyc7XG5pbXBvcnQgeyBlcnJvckNhdGVnb3J5IH0gZnJvbSAnLi9jYXRlZ29yeS5qcyc7XG5pbXBvcnQgeyBkZWNpZGVBdHRlbXB0LCByZXRyeVJ1bGVzIH0gZnJvbSAnLi9kZWNpc2lvbi5qcyc7XG5pbXBvcnQgeyBhZG1pdEF0dGVtcHROYW1lIH0gZnJvbSAnLi9uYW1lLmpzJztcbmltcG9ydCB7IGZyZWV6ZURlZXAsIHJlY29yZGVkRXJyb3IgfSBmcm9tICcuL3JlY29yZC5qcyc7XG5pbXBvcnQgdHlwZSB7IEF0dGVtcHRDYXRlZ29yeSwgQXR0ZW1wdE91dGNvbWUsIEF0dGVtcHRSZWNvcmQgfSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqIFRoZSBvdXRjb21lcyBhIHJlcG9ydCBtYXkgc3RhdGUg4oCUIGFuIFNESyBjYW5ub3QgcGF1c2UgYSBmbG93Y2hhcnQuICovXG5jb25zdCBPVVRDT01FUzogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQ8QXR0ZW1wdE91dGNvbWU+KFsnb2snLCAnZmFpbGVkJywgJ3RpbWVvdXQnLCAnYWJvcnRlZCddKTtcblxuY29uc3QgV0hFUkUgPSAnb2JzZXJ2ZWQoKSc7XG5cbi8qKiBBIHJlcG9ydCBhcyByZWFkOiBldmVyeSBmaWVsZCBvbmNlLCB2YWxpZGF0ZWQsIGRlZmF1bHRzIGFwcGxpZWQuICovXG5leHBvcnQgaW50ZXJmYWNlIE9ic2VydmVkUmVwb3J0IHtcbiAgcmVhZG9ubHkgdGFyZ2V0OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNvdXJjZTogc3RyaW5nO1xuICByZWFkb25seSBhdHRlbXB0OiBudW1iZXI7XG4gIHJlYWRvbmx5IG9mPzogbnVtYmVyO1xuICByZWFkb25seSBvdXRjb21lOiBFeGNsdWRlPEF0dGVtcHRPdXRjb21lLCAncGF1c2VkJz47XG4gIHJlYWRvbmx5IGR1cmF0aW9uTXM6IG51bWJlcjtcbiAgcmVhZG9ubHkgc3RhcnRlZEF0PzogbnVtYmVyO1xuICByZWFkb25seSBlcnJvcj86IHVua25vd247XG59XG5cbi8qKlxuICogUmVhZCBhbiBhZGFwdGVyJ3MgcmVwb3J0OiB0aGUgbmFtZWQgZmllbGRzIG9ubHksIGVhY2ggb25jZS4gQSBtYWxmb3JtZWQgcmVwb3J0IGlzIHJlZnVzZWQgd2l0aCBhIGBUeXBlRXJyb3JgXG4gKiBuYW1pbmcgdGhlIGZpZWxkIChuZXZlciBpdHMgdmFsdWUpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZE9ic2VydmVkUmVwb3J0KHJlcG9ydDogdW5rbm93bik6IE9ic2VydmVkUmVwb3J0IHtcbiAgaWYgKHJlcG9ydCA9PT0gbnVsbCB8fCB0eXBlb2YgcmVwb3J0ICE9PSAnb2JqZWN0JykgdGhyb3cgbmV3IFR5cGVFcnJvcihgJHtXSEVSRX06IHRoZSByZXBvcnQgbXVzdCBiZSBhbiBvYmplY3RgKTtcbiAgY29uc3QgZmllbGQgPSAobmFtZTogc3RyaW5nKTogdW5rbm93biA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiAocmVwb3J0IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtuYW1lXTtcbiAgICB9IGNhdGNoIChjYXVzZSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgJHtXSEVSRX06IHRoZSByZXBvcnQncyAke25hbWV9IGNvdWxkIG5vdCBiZSByZWFkYCwgeyBjYXVzZSB9KTtcbiAgICB9XG4gIH07XG4gIGNvbnN0IHRhcmdldCA9IGFkbWl0QXR0ZW1wdE5hbWUoV0hFUkUsICd0YXJnZXQnLCBmaWVsZCgndGFyZ2V0JykpO1xuICBjb25zdCByYXdTb3VyY2UgPSBmaWVsZCgnc291cmNlJyk7XG4gIGNvbnN0IHNvdXJjZSA9IHJhd1NvdXJjZSA9PT0gdW5kZWZpbmVkID8gJ3NkaycgOiBhZG1pdEF0dGVtcHROYW1lKFdIRVJFLCAnc291cmNlJywgcmF3U291cmNlKTtcbiAgY29uc3QgcmF3QXR0ZW1wdCA9IGZpZWxkKCdhdHRlbXB0Jyk7XG4gIGNvbnN0IGF0dGVtcHQgPSByYXdBdHRlbXB0ID09PSB1bmRlZmluZWQgPyAxIDogY291bnQoJ2F0dGVtcHQnLCByYXdBdHRlbXB0KTtcbiAgY29uc3QgcmF3T2YgPSBmaWVsZCgnb2YnKTtcbiAgY29uc3Qgb2YgPSByYXdPZiA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogY291bnQoJ29mJywgcmF3T2YpO1xuICBpZiAob2YgIT09IHVuZGVmaW5lZCAmJiBvZiA8IGF0dGVtcHQpIHRocm93IG5ldyBUeXBlRXJyb3IoYCR7V0hFUkV9OiBvZiBtdXN0IGJlIGF0IGxlYXN0IGF0dGVtcHRgKTtcbiAgY29uc3Qgb3V0Y29tZSA9IGZpZWxkKCdvdXRjb21lJyk7XG4gIGlmICh0eXBlb2Ygb3V0Y29tZSAhPT0gJ3N0cmluZycgfHwgIU9VVENPTUVTLmhhcyhvdXRjb21lKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYCR7V0hFUkV9OiBvdXRjb21lIG11c3QgYmUgb25lIG9mICdvaycsICdmYWlsZWQnLCAndGltZW91dCcsICdhYm9ydGVkJ2ApO1xuICB9XG4gIGNvbnN0IGR1cmF0aW9uTXMgPSBmaWVsZCgnZHVyYXRpb25NcycpO1xuICBpZiAodHlwZW9mIGR1cmF0aW9uTXMgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNGaW5pdGUoZHVyYXRpb25NcykgfHwgZHVyYXRpb25NcyA8IDApIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGAke1dIRVJFfTogZHVyYXRpb25NcyBtdXN0IGJlIGEgZmluaXRlIG51bWJlciA+PSAwYCk7XG4gIH1cbiAgY29uc3Qgc3RhcnRlZEF0ID0gZmllbGQoJ3N0YXJ0ZWRBdCcpO1xuICBpZiAoc3RhcnRlZEF0ICE9PSB1bmRlZmluZWQgJiYgKHR5cGVvZiBzdGFydGVkQXQgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNGaW5pdGUoc3RhcnRlZEF0KSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGAke1dIRVJFfTogc3RhcnRlZEF0IG11c3QgYmUgYSBmaW5pdGUgbnVtYmVyIChlcG9jaCBtcylgKTtcbiAgfVxuICBjb25zdCBlcnJvciA9IGZpZWxkKCdlcnJvcicpO1xuICByZXR1cm4ge1xuICAgIHRhcmdldCxcbiAgICBzb3VyY2UsXG4gICAgYXR0ZW1wdCxcbiAgICAuLi4ob2YgIT09IHVuZGVmaW5lZCAmJiB7IG9mIH0pLFxuICAgIG91dGNvbWU6IG91dGNvbWUgYXMgT2JzZXJ2ZWRSZXBvcnRbJ291dGNvbWUnXSxcbiAgICBkdXJhdGlvbk1zLFxuICAgIC4uLihzdGFydGVkQXQgIT09IHVuZGVmaW5lZCAmJiB7IHN0YXJ0ZWRBdDogc3RhcnRlZEF0IGFzIG51bWJlciB9KSxcbiAgICAuLi4oZXJyb3IgIT09IHVuZGVmaW5lZCAmJiB7IGVycm9yIH0pLFxuICB9O1xufVxuXG5mdW5jdGlvbiBjb3VudChuYW1lOiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKTogbnVtYmVyIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKHZhbHVlKSB8fCB2YWx1ZSA8IDEpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGAke1dIRVJFfTogJHtuYW1lfSBtdXN0IGJlIGEgd2hvbGUgbnVtYmVyID49IDFgKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKiBXaGF0IHR1cm5zIGEgcmVwb3J0IGludG8gYSByZWNvcmQg4oCUIHRoZSBvd25lcidzIHNlcmllcywgY2xvY2sgYW5kIHNlcnZlZC1lcnJvciBydWxlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBPYnNlcnZlZFJlY29yZEluaXQge1xuICByZWFkb25seSBzZXJpZXM6IHN0cmluZztcbiAgcmVhZG9ubHkgbm93OiAoKSA9PiBudW1iZXI7XG4gIHJlYWRvbmx5IHNlcnZlOiAoZXJyb3I6IHVua25vd24pID0+IFN0cnVjdHVyZWRFcnJvckluZm87XG59XG5cbi8qKiBUaGUgZnJvemVuIHJlY29yZCBvZiBhIHJlcG9ydCwgYW5kIHRoZSBzZXJ2ZWQgZXJyb3IgKHdpdGggYHJhd2ApIHRoZSBgb25BdHRlbXB0YCBob29rIGNhcnJpZXMuICovXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2ZWRSZWNvcmQoXG4gIHJlcG9ydDogT2JzZXJ2ZWRSZXBvcnQsXG4gIGluaXQ6IE9ic2VydmVkUmVjb3JkSW5pdCxcbik6IHsgcmVjb3JkOiBBdHRlbXB0UmVjb3JkOyBzdHJ1Y3R1cmVkRXJyb3I/OiBTdHJ1Y3R1cmVkRXJyb3JJbmZvIH0ge1xuICBjb25zdCBmYWlsZWQgPSByZXBvcnQub3V0Y29tZSAhPT0gJ29rJztcbiAgY29uc3QgY2F0ZWdvcnk6IEF0dGVtcHRDYXRlZ29yeSB8IHVuZGVmaW5lZCA9IGZhaWxlZCA/IGVycm9yQ2F0ZWdvcnkocmVwb3J0LmVycm9yLCByZXBvcnQub3V0Y29tZSkgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHNlcnZlZCA9IGZhaWxlZCAmJiByZXBvcnQuZXJyb3IgIT09IHVuZGVmaW5lZCA/IHdpdGhvdXRSYXcoaW5pdC5zZXJ2ZShyZXBvcnQuZXJyb3IpKSA6IHVuZGVmaW5lZDtcbiAgY29uc3QgZGVjaXNpb24gPSBkZWNpZGVBdHRlbXB0KHJldHJ5UnVsZXMoeyBhdHRlbXB0czogcmVwb3J0Lm9mID8/IHJlcG9ydC5hdHRlbXB0IH0pLCAoa2V5KSA9PlxuICAgIHJlYWRJbnB1dChyZXBvcnQsIGNhdGVnb3J5LCBrZXkpLFxuICApO1xuICBjb25zdCByZWNvcmQgPSBmcmVlemVEZWVwPEF0dGVtcHRSZWNvcmQ+KHtcbiAgICBzZXJpZXM6IGluaXQuc2VyaWVzLFxuICAgIGtpbmQ6ICdvYnNlcnZlZCcsXG4gICAgdGFyZ2V0OiByZXBvcnQudGFyZ2V0LFxuICAgIHNvdXJjZTogcmVwb3J0LnNvdXJjZSxcbiAgICBhdHRlbXB0OiByZXBvcnQuYXR0ZW1wdCxcbiAgICAuLi4ocmVwb3J0Lm9mICE9PSB1bmRlZmluZWQgJiYgeyBvZjogcmVwb3J0Lm9mIH0pLFxuICAgIHN0YXJ0ZWRBdDogcmVwb3J0LnN0YXJ0ZWRBdCA/PyBpbml0Lm5vdygpIC0gcmVwb3J0LmR1cmF0aW9uTXMsXG4gICAgZHVyYXRpb25NczogcmVwb3J0LmR1cmF0aW9uTXMsXG4gICAgb3V0Y29tZTogcmVwb3J0Lm91dGNvbWUsXG4gICAgLi4uKGNhdGVnb3J5ICE9PSB1bmRlZmluZWQgJiYgeyBjYXRlZ29yeSB9KSxcbiAgICBkZWNpc2lvbjogZGVjaXNpb24uZXZpZGVuY2UsXG4gICAgbmV4dDogZGVjaXNpb24ubmV4dCxcbiAgICByZWFzb246IGRlY2lzaW9uLnJlYXNvbixcbiAgICAuLi4oc2VydmVkICE9PSB1bmRlZmluZWQgJiYgeyBlcnJvcjogcmVjb3JkZWRFcnJvcihzZXJ2ZWQpIH0pLFxuICB9KTtcbiAgcmV0dXJuIHsgcmVjb3JkLCAuLi4oc2VydmVkICE9PSB1bmRlZmluZWQgJiYgeyBzdHJ1Y3R1cmVkRXJyb3I6IHNlcnZlZCB9KSB9O1xufVxuXG4vKipcbiAqIFRoZSBzZXJ2ZWQgZXJyb3Igd2l0aG91dCBgcmF3YDogdGhlIGxpYnJhcnkgbmV2ZXIgdGhyZXcgYW4gYWRhcHRlcidzIGVycm9yLCBhbmQgYW4gU0RLIGVycm9yIGNhbiBjYXJyeSBpdHNcbiAqIHJlcXVlc3QgKGhlYWRlcnMsIGJvZHkpIOKAlCBzbyBubyBob29rIGlzIGhhbmRlZCB0aGUgdmFsdWUgaXRzZWxmLCBvbmx5IGl0cyBzZXJ2ZWQsIG5hbWVkIGZpZWxkcy5cbiAqL1xuZnVuY3Rpb24gd2l0aG91dFJhdyhzZXJ2ZWQ6IFN0cnVjdHVyZWRFcnJvckluZm8pOiBTdHJ1Y3R1cmVkRXJyb3JJbmZvIHtcbiAgcmV0dXJuIHsgLi4uc2VydmVkLCByYXc6IHVuZGVmaW5lZCB9O1xufVxuXG4vKiogVGhlIHJ1bGUgdGFibGUncyBpbnB1dHMgYXMgdGhlIHJlcG9ydCBzdGF0ZXMgdGhlbSwgdW5kZXIgdGhlIGRlZmF1bHQgcG9saWN5IChubyBkZWFkbGluZSwgZXZlcnkgZXJyb3IgcmV0cnlhYmxlKS4gKi9cbmZ1bmN0aW9uIHJlYWRJbnB1dChyZXBvcnQ6IE9ic2VydmVkUmVwb3J0LCBjYXRlZ29yeTogQXR0ZW1wdENhdGVnb3J5IHwgdW5kZWZpbmVkLCBrZXk6IHN0cmluZyk6IHVua25vd24ge1xuICBzd2l0Y2ggKGtleSkge1xuICAgIGNhc2UgJ291dGNvbWUnOlxuICAgICAgcmV0dXJuIHJlcG9ydC5vdXRjb21lO1xuICAgIGNhc2UgJ2NhdGVnb3J5JzpcbiAgICAgIHJldHVybiBjYXRlZ29yeTtcbiAgICBjYXNlICdhYm9ydGVkJzpcbiAgICAgIHJldHVybiByZXBvcnQub3V0Y29tZSA9PT0gJ2Fib3J0ZWQnO1xuICAgIGNhc2UgJ2F0dGVtcHQnOlxuICAgICAgcmV0dXJuIHJlcG9ydC5hdHRlbXB0O1xuICAgIGNhc2UgJ29mJzpcbiAgICAgIHJldHVybiByZXBvcnQub2YgPz8gcmVwb3J0LmF0dGVtcHQ7XG4gICAgY2FzZSAndGltZUxlZnRNcyc6XG4gICAgY2FzZSAndGltZUxlZnRBZnRlcldhaXRNcyc6XG4gICAgICByZXR1cm4gSW5maW5pdHk7XG4gICAgY2FzZSAnZGVsYXlNcyc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdyZXRyeU9uJzpcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIGNhc2UgJ2tleVByZXNlbnQnOlxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKiBIb3cgbWFueSBkaXN0aW5jdCB0YXJnZXQvc291cmNlIHBhaXJzIG9uZSBhdHRlbXB0J3MgYm9vayByZW1lbWJlcnMg4oCUIHBhc3QgaXQsIGVhY2ggcmVwb3J0IG9wZW5zIGl0cyBvd24gc2VyaWVzLiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9PUEVOX09CU0VSVkVEX1NFUklFUyA9IDI1NjtcblxuLyoqXG4gKiBHcm91cHMgb25lIGF0dGVtcHQncyBvYnNlcnZlZCByZXBvcnRzIGludG8gc2VyaWVzLiBBIHJlcG9ydCBjb250aW51ZXMgdGhlIG9wZW4gc2VyaWVzIG9mIGl0cyB0YXJnZXQgYW5kIHNvdXJjZVxuICogd2hpbGUgaXRzIGF0dGVtcHQgbnVtYmVyIGdyb3dzOyBvdGhlcndpc2UgaXQgb3BlbnMgYSBuZXcgb25lIHRocm91Z2ggYG9wZW5gICh0aGUgb3duZXIncyBuZXh0IGNhbGwtbGV2ZWwgc2VyaWVzKS5cbiAqIEJvdW5kZWQ6IGl0IHJlbWVtYmVycyBhdCBtb3N0IHtAbGluayBNQVhfT1BFTl9PQlNFUlZFRF9TRVJJRVN9IG5hbWVzLlxuICovXG5leHBvcnQgY2xhc3MgT2JzZXJ2ZWRTZXJpZXNCb29rIHtcbiAgcHJpdmF0ZSByZWFkb25seSBvcGVuID0gbmV3IE1hcDxzdHJpbmcsIHsgc2VyaWVzOiBzdHJpbmc7IGxhc3Q6IG51bWJlciB9PigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgb3BlblNlcmllczogKCkgPT4gc3RyaW5nKSB7fVxuXG4gIHNlcmllc0ZvcihyZXBvcnQ6IFBpY2s8T2JzZXJ2ZWRSZXBvcnQsICd0YXJnZXQnIHwgJ3NvdXJjZScgfCAnYXR0ZW1wdCc+KTogc3RyaW5nIHtcbiAgICAvLyBOYW1lcyBob2xkIG5vIGNvbnRyb2wgY2hhcmFjdGVyLCBzbyBOVUwgY2Fubm90IG9jY3VyIGluIGVpdGhlcjogdGhlIGtleSBpcyB1bmFtYmlndW91cy5cbiAgICBjb25zdCBrZXkgPSBgJHtyZXBvcnQuc291cmNlfVxcdTAwMDAke3JlcG9ydC50YXJnZXR9YDtcbiAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5vcGVuLmdldChrZXkpO1xuICAgIGlmIChjdXJyZW50ICE9PSB1bmRlZmluZWQgJiYgcmVwb3J0LmF0dGVtcHQgPiBjdXJyZW50Lmxhc3QpIHtcbiAgICAgIGN1cnJlbnQubGFzdCA9IHJlcG9ydC5hdHRlbXB0O1xuICAgICAgcmV0dXJuIGN1cnJlbnQuc2VyaWVzO1xuICAgIH1cbiAgICBjb25zdCBzZXJpZXMgPSB0aGlzLm9wZW5TZXJpZXMoKTtcbiAgICBpZiAoY3VycmVudCAhPT0gdW5kZWZpbmVkIHx8IHRoaXMub3Blbi5zaXplIDwgTUFYX09QRU5fT0JTRVJWRURfU0VSSUVTKSB7XG4gICAgICB0aGlzLm9wZW4uc2V0KGtleSwgeyBzZXJpZXMsIGxhc3Q6IHJlcG9ydC5hdHRlbXB0IH0pO1xuICAgIH1cbiAgICByZXR1cm4gc2VyaWVzO1xuICB9XG59XG4iXX0=
|
|
@@ -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;
|