@smthrs/flow 0.0.0-stage → 1.0.0-rc.12
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/CHANGELOG.md +161 -0
- package/LICENSE +21 -0
- package/README.md +212 -2
- package/THIRD_PARTY_NOTICES.md +52 -0
- package/dist/cjs/Action/Action.d.ts +250 -0
- package/dist/cjs/Action/Action.d.ts.map +1 -0
- package/dist/cjs/Action/Action.js +42 -0
- package/dist/cjs/Action/Action.js.map +7 -0
- package/dist/cjs/Action/AttemptTimedOut.d.ts +33 -0
- package/dist/cjs/Action/AttemptTimedOut.d.ts.map +1 -0
- package/dist/cjs/Action/AttemptTimedOut.js +51 -0
- package/dist/cjs/Action/AttemptTimedOut.js.map +7 -0
- package/dist/cjs/Action/BoundaryMode.d.ts +29 -0
- package/dist/cjs/Action/BoundaryMode.d.ts.map +1 -0
- package/dist/cjs/Action/BoundaryMode.js +36 -0
- package/dist/cjs/Action/BoundaryMode.js.map +7 -0
- package/dist/cjs/Action/CacheEnvironment.d.ts +158 -0
- package/dist/cjs/Action/CacheEnvironment.d.ts.map +1 -0
- package/dist/cjs/Action/CacheEnvironment.js +57 -0
- package/dist/cjs/Action/CacheEnvironment.js.map +7 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts +34 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.js +46 -0
- package/dist/cjs/Action/ConcurrentKeylessDispatch.js.map +7 -0
- package/dist/cjs/Action/Context.d.ts +131 -0
- package/dist/cjs/Action/Context.d.ts.map +1 -0
- package/dist/cjs/Action/Context.js +68 -0
- package/dist/cjs/Action/Context.js.map +7 -0
- package/dist/cjs/Action/DuplicateImplementation.d.ts +20 -0
- package/dist/cjs/Action/DuplicateImplementation.d.ts.map +1 -0
- package/dist/cjs/Action/DuplicateImplementation.js +46 -0
- package/dist/cjs/Action/DuplicateImplementation.js.map +7 -0
- package/dist/cjs/Action/FileBoundary.d.ts +59 -0
- package/dist/cjs/Action/FileBoundary.d.ts.map +1 -0
- package/dist/cjs/Action/FileBoundary.js +81 -0
- package/dist/cjs/Action/FileBoundary.js.map +7 -0
- package/dist/cjs/Action/FileInput.d.ts +28 -0
- package/dist/cjs/Action/FileInput.d.ts.map +1 -0
- package/dist/cjs/Action/FileInput.js +42 -0
- package/dist/cjs/Action/FileInput.js.map +7 -0
- package/dist/cjs/Action/Filegroup.d.ts +16 -0
- package/dist/cjs/Action/Filegroup.d.ts.map +1 -0
- package/dist/cjs/Action/Filegroup.js +27 -0
- package/dist/cjs/Action/Filegroup.js.map +7 -0
- package/dist/cjs/Action/Glob.d.ts +8 -0
- package/dist/cjs/Action/Glob.d.ts.map +1 -0
- package/dist/cjs/Action/Glob.js +28 -0
- package/dist/cjs/Action/Glob.js.map +7 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.d.ts +26 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.d.ts.map +1 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.js +45 -0
- package/dist/cjs/Action/ImplementationVersionMismatch.js.map +7 -0
- package/dist/cjs/Action/Implementations.d.ts +114 -0
- package/dist/cjs/Action/Implementations.d.ts.map +1 -0
- package/dist/cjs/Action/Implementations.js +65 -0
- package/dist/cjs/Action/Implementations.js.map +7 -0
- package/dist/cjs/Action/InfraInterrupt.d.ts +26 -0
- package/dist/cjs/Action/InfraInterrupt.d.ts.map +1 -0
- package/dist/cjs/Action/InfraInterrupt.js +46 -0
- package/dist/cjs/Action/InfraInterrupt.js.map +7 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.js +54 -0
- package/dist/cjs/Action/InfraInterruptRetriesExhausted.js.map +7 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js +47 -0
- package/dist/cjs/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +7 -0
- package/dist/cjs/Action/StepIdentity.d.ts +153 -0
- package/dist/cjs/Action/StepIdentity.d.ts.map +1 -0
- package/dist/cjs/Action/StepIdentity.js +75 -0
- package/dist/cjs/Action/StepIdentity.js.map +7 -0
- package/dist/cjs/Action/TreeArtifact.d.ts +8 -0
- package/dist/cjs/Action/TreeArtifact.d.ts.map +1 -0
- package/dist/cjs/Action/TreeArtifact.js +25 -0
- package/dist/cjs/Action/TreeArtifact.js.map +7 -0
- package/dist/cjs/Action/TypeId.d.ts +8 -0
- package/dist/cjs/Action/TypeId.d.ts.map +1 -0
- package/dist/cjs/Action/TypeId.js +25 -0
- package/dist/cjs/Action/TypeId.js.map +7 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts +32 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.js +51 -0
- package/dist/cjs/Action/UncanonicalIdempotencyKey.js.map +7 -0
- package/dist/cjs/Action/idempotencyKey.d.ts +21 -0
- package/dist/cjs/Action/idempotencyKey.d.ts.map +1 -0
- package/dist/cjs/Action/idempotencyKey.js +59 -0
- package/dist/cjs/Action/idempotencyKey.js.map +7 -0
- package/dist/cjs/Action/index.d.ts +29 -0
- package/dist/cjs/Action/index.d.ts.map +1 -0
- package/dist/cjs/Action/index.js +60 -0
- package/dist/cjs/Action/index.js.map +7 -0
- package/dist/cjs/Action/make.d.ts +128 -0
- package/dist/cjs/Action/make.d.ts.map +1 -0
- package/dist/cjs/Action/make.js +387 -0
- package/dist/cjs/Action/make.js.map +7 -0
- package/dist/cjs/Action/raceAll.d.ts +21 -0
- package/dist/cjs/Action/raceAll.d.ts.map +1 -0
- package/dist/cjs/Action/raceAll.js +46 -0
- package/dist/cjs/Action/raceAll.js.map +7 -0
- package/dist/cjs/Action/retry.d.ts +19 -0
- package/dist/cjs/Action/retry.d.ts.map +1 -0
- package/dist/cjs/Action/retry.js +75 -0
- package/dist/cjs/Action/retry.js.map +7 -0
- package/dist/cjs/Deadline.d.ts +110 -0
- package/dist/cjs/Deadline.d.ts.map +1 -0
- package/dist/cjs/Deadline.js +112 -0
- package/dist/cjs/Deadline.js.map +7 -0
- package/dist/cjs/DurableClock.d.ts +60 -0
- package/dist/cjs/DurableClock.d.ts.map +1 -0
- package/dist/cjs/DurableClock.js +107 -0
- package/dist/cjs/DurableClock.js.map +7 -0
- package/dist/cjs/DurableDeferred.d.ts +311 -0
- package/dist/cjs/DurableDeferred.d.ts.map +1 -0
- package/dist/cjs/DurableDeferred.js +322 -0
- package/dist/cjs/DurableDeferred.js.map +7 -0
- package/dist/cjs/DurableQueue.d.ts +160 -0
- package/dist/cjs/DurableQueue.d.ts.map +1 -0
- package/dist/cjs/DurableQueue.js +229 -0
- package/dist/cjs/DurableQueue.js.map +7 -0
- package/dist/cjs/ExternalJob.d.ts +179 -0
- package/dist/cjs/ExternalJob.d.ts.map +1 -0
- package/dist/cjs/ExternalJob.js +339 -0
- package/dist/cjs/ExternalJob.js.map +7 -0
- package/dist/cjs/Fault.d.ts +131 -0
- package/dist/cjs/Fault.d.ts.map +1 -0
- package/dist/cjs/Fault.js +157 -0
- package/dist/cjs/Fault.js.map +7 -0
- package/dist/cjs/Flow/Annotations.d.ts +245 -0
- package/dist/cjs/Flow/Annotations.d.ts.map +1 -0
- package/dist/cjs/Flow/Annotations.js +72 -0
- package/dist/cjs/Flow/Annotations.js.map +7 -0
- package/dist/cjs/Flow/CapabilityCeiling.d.ts +21 -0
- package/dist/cjs/Flow/CapabilityCeiling.d.ts.map +1 -0
- package/dist/cjs/Flow/CapabilityCeiling.js +49 -0
- package/dist/cjs/Flow/CapabilityCeiling.js.map +7 -0
- package/dist/cjs/Flow/DeadlineExceeded.d.ts +33 -0
- package/dist/cjs/Flow/DeadlineExceeded.d.ts.map +1 -0
- package/dist/cjs/Flow/DeadlineExceeded.js +52 -0
- package/dist/cjs/Flow/DeadlineExceeded.js.map +7 -0
- package/dist/cjs/Flow/ExecutionIdRequired.d.ts +25 -0
- package/dist/cjs/Flow/ExecutionIdRequired.d.ts.map +1 -0
- package/dist/cjs/Flow/ExecutionIdRequired.js +46 -0
- package/dist/cjs/Flow/ExecutionIdRequired.js.map +7 -0
- package/dist/cjs/Flow/ExecutionIds.d.ts +80 -0
- package/dist/cjs/Flow/ExecutionIds.d.ts.map +1 -0
- package/dist/cjs/Flow/ExecutionIds.js +66 -0
- package/dist/cjs/Flow/ExecutionIds.js.map +7 -0
- package/dist/cjs/Flow/Flow.d.ts +422 -0
- package/dist/cjs/Flow/Flow.d.ts.map +1 -0
- package/dist/cjs/Flow/Flow.js +17 -0
- package/dist/cjs/Flow/Flow.js.map +7 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.d.ts +35 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.d.ts.map +1 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.js +50 -0
- package/dist/cjs/Flow/MaxRoundsExceeded.js.map +7 -0
- package/dist/cjs/Flow/Outcome.d.ts +162 -0
- package/dist/cjs/Flow/Outcome.d.ts.map +1 -0
- package/dist/cjs/Flow/Outcome.js +80 -0
- package/dist/cjs/Flow/Outcome.js.map +7 -0
- package/dist/cjs/Flow/Result.d.ts +186 -0
- package/dist/cjs/Flow/Result.d.ts.map +1 -0
- package/dist/cjs/Flow/Result.js +159 -0
- package/dist/cjs/Flow/Result.js.map +7 -0
- package/dist/cjs/Flow/Runtime.d.ts +98 -0
- package/dist/cjs/Flow/Runtime.d.ts.map +1 -0
- package/dist/cjs/Flow/Runtime.js +186 -0
- package/dist/cjs/Flow/Runtime.js.map +7 -0
- package/dist/cjs/Flow/TypeId.d.ts +8 -0
- package/dist/cjs/Flow/TypeId.d.ts.map +1 -0
- package/dist/cjs/Flow/TypeId.js +25 -0
- package/dist/cjs/Flow/TypeId.js.map +7 -0
- package/dist/cjs/Flow/index.d.ts +17 -0
- package/dist/cjs/Flow/index.d.ts.map +1 -0
- package/dist/cjs/Flow/index.js +29 -0
- package/dist/cjs/Flow/index.js.map +7 -0
- package/dist/cjs/Flow/internal.d.ts +34 -0
- package/dist/cjs/Flow/internal.d.ts.map +1 -0
- package/dist/cjs/Flow/internal.js +187 -0
- package/dist/cjs/Flow/internal.js.map +7 -0
- package/dist/cjs/Flow/make.d.ts +135 -0
- package/dist/cjs/Flow/make.d.ts.map +1 -0
- package/dist/cjs/Flow/make.js +107 -0
- package/dist/cjs/Flow/make.js.map +7 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts +55 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.js +51 -0
- package/dist/cjs/FlowRuntime/CancelRequestFailed.js.map +7 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js +55 -0
- package/dist/cjs/FlowRuntime/ExecutionIdentityConflict.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts +28 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.js +49 -0
- package/dist/cjs/FlowRuntime/FlowCycleDetected.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js +53 -0
- package/dist/cjs/FlowRuntime/FlowExecutionNotFound.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowInstance.d.ts +115 -0
- package/dist/cjs/FlowRuntime/FlowInstance.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowInstance.js +37 -0
- package/dist/cjs/FlowRuntime/FlowInstance.js.map +7 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.d.ts +204 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.js +37 -0
- package/dist/cjs/FlowRuntime/FlowRuntime.js.map +7 -0
- package/dist/cjs/FlowRuntime/NodeRecord.d.ts +177 -0
- package/dist/cjs/FlowRuntime/NodeRecord.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/NodeRecord.js +17 -0
- package/dist/cjs/FlowRuntime/NodeRecord.js.map +7 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts +69 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.js +53 -0
- package/dist/cjs/FlowRuntime/WaitingAnnotation.js.map +7 -0
- package/dist/cjs/FlowRuntime/index.d.ts +14 -0
- package/dist/cjs/FlowRuntime/index.d.ts.map +1 -0
- package/dist/cjs/FlowRuntime/index.js +26 -0
- package/dist/cjs/FlowRuntime/index.js.map +7 -0
- package/dist/cjs/Graph.d.ts +325 -0
- package/dist/cjs/Graph.d.ts.map +1 -0
- package/dist/cjs/Graph.js +1020 -0
- package/dist/cjs/Graph.js.map +7 -0
- package/dist/cjs/HumanTask.d.ts +442 -0
- package/dist/cjs/HumanTask.d.ts.map +1 -0
- package/dist/cjs/HumanTask.js +413 -0
- package/dist/cjs/HumanTask.js.map +7 -0
- package/dist/cjs/Interpreter.d.ts +223 -0
- package/dist/cjs/Interpreter.d.ts.map +1 -0
- package/dist/cjs/Interpreter.js +908 -0
- package/dist/cjs/Interpreter.js.map +7 -0
- package/dist/cjs/Poll.d.ts +240 -0
- package/dist/cjs/Poll.d.ts.map +1 -0
- package/dist/cjs/Poll.js +154 -0
- package/dist/cjs/Poll.js.map +7 -0
- package/dist/cjs/RetryPolicy.d.ts +273 -0
- package/dist/cjs/RetryPolicy.d.ts.map +1 -0
- package/dist/cjs/RetryPolicy.js +251 -0
- package/dist/cjs/RetryPolicy.js.map +7 -0
- package/dist/cjs/Sleep.d.ts +98 -0
- package/dist/cjs/Sleep.d.ts.map +1 -0
- package/dist/cjs/Sleep.js +141 -0
- package/dist/cjs/Sleep.js.map +7 -0
- package/dist/cjs/Stall.d.ts +173 -0
- package/dist/cjs/Stall.d.ts.map +1 -0
- package/dist/cjs/Stall.js +92 -0
- package/dist/cjs/Stall.js.map +7 -0
- package/dist/cjs/WaitFor.d.ts +109 -0
- package/dist/cjs/WaitFor.d.ts.map +1 -0
- package/dist/cjs/WaitFor.js +117 -0
- package/dist/cjs/WaitFor.js.map +7 -0
- package/dist/cjs/index.d.ts +107 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +69 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/BoundedJson.d.ts +48 -0
- package/dist/cjs/internal/BoundedJson.d.ts.map +1 -0
- package/dist/cjs/internal/BoundedJson.js +96 -0
- package/dist/cjs/internal/BoundedJson.js.map +7 -0
- package/dist/cjs/internal/DeclarationSite.d.ts +135 -0
- package/dist/cjs/internal/DeclarationSite.d.ts.map +1 -0
- package/dist/cjs/internal/DeclarationSite.js +89 -0
- package/dist/cjs/internal/DeclarationSite.js.map +7 -0
- package/dist/cjs/internal/Declarations.d.ts +35 -0
- package/dist/cjs/internal/Declarations.d.ts.map +1 -0
- package/dist/cjs/internal/Declarations.js +50 -0
- package/dist/cjs/internal/Declarations.js.map +7 -0
- package/dist/cjs/internal/ExecutionMiddleware.d.ts +21 -0
- package/dist/cjs/internal/ExecutionMiddleware.d.ts.map +1 -0
- package/dist/cjs/internal/ExecutionMiddleware.js +39 -0
- package/dist/cjs/internal/ExecutionMiddleware.js.map +7 -0
- package/dist/cjs/internal/JsonSchemaSubset.d.ts +133 -0
- package/dist/cjs/internal/JsonSchemaSubset.d.ts.map +1 -0
- package/dist/cjs/internal/JsonSchemaSubset.js +229 -0
- package/dist/cjs/internal/JsonSchemaSubset.js.map +7 -0
- package/dist/cjs/internal/OutcomeMarker.d.ts +18 -0
- package/dist/cjs/internal/OutcomeMarker.d.ts.map +1 -0
- package/dist/cjs/internal/OutcomeMarker.js +27 -0
- package/dist/cjs/internal/OutcomeMarker.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/Action/Action.d.ts +250 -0
- package/dist/esm/Action/Action.d.ts.map +1 -0
- package/dist/esm/Action/Action.js +30 -0
- package/dist/esm/Action/Action.js.map +1 -0
- package/dist/esm/Action/AttemptTimedOut.d.ts +33 -0
- package/dist/esm/Action/AttemptTimedOut.d.ts.map +1 -0
- package/dist/esm/Action/AttemptTimedOut.js +32 -0
- package/dist/esm/Action/AttemptTimedOut.js.map +1 -0
- package/dist/esm/Action/BoundaryMode.d.ts +29 -0
- package/dist/esm/Action/BoundaryMode.d.ts.map +1 -0
- package/dist/esm/Action/BoundaryMode.js +23 -0
- package/dist/esm/Action/BoundaryMode.js.map +1 -0
- package/dist/esm/Action/CacheEnvironment.d.ts +158 -0
- package/dist/esm/Action/CacheEnvironment.d.ts.map +1 -0
- package/dist/esm/Action/CacheEnvironment.js +130 -0
- package/dist/esm/Action/CacheEnvironment.js.map +1 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts +34 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.d.ts.map +1 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.js +33 -0
- package/dist/esm/Action/ConcurrentKeylessDispatch.js.map +1 -0
- package/dist/esm/Action/Context.d.ts +131 -0
- package/dist/esm/Action/Context.d.ts.map +1 -0
- package/dist/esm/Action/Context.js +99 -0
- package/dist/esm/Action/Context.js.map +1 -0
- package/dist/esm/Action/DuplicateImplementation.d.ts +20 -0
- package/dist/esm/Action/DuplicateImplementation.d.ts.map +1 -0
- package/dist/esm/Action/DuplicateImplementation.js +20 -0
- package/dist/esm/Action/DuplicateImplementation.js.map +1 -0
- package/dist/esm/Action/FileBoundary.d.ts +59 -0
- package/dist/esm/Action/FileBoundary.d.ts.map +1 -0
- package/dist/esm/Action/FileBoundary.js +60 -0
- package/dist/esm/Action/FileBoundary.js.map +1 -0
- package/dist/esm/Action/FileInput.d.ts +28 -0
- package/dist/esm/Action/FileInput.d.ts.map +1 -0
- package/dist/esm/Action/FileInput.js +32 -0
- package/dist/esm/Action/FileInput.js.map +1 -0
- package/dist/esm/Action/Filegroup.d.ts +16 -0
- package/dist/esm/Action/Filegroup.d.ts.map +1 -0
- package/dist/esm/Action/Filegroup.js +15 -0
- package/dist/esm/Action/Filegroup.js.map +1 -0
- package/dist/esm/Action/Glob.d.ts +8 -0
- package/dist/esm/Action/Glob.d.ts.map +1 -0
- package/dist/esm/Action/Glob.js +7 -0
- package/dist/esm/Action/Glob.js.map +1 -0
- package/dist/esm/Action/ImplementationVersionMismatch.d.ts +26 -0
- package/dist/esm/Action/ImplementationVersionMismatch.d.ts.map +1 -0
- package/dist/esm/Action/ImplementationVersionMismatch.js +24 -0
- package/dist/esm/Action/ImplementationVersionMismatch.js.map +1 -0
- package/dist/esm/Action/Implementations.d.ts +114 -0
- package/dist/esm/Action/Implementations.d.ts.map +1 -0
- package/dist/esm/Action/Implementations.js +94 -0
- package/dist/esm/Action/Implementations.js.map +1 -0
- package/dist/esm/Action/InfraInterrupt.d.ts +26 -0
- package/dist/esm/Action/InfraInterrupt.d.ts.map +1 -0
- package/dist/esm/Action/InfraInterrupt.js +25 -0
- package/dist/esm/Action/InfraInterrupt.js.map +1 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts +33 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.d.ts.map +1 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.js +32 -0
- package/dist/esm/Action/InfraInterruptRetriesExhausted.js.map +1 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts +26 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.d.ts.map +1 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js +25 -0
- package/dist/esm/Action/IrreversibleRetryRequiresIdempotencyKey.js.map +1 -0
- package/dist/esm/Action/StepIdentity.d.ts +153 -0
- package/dist/esm/Action/StepIdentity.d.ts.map +1 -0
- package/dist/esm/Action/StepIdentity.js +139 -0
- package/dist/esm/Action/StepIdentity.js.map +1 -0
- package/dist/esm/Action/TreeArtifact.d.ts +8 -0
- package/dist/esm/Action/TreeArtifact.d.ts.map +1 -0
- package/dist/esm/Action/TreeArtifact.js +7 -0
- package/dist/esm/Action/TreeArtifact.js.map +1 -0
- package/dist/esm/Action/TypeId.d.ts +8 -0
- package/dist/esm/Action/TypeId.d.ts.map +1 -0
- package/dist/esm/Action/TypeId.js +9 -0
- package/dist/esm/Action/TypeId.js.map +1 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts +32 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.d.ts.map +1 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.js +31 -0
- package/dist/esm/Action/UncanonicalIdempotencyKey.js.map +1 -0
- package/dist/esm/Action/idempotencyKey.d.ts +21 -0
- package/dist/esm/Action/idempotencyKey.d.ts.map +1 -0
- package/dist/esm/Action/idempotencyKey.js +50 -0
- package/dist/esm/Action/idempotencyKey.js.map +1 -0
- package/dist/esm/Action/index.d.ts +29 -0
- package/dist/esm/Action/index.d.ts.map +1 -0
- package/dist/esm/Action/index.js +30 -0
- package/dist/esm/Action/index.js.map +1 -0
- package/dist/esm/Action/make.d.ts +128 -0
- package/dist/esm/Action/make.d.ts.map +1 -0
- package/dist/esm/Action/make.js +413 -0
- package/dist/esm/Action/make.js.map +1 -0
- package/dist/esm/Action/raceAll.d.ts +21 -0
- package/dist/esm/Action/raceAll.d.ts.map +1 -0
- package/dist/esm/Action/raceAll.js +20 -0
- package/dist/esm/Action/raceAll.js.map +1 -0
- package/dist/esm/Action/retry.d.ts +19 -0
- package/dist/esm/Action/retry.d.ts.map +1 -0
- package/dist/esm/Action/retry.js +72 -0
- package/dist/esm/Action/retry.js.map +1 -0
- package/dist/esm/Deadline.d.ts +110 -0
- package/dist/esm/Deadline.d.ts.map +1 -0
- package/dist/esm/Deadline.js +164 -0
- package/dist/esm/Deadline.js.map +1 -0
- package/dist/esm/DurableClock.d.ts +60 -0
- package/dist/esm/DurableClock.d.ts.map +1 -0
- package/dist/esm/DurableClock.js +122 -0
- package/dist/esm/DurableClock.js.map +1 -0
- package/dist/esm/DurableDeferred.d.ts +311 -0
- package/dist/esm/DurableDeferred.d.ts.map +1 -0
- package/dist/esm/DurableDeferred.js +357 -0
- package/dist/esm/DurableDeferred.js.map +1 -0
- package/dist/esm/DurableQueue.d.ts +160 -0
- package/dist/esm/DurableQueue.d.ts.map +1 -0
- package/dist/esm/DurableQueue.js +303 -0
- package/dist/esm/DurableQueue.js.map +1 -0
- package/dist/esm/ExternalJob.d.ts +179 -0
- package/dist/esm/ExternalJob.d.ts.map +1 -0
- package/dist/esm/ExternalJob.js +296 -0
- package/dist/esm/ExternalJob.js.map +1 -0
- package/dist/esm/Fault.d.ts +131 -0
- package/dist/esm/Fault.d.ts.map +1 -0
- package/dist/esm/Fault.js +198 -0
- package/dist/esm/Fault.js.map +1 -0
- package/dist/esm/Flow/Annotations.d.ts +245 -0
- package/dist/esm/Flow/Annotations.d.ts.map +1 -0
- package/dist/esm/Flow/Annotations.js +110 -0
- package/dist/esm/Flow/Annotations.js.map +1 -0
- package/dist/esm/Flow/CapabilityCeiling.d.ts +21 -0
- package/dist/esm/Flow/CapabilityCeiling.d.ts.map +1 -0
- package/dist/esm/Flow/CapabilityCeiling.js +27 -0
- package/dist/esm/Flow/CapabilityCeiling.js.map +1 -0
- package/dist/esm/Flow/DeadlineExceeded.d.ts +33 -0
- package/dist/esm/Flow/DeadlineExceeded.d.ts.map +1 -0
- package/dist/esm/Flow/DeadlineExceeded.js +34 -0
- package/dist/esm/Flow/DeadlineExceeded.js.map +1 -0
- package/dist/esm/Flow/ExecutionIdRequired.d.ts +25 -0
- package/dist/esm/Flow/ExecutionIdRequired.d.ts.map +1 -0
- package/dist/esm/Flow/ExecutionIdRequired.js +30 -0
- package/dist/esm/Flow/ExecutionIdRequired.js.map +1 -0
- package/dist/esm/Flow/ExecutionIds.d.ts +80 -0
- package/dist/esm/Flow/ExecutionIds.d.ts.map +1 -0
- package/dist/esm/Flow/ExecutionIds.js +91 -0
- package/dist/esm/Flow/ExecutionIds.js.map +1 -0
- package/dist/esm/Flow/Flow.d.ts +422 -0
- package/dist/esm/Flow/Flow.d.ts.map +1 -0
- package/dist/esm/Flow/Flow.js +3 -0
- package/dist/esm/Flow/Flow.js.map +1 -0
- package/dist/esm/Flow/MaxRoundsExceeded.d.ts +35 -0
- package/dist/esm/Flow/MaxRoundsExceeded.d.ts.map +1 -0
- package/dist/esm/Flow/MaxRoundsExceeded.js +34 -0
- package/dist/esm/Flow/MaxRoundsExceeded.js.map +1 -0
- package/dist/esm/Flow/Outcome.d.ts +162 -0
- package/dist/esm/Flow/Outcome.d.ts.map +1 -0
- package/dist/esm/Flow/Outcome.js +115 -0
- package/dist/esm/Flow/Outcome.js.map +1 -0
- package/dist/esm/Flow/Result.d.ts +186 -0
- package/dist/esm/Flow/Result.d.ts.map +1 -0
- package/dist/esm/Flow/Result.js +171 -0
- package/dist/esm/Flow/Result.js.map +1 -0
- package/dist/esm/Flow/Runtime.d.ts +98 -0
- package/dist/esm/Flow/Runtime.d.ts.map +1 -0
- package/dist/esm/Flow/Runtime.js +252 -0
- package/dist/esm/Flow/Runtime.js.map +1 -0
- package/dist/esm/Flow/TypeId.d.ts +8 -0
- package/dist/esm/Flow/TypeId.d.ts.map +1 -0
- package/dist/esm/Flow/TypeId.js +9 -0
- package/dist/esm/Flow/TypeId.js.map +1 -0
- package/dist/esm/Flow/index.d.ts +17 -0
- package/dist/esm/Flow/index.d.ts.map +1 -0
- package/dist/esm/Flow/index.js +18 -0
- package/dist/esm/Flow/index.js.map +1 -0
- package/dist/esm/Flow/internal.d.ts +34 -0
- package/dist/esm/Flow/internal.d.ts.map +1 -0
- package/dist/esm/Flow/internal.js +149 -0
- package/dist/esm/Flow/internal.js.map +1 -0
- package/dist/esm/Flow/make.d.ts +135 -0
- package/dist/esm/Flow/make.d.ts.map +1 -0
- package/dist/esm/Flow/make.js +111 -0
- package/dist/esm/Flow/make.js.map +1 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts +55 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.js +53 -0
- package/dist/esm/FlowRuntime/CancelRequestFailed.js.map +1 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts +23 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js +24 -0
- package/dist/esm/FlowRuntime/ExecutionIdentityConflict.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts +28 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.js +35 -0
- package/dist/esm/FlowRuntime/FlowCycleDetected.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts +38 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.js +40 -0
- package/dist/esm/FlowRuntime/FlowExecutionNotFound.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowInstance.d.ts +115 -0
- package/dist/esm/FlowRuntime/FlowInstance.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowInstance.js +24 -0
- package/dist/esm/FlowRuntime/FlowInstance.js.map +1 -0
- package/dist/esm/FlowRuntime/FlowRuntime.d.ts +204 -0
- package/dist/esm/FlowRuntime/FlowRuntime.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/FlowRuntime.js +34 -0
- package/dist/esm/FlowRuntime/FlowRuntime.js.map +1 -0
- package/dist/esm/FlowRuntime/NodeRecord.d.ts +177 -0
- package/dist/esm/FlowRuntime/NodeRecord.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/NodeRecord.js +21 -0
- package/dist/esm/FlowRuntime/NodeRecord.js.map +1 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts +69 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.js +53 -0
- package/dist/esm/FlowRuntime/WaitingAnnotation.js.map +1 -0
- package/dist/esm/FlowRuntime/index.d.ts +14 -0
- package/dist/esm/FlowRuntime/index.d.ts.map +1 -0
- package/dist/esm/FlowRuntime/index.js +15 -0
- package/dist/esm/FlowRuntime/index.js.map +1 -0
- package/dist/esm/Graph.d.ts +325 -0
- package/dist/esm/Graph.d.ts.map +1 -0
- package/dist/esm/Graph.js +1485 -0
- package/dist/esm/Graph.js.map +1 -0
- package/dist/esm/HumanTask.d.ts +442 -0
- package/dist/esm/HumanTask.d.ts.map +1 -0
- package/dist/esm/HumanTask.js +798 -0
- package/dist/esm/HumanTask.js.map +1 -0
- package/dist/esm/Interpreter.d.ts +223 -0
- package/dist/esm/Interpreter.d.ts.map +1 -0
- package/dist/esm/Interpreter.js +1289 -0
- package/dist/esm/Interpreter.js.map +1 -0
- package/dist/esm/Poll.d.ts +240 -0
- package/dist/esm/Poll.d.ts.map +1 -0
- package/dist/esm/Poll.js +289 -0
- package/dist/esm/Poll.js.map +1 -0
- package/dist/esm/RetryPolicy.d.ts +273 -0
- package/dist/esm/RetryPolicy.d.ts.map +1 -0
- package/dist/esm/RetryPolicy.js +429 -0
- package/dist/esm/RetryPolicy.js.map +1 -0
- package/dist/esm/Sleep.d.ts +98 -0
- package/dist/esm/Sleep.d.ts.map +1 -0
- package/dist/esm/Sleep.js +256 -0
- package/dist/esm/Sleep.js.map +1 -0
- package/dist/esm/Stall.d.ts +173 -0
- package/dist/esm/Stall.d.ts.map +1 -0
- package/dist/esm/Stall.js +138 -0
- package/dist/esm/Stall.js.map +1 -0
- package/dist/esm/WaitFor.d.ts +109 -0
- package/dist/esm/WaitFor.d.ts.map +1 -0
- package/dist/esm/WaitFor.js +184 -0
- package/dist/esm/WaitFor.js.map +1 -0
- package/dist/esm/index.d.ts +107 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +108 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/BoundedJson.d.ts +48 -0
- package/dist/esm/internal/BoundedJson.d.ts.map +1 -0
- package/dist/esm/internal/BoundedJson.js +107 -0
- package/dist/esm/internal/BoundedJson.js.map +1 -0
- package/dist/esm/internal/DeclarationSite.d.ts +135 -0
- package/dist/esm/internal/DeclarationSite.d.ts.map +1 -0
- package/dist/esm/internal/DeclarationSite.js +196 -0
- package/dist/esm/internal/DeclarationSite.js.map +1 -0
- package/dist/esm/internal/Declarations.d.ts +35 -0
- package/dist/esm/internal/Declarations.d.ts.map +1 -0
- package/dist/esm/internal/Declarations.js +43 -0
- package/dist/esm/internal/Declarations.js.map +1 -0
- package/dist/esm/internal/ExecutionMiddleware.d.ts +21 -0
- package/dist/esm/internal/ExecutionMiddleware.d.ts.map +1 -0
- package/dist/esm/internal/ExecutionMiddleware.js +13 -0
- package/dist/esm/internal/ExecutionMiddleware.js.map +1 -0
- package/dist/esm/internal/JsonSchemaSubset.d.ts +133 -0
- package/dist/esm/internal/JsonSchemaSubset.d.ts.map +1 -0
- package/dist/esm/internal/JsonSchemaSubset.js +363 -0
- package/dist/esm/internal/JsonSchemaSubset.js.map +1 -0
- package/dist/esm/internal/OutcomeMarker.d.ts +18 -0
- package/dist/esm/internal/OutcomeMarker.d.ts.map +1 -0
- package/dist/esm/internal/OutcomeMarker.js +18 -0
- package/dist/esm/internal/OutcomeMarker.js.map +1 -0
- package/docs/README.md +152 -0
- package/docs/api.md +440 -0
- package/docs/concepts/bodies-and-plans.md +167 -0
- package/docs/concepts/execution-identity.md +142 -0
- package/docs/concepts/flows-and-actions.md +129 -0
- package/docs/concepts/suspension-and-replay.md +130 -0
- package/docs/concepts/the-runtime-port.md +110 -0
- package/docs/concepts/trampoline-rounds.md +151 -0
- package/docs/guides/ask-a-person.md +184 -0
- package/docs/guides/build-a-body.md +164 -0
- package/docs/guides/cancel-and-roll-back.md +112 -0
- package/docs/guides/implement-an-action.md +155 -0
- package/docs/guides/inspect-the-plan.md +235 -0
- package/docs/guides/poll-until-ready.md +169 -0
- package/docs/guides/queue-work-to-a-worker.md +122 -0
- package/docs/guides/retry-a-failing-action.md +243 -0
- package/docs/guides/reuse-a-recorded-result.md +129 -0
- package/docs/guides/run-a-child-flow.md +108 -0
- package/docs/guides/run-an-external-job.md +86 -0
- package/docs/guides/use-a-prompt.md +38 -0
- package/docs/guides/wait-for-a-deadline.md +141 -0
- package/docs/guides/wait-for-an-external-signal.md +151 -0
- package/docs/installation.md +87 -0
- package/docs/quickstart.md +164 -0
- package/docs/reference/flow.md +1835 -0
- package/docs/testing.md +157 -0
- package/docs/troubleshooting.md +286 -0
- package/package.json +327 -3
- package/src/Action/Action.ts +333 -0
- package/src/Action/AttemptTimedOut.ts +37 -0
- package/src/Action/BoundaryMode.ts +33 -0
- package/src/Action/CacheEnvironment.ts +170 -0
- package/src/Action/ConcurrentKeylessDispatch.ts +38 -0
- package/src/Action/Context.ts +156 -0
- package/src/Action/DuplicateImplementation.ts +24 -0
- package/src/Action/FileBoundary.ts +77 -0
- package/src/Action/FileInput.ts +42 -0
- package/src/Action/Filegroup.ts +16 -0
- package/src/Action/Glob.ts +8 -0
- package/src/Action/ImplementationVersionMismatch.ts +27 -0
- package/src/Action/Implementations.ts +149 -0
- package/src/Action/InfraInterrupt.ts +30 -0
- package/src/Action/InfraInterruptRetriesExhausted.ts +37 -0
- package/src/Action/IrreversibleRetryRequiresIdempotencyKey.ts +32 -0
- package/src/Action/StepIdentity.ts +219 -0
- package/src/Action/TreeArtifact.ts +8 -0
- package/src/Action/TypeId.ts +9 -0
- package/src/Action/UncanonicalIdempotencyKey.ts +36 -0
- package/src/Action/idempotencyKey.ts +67 -0
- package/src/Action/index.ts +31 -0
- package/src/Action/make.ts +671 -0
- package/src/Action/raceAll.ts +48 -0
- package/src/Action/retry.ts +92 -0
- package/src/Deadline.ts +201 -0
- package/src/DurableClock.ts +176 -0
- package/src/DurableDeferred.ts +753 -0
- package/src/DurableQueue.ts +519 -0
- package/src/ExternalJob.ts +437 -0
- package/src/Fault.ts +279 -0
- package/src/Flow/Annotations.ts +151 -0
- package/src/Flow/CapabilityCeiling.ts +37 -0
- package/src/Flow/DeadlineExceeded.ts +40 -0
- package/src/Flow/ExecutionIdRequired.ts +36 -0
- package/src/Flow/ExecutionIds.ts +133 -0
- package/src/Flow/Flow.ts +576 -0
- package/src/Flow/MaxRoundsExceeded.ts +39 -0
- package/src/Flow/Outcome.ts +179 -0
- package/src/Flow/Result.ts +284 -0
- package/src/Flow/Runtime.ts +339 -0
- package/src/Flow/TypeId.ts +9 -0
- package/src/Flow/index.ts +19 -0
- package/src/Flow/internal.ts +237 -0
- package/src/Flow/make.ts +285 -0
- package/src/FlowRuntime/CancelRequestFailed.ts +56 -0
- package/src/FlowRuntime/ExecutionIdentityConflict.ts +32 -0
- package/src/FlowRuntime/FlowCycleDetected.ts +41 -0
- package/src/FlowRuntime/FlowExecutionNotFound.ts +46 -0
- package/src/FlowRuntime/FlowInstance.ts +128 -0
- package/src/FlowRuntime/FlowRuntime.ts +339 -0
- package/src/FlowRuntime/NodeRecord.ts +185 -0
- package/src/FlowRuntime/WaitingAnnotation.ts +85 -0
- package/src/FlowRuntime/index.ts +17 -0
- package/src/Graph.ts +1865 -0
- package/src/HumanTask.ts +1007 -0
- package/src/Interpreter.ts +1620 -0
- package/src/Poll.ts +420 -0
- package/src/RetryPolicy.ts +550 -0
- package/src/Sleep.ts +296 -0
- package/src/Stall.ts +217 -0
- package/src/WaitFor.ts +228 -0
- package/src/index.ts +125 -0
- package/src/internal/BoundedJson.ts +109 -0
- package/src/internal/DeclarationSite.ts +214 -0
- package/src/internal/Declarations.ts +49 -0
- package/src/internal/ExecutionMiddleware.ts +29 -0
- package/src/internal/JsonSchemaSubset.ts +392 -0
- package/src/internal/OutcomeMarker.ts +19 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Cancel a run and undo its effects"
|
|
3
|
+
description: "Request cancellation of an execution, register a rollback for a successful effect, add a finalizer to the flow scope, and know which undo belongs to the engine."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 9
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Stopping a durable run and undoing what it already did are two separate jobs.
|
|
9
|
+
This package gives you a request for the first and three mechanisms for the
|
|
10
|
+
second, and each of the three covers a different kind of work.
|
|
11
|
+
|
|
12
|
+
## Request cancellation
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
// `Checkout` is a flow declaration; the id names one of its executions.
|
|
16
|
+
const stop = Checkout.interrupt("checkout-42")
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`interrupt` is not a pause. The engine interrupts active work while preserving
|
|
20
|
+
its normal cleanup, compensation, and child-flow semantics, and calling `resume`
|
|
21
|
+
afterwards does not undo the cancellation request.
|
|
22
|
+
|
|
23
|
+
A durable engine records the request **before** it interrupts anything, and
|
|
24
|
+
reports `FlowRuntime.CancelRequestFailed` when that record could not be written.
|
|
25
|
+
The execution is then still running, so the caller sees the storage failure
|
|
26
|
+
instead of a false success. An in-memory engine has nothing to record and never
|
|
27
|
+
raises it.
|
|
28
|
+
|
|
29
|
+
The same failure carries `unsafe_interrupt_unsupported` when a durable engine is
|
|
30
|
+
asked for `interruptUnsafe`, which it does not implement.
|
|
31
|
+
|
|
32
|
+
## Undo a successful effect
|
|
33
|
+
|
|
34
|
+
`Flow.withRollback` registers how to undo an effect's successful result if the
|
|
35
|
+
current round later exits unsuccessfully:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Flow } from "@smthrs/flow"
|
|
39
|
+
|
|
40
|
+
const reserved = Flow.withRollback(
|
|
41
|
+
reserveInventory(order),
|
|
42
|
+
(reservation, cause) => releaseInventory(reservation, cause)
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The three cases are worth stating exactly:
|
|
47
|
+
|
|
48
|
+
- If the effect itself fails, no rollback is registered. There is nothing to undo.
|
|
49
|
+
- If both the effect and the round succeed, the rollback is discarded.
|
|
50
|
+
- If the effect succeeds and the round exits unsuccessfully, the rollback
|
|
51
|
+
receives the effect's successful value and the round's failure cause when
|
|
52
|
+
the scope closes.
|
|
53
|
+
|
|
54
|
+
A handoff completes the round successfully and discards its `withRollback` registrations.
|
|
55
|
+
Failure or cancellation in a later round cannot invoke those rollbacks. The
|
|
56
|
+
engine does not provide lineage-scoped compensation; compensation across rounds
|
|
57
|
+
requires an explicit durable design. These in-memory finalizers are not durable
|
|
58
|
+
compensation records.
|
|
59
|
+
|
|
60
|
+
This applies only to effects run directly inside the flow execution. It does
|
|
61
|
+
**not** attach rollback behavior to nested actions. An action that changes the
|
|
62
|
+
world undoes itself through its tier, which is the next section.
|
|
63
|
+
|
|
64
|
+
`flow.withRollback` is the same function reachable off a flow declaration, typed
|
|
65
|
+
with that flow's error channel.
|
|
66
|
+
|
|
67
|
+
## Clean up on exit
|
|
68
|
+
|
|
69
|
+
`Flow.addFinalizer` registers an exit finalizer on the flow scope, preserving the
|
|
70
|
+
services available where it was registered:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import * as Effect from "effect/Effect"
|
|
74
|
+
|
|
75
|
+
const withCleanup = Effect.gen(function*() {
|
|
76
|
+
const handle = yield* openHandle()
|
|
77
|
+
yield* Flow.addFinalizer(() => closeHandle(handle))
|
|
78
|
+
return handle
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Suspension keeps the current round's scope open for a re-drive of the same
|
|
83
|
+
instance. Terminal completion closes it with the round's success or failure
|
|
84
|
+
exit. Handoff closes it with a success exit and runs its finalizers; the next
|
|
85
|
+
round has a fresh scope. `Flow.scope` and `Flow.provideScope` refer to this
|
|
86
|
+
round's scope. Its resources and finalizers do not survive process death.
|
|
87
|
+
|
|
88
|
+
## Let the engine undo the work
|
|
89
|
+
|
|
90
|
+
An action whose body changes the workspace declares `tier: "compensable"`. The
|
|
91
|
+
engine then takes a pre-image before each attempt and restores it before the
|
|
92
|
+
next one, so an action that failed halfway through leaves nothing behind for
|
|
93
|
+
attempt two to trip over. The undo is the engine's rather than the body's, and
|
|
94
|
+
it needs a `FlowEngine.SnapshotBoundary` in context, which
|
|
95
|
+
[`@smthrs/engine-store`](/api/engine-store) supplies.
|
|
96
|
+
|
|
97
|
+
Choosing between the three:
|
|
98
|
+
|
|
99
|
+
| The work | The undo |
|
|
100
|
+
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
|
|
101
|
+
| An action that writes to the workspace | `tier: "compensable"`. The engine snapshots and restores. |
|
|
102
|
+
| An action that changes the world outside the workspace | `tier: "irreversible"` plus an `idempotencyKey`. There is no undo, so the engine refuses to retry blind. |
|
|
103
|
+
| An effect inside a handler | `Flow.withRollback`, or `Flow.addFinalizer` when the cleanup is unconditional. |
|
|
104
|
+
|
|
105
|
+
## Related pages
|
|
106
|
+
|
|
107
|
+
- [Attach an implementation to an action](./implement-an-action.md): choosing a
|
|
108
|
+
tier.
|
|
109
|
+
- [Run a flow as a child execution](./run-a-child-flow.md): how cancellation
|
|
110
|
+
travels down a lineage.
|
|
111
|
+
- [Suspension and replay](../concepts/suspension-and-replay.md): scope lifetime
|
|
112
|
+
across suspension, completion, and handoff.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Attach an implementation to an action"
|
|
3
|
+
description: "Declare an action, write its implementation with toLayer, choose its tier, and compose the layers in the order the implementation table requires."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 1
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
An action declaration holds no code. This guide attaches the code, picks the tier
|
|
9
|
+
that describes what the code does to the world, and composes the layers in the
|
|
10
|
+
one order that works.
|
|
11
|
+
|
|
12
|
+
## Declare the action
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { Action } from "@smthrs/flow"
|
|
16
|
+
import * as Schema from "effect/Schema"
|
|
17
|
+
|
|
18
|
+
export class ChargeDeclined extends Schema.TaggedError<ChargeDeclined>()(
|
|
19
|
+
"payments/ChargeDeclined",
|
|
20
|
+
{ reason: Schema.String }
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
export const Charge = Action.make("payments/Charge", {
|
|
24
|
+
payload: { customer: Schema.String, cents: Schema.Number },
|
|
25
|
+
success: Schema.String,
|
|
26
|
+
error: ChargeDeclined,
|
|
27
|
+
tier: "irreversible",
|
|
28
|
+
idempotencyKey: { charge: "checkout-v1" }
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The declared options are `payload`, `success`, `error`, `tier`,
|
|
33
|
+
`idempotencyKey`, `nondeterministic`, and `annotations`. `success` defaults to
|
|
34
|
+
`Schema.Void` and `error` to `Schema.Never`, so an action that declares no error
|
|
35
|
+
schema cannot fail typed.
|
|
36
|
+
|
|
37
|
+
## Write the implementation
|
|
38
|
+
|
|
39
|
+
`toLayer` takes a function from the decoded payload to an effect and returns the
|
|
40
|
+
layer that provides this declaration's requirement:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import * as Effect from "effect/Effect"
|
|
44
|
+
|
|
45
|
+
export const charges = Charge.toLayer(({ cents, customer }) =>
|
|
46
|
+
Effect.gen(function*() {
|
|
47
|
+
const attempt = yield* Action.CurrentAttempt
|
|
48
|
+
const result = yield* chargeCard(customer, cents, { attempt })
|
|
49
|
+
return result.confirmation
|
|
50
|
+
})
|
|
51
|
+
)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Inside the implementation you can read three references the runtime supplies:
|
|
55
|
+
|
|
56
|
+
| Reference | What it carries |
|
|
57
|
+
| ----------------------------- | ------------------------------------------------------------------------------ |
|
|
58
|
+
| `Action.CurrentAttempt` | The one-based durable attempt. Defaults to `1`. |
|
|
59
|
+
| `Action.CurrentInvocationKey` | The persisted key of the dispatch, when the runtime supplies one. |
|
|
60
|
+
| `Action.CurrentOrdinal` | The `OrdinalSlot` of the enclosing `Action.retry` sequence, when there is one. |
|
|
61
|
+
|
|
62
|
+
The implementation may also require services of its own. Those requirements
|
|
63
|
+
appear on the returned layer, so a composition that forgot a database client
|
|
64
|
+
fails to compile the same way a missing action implementation does.
|
|
65
|
+
|
|
66
|
+
## Choose the tier
|
|
67
|
+
|
|
68
|
+
The tier tells the engine what retrying this action means. It is part of the step
|
|
69
|
+
key, so it is not a hint.
|
|
70
|
+
|
|
71
|
+
| Tier | Choose it when | What the engine does |
|
|
72
|
+
| -------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
73
|
+
| `sealed` | The result is a pure function of the declared inputs. | Records the result and replays it. With the right declarations, reuses it across runs. |
|
|
74
|
+
| `compensable` | The body changes the workspace. | Takes a pre-image before each attempt and restores it before the next one, so attempt two does not trip over attempt one's half-written files. Requires a `FlowEngine.SnapshotBoundary` in context, which [`@smthrs/engine-store`](/api/engine-store) supplies, and a workspace that is a jj repository. |
|
|
75
|
+
| `irreversible` | The body changes the world outside the workspace. | Refuses to retry without a declared `idempotencyKey`, dying with `IrreversibleRetryRequiresIdempotencyKey`. |
|
|
76
|
+
|
|
77
|
+
The `compensable` pre-image is a jj snapshot of the workspace, so the
|
|
78
|
+
workspace must be a jj repository: run `jj git init` in it first. Without one,
|
|
79
|
+
the step dies before its first attempt runs:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
@smthrs/jj/JjError: jj snapshot: Error: There is no jj repo in "."
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`sealed` is the default, and it is a claim about the body: this result is worth
|
|
86
|
+
replaying. Add `nondeterministic: true` when several legitimate results may race
|
|
87
|
+
under one cache key, so a conflict is resolved first-writer-wins instead of being
|
|
88
|
+
reported as a hermeticity violation. The flag is key material, so a tolerant
|
|
89
|
+
declaration never consumes a strict declaration's recorded row.
|
|
90
|
+
|
|
91
|
+
## Compose the layers
|
|
92
|
+
|
|
93
|
+
Three rules, in the order they bite:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { FlowEngine } from "@smthrs/engine"
|
|
97
|
+
import { Interpreter } from "@smthrs/flow"
|
|
98
|
+
import * as Layer from "effect/Layer"
|
|
99
|
+
|
|
100
|
+
export const layer = Layer.mergeAll(
|
|
101
|
+
charges,
|
|
102
|
+
Interpreter.layer(Checkout)
|
|
103
|
+
).pipe(
|
|
104
|
+
Layer.provideMerge(Action.layerImplementations),
|
|
105
|
+
Layer.provideMerge(FlowEngine.layerMemory)
|
|
106
|
+
)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
1. Merge the implementation layers beside `Interpreter.layer(flow)`. The
|
|
110
|
+
interpreter registers the flow and installs the handler that drives its body.
|
|
111
|
+
2. Provide `Action.layerImplementations` **under** them with
|
|
112
|
+
`Layer.provideMerge`, never beside them. An implementation files itself in the
|
|
113
|
+
table while its own layer is built, so the table has to be built first.
|
|
114
|
+
3. Provide the engine under that. Every declaration above it is engine agnostic.
|
|
115
|
+
|
|
116
|
+
A second, different implementation of one tag dies during layer construction
|
|
117
|
+
with `Action.DuplicateImplementation`. To substitute one on purpose, register it
|
|
118
|
+
with `action.toLayer(handler, { override: true })`. The override shadows the
|
|
119
|
+
earlier registration, and closing its scope restores what it shadowed. That is
|
|
120
|
+
what lets a test scope an override to one block without leaking it into the
|
|
121
|
+
next.
|
|
122
|
+
|
|
123
|
+
## Skip the layer for a nested operation
|
|
124
|
+
|
|
125
|
+
Not every durable step needs a declaration. Inside an implementation, the inline
|
|
126
|
+
form of `Action.make` is itself an `Effect`, and the engine records it as a step
|
|
127
|
+
of its own:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import { RetryPolicy } from "@smthrs/flow"
|
|
131
|
+
|
|
132
|
+
const settle = Action.make({
|
|
133
|
+
name: "payments/Settle",
|
|
134
|
+
success: Schema.String,
|
|
135
|
+
error: Schema.String,
|
|
136
|
+
tier: "irreversible",
|
|
137
|
+
idempotencyKey: "settle:checkout-v1",
|
|
138
|
+
retryPolicy: RetryPolicy.make({ initialMs: 200, factor: 2, maxMs: 10_000, maxAttempts: 5 }),
|
|
139
|
+
execute: Effect.succeed("settled")
|
|
140
|
+
})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Both forms take `retryPolicy` and `interruptRetryPolicy`; only the inline form
|
|
144
|
+
takes `metadata`. The [`Action.make` reference](../reference/flow.md#actionmake)
|
|
145
|
+
is the one option table. Reach for the inline form when an implementation needs
|
|
146
|
+
a nested durable operation of its own; reach for the declared form when a body
|
|
147
|
+
should name the step.
|
|
148
|
+
|
|
149
|
+
## Related pages
|
|
150
|
+
|
|
151
|
+
- [Flows and actions](../concepts/flows-and-actions.md): why the split exists.
|
|
152
|
+
- [Retry a failing action](./retry-a-failing-action.md): what a policy does, and
|
|
153
|
+
where a policy can be declared.
|
|
154
|
+
- [Reuse a recorded result](./reuse-a-recorded-result.md): the three declarations
|
|
155
|
+
a sealed result needs before it can be shared.
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Inspect the plan a body builds"
|
|
3
|
+
description: "Build a flow's graph without running it, read its nodes, edges, and diagnostics, and drive one interpretation to see what settled, failed, or was skipped."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 11
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Building a plan is a pure function of the declarations and the payload, so you
|
|
9
|
+
can look at the whole shape of a round before its first step runs. That is the
|
|
10
|
+
tool to reach for when a step key changed unexpectedly, when a branch took the
|
|
11
|
+
arm you did not expect, or when you want to show an operator what a run is about
|
|
12
|
+
to do.
|
|
13
|
+
|
|
14
|
+
## Before you start
|
|
15
|
+
|
|
16
|
+
The examples run with `node <file>.ts` on Node.js 26.4.0 or later and need no
|
|
17
|
+
engine, database, or jj: planning reads declarations only. They import
|
|
18
|
+
`@smthrs/flow` and `@smthrs/plan`. In a project that installed `@smthrs/flows`,
|
|
19
|
+
add both at the version of `@smthrs/flows` you have:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @smthrs/flow@1.0.0-rc.12 @smthrs/plan@1.0.0-rc.12
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`@smthrs/flows` re-exports the same modules, so `import { Graph } from "@smthrs/flows"`
|
|
26
|
+
and its `Plan.Node` work too. The outputs below are real output from 1.0.0-rc.6.
|
|
27
|
+
|
|
28
|
+
## Build the graph
|
|
29
|
+
|
|
30
|
+
Create `inspect.ts`. The flow runs two checks in parallel, joins them into a
|
|
31
|
+
report, and then ships or explains:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { Action, Flow, Graph } from "@smthrs/flow"
|
|
35
|
+
import { Node } from "@smthrs/plan"
|
|
36
|
+
import * as Schema from "effect/Schema"
|
|
37
|
+
|
|
38
|
+
const Lint = Action.make("release/Lint", { payload: { target: Schema.String }, success: Schema.String })
|
|
39
|
+
const Types = Action.make("release/Types", { payload: { target: Schema.String }, success: Schema.String })
|
|
40
|
+
const Report = Action.make("release/Report", {
|
|
41
|
+
payload: { lint: Schema.String, types: Schema.String },
|
|
42
|
+
success: Schema.String
|
|
43
|
+
})
|
|
44
|
+
const Ship = Action.make("release/Ship", { payload: { report: Schema.String }, success: Schema.String })
|
|
45
|
+
const Explain = Action.make("release/Explain", { payload: { reason: Schema.String }, success: Schema.String })
|
|
46
|
+
|
|
47
|
+
const Release = Flow.make("release/Release", {
|
|
48
|
+
payload: { target: Schema.String },
|
|
49
|
+
success: Schema.String,
|
|
50
|
+
body: ({ target }) =>
|
|
51
|
+
Node.all({ lint: Lint.call({ target }), types: Types.call({ target }) }).pipe(
|
|
52
|
+
Node.bindPlanned((checks) => Report.call({ lint: checks.lint, types: checks.types })),
|
|
53
|
+
Node.branch({
|
|
54
|
+
if: (report) => report.includes("clean"),
|
|
55
|
+
then: (report) => Ship.call({ report }),
|
|
56
|
+
else: (reason) => Explain.call({ reason })
|
|
57
|
+
})
|
|
58
|
+
)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const graph = Graph.build(Release, { target: "web" })
|
|
62
|
+
|
|
63
|
+
for (const node of Graph.nodes(graph)) {
|
|
64
|
+
console.log(`${node.id} ${node.kind} [${node.dependencies.join(", ")}]`)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const edge of Graph.edges(graph)) {
|
|
68
|
+
console.log(`${edge.from} -> ${edge.to} (${edge.reason})`)
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
node inspect.ts
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
root.flow.branch.andThen.all.lint ActionCall []
|
|
78
|
+
root.flow.branch.andThen.all.types ActionCall []
|
|
79
|
+
root.flow.branch.andThen All [root.flow.branch.andThen.all.lint, root.flow.branch.andThen.all.types]
|
|
80
|
+
root.flow.branch.then ActionCall [root.flow.branch.andThen]
|
|
81
|
+
root.flow.branch AndThen [root.flow.branch.andThen, root.flow.branch.then]
|
|
82
|
+
root.flow.then ActionCall [root.flow.branch]
|
|
83
|
+
root.flow.else ActionCall [root.flow.branch]
|
|
84
|
+
root.flow Branch [root.flow.branch, root.flow.then, root.flow.else]
|
|
85
|
+
root FlowCall [root.flow]
|
|
86
|
+
root.flow.branch.andThen.all.lint -> root.flow.branch.andThen (value)
|
|
87
|
+
root.flow.branch.andThen.all.types -> root.flow.branch.andThen (value)
|
|
88
|
+
root.flow.branch.andThen -> root.flow.branch (value)
|
|
89
|
+
root.flow.branch.andThen -> root.flow.branch.then (continuation)
|
|
90
|
+
root.flow.branch.then -> root.flow.branch (value)
|
|
91
|
+
root.flow.branch -> root.flow (value)
|
|
92
|
+
root.flow.branch -> root.flow.then (continuation)
|
|
93
|
+
root.flow.then -> root.flow (value)
|
|
94
|
+
root.flow.branch -> root.flow.else (continuation)
|
|
95
|
+
root.flow.else -> root.flow (value)
|
|
96
|
+
root.flow -> root (value)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`Graph.build` takes a flow declaration or a bare node, the payload, and options.
|
|
100
|
+
Nothing runs. It refuses a nesting depth past its bound and a duplicate node id,
|
|
101
|
+
because a node id is durable dispatch identity and two nodes answering to one
|
|
102
|
+
address would let a later settlement overwrite an earlier one.
|
|
103
|
+
|
|
104
|
+
## What a node carries
|
|
105
|
+
|
|
106
|
+
| Field | What it holds |
|
|
107
|
+
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| `id` | The structural address, which is what the durable step key is derived from. |
|
|
109
|
+
| `kind` | The authoring variant it came from, not the plan's node kind. Every draft a graph produces is a plan `step`. |
|
|
110
|
+
| `dependencies` | The ids this node consumes. |
|
|
111
|
+
| `capabilities`, `placement` | The declarations lowered onto it. |
|
|
112
|
+
| `draft` | The `Plan.NodeDraft` the plan is compiled from. |
|
|
113
|
+
| `ast` | The authoring node it was observed at, so a driver can reach the real mapper, predicate, and member names. |
|
|
114
|
+
| `payload` | What the node passes on, hydrated: real data where the author wrote data, and a planned placeholder where a step result goes. |
|
|
115
|
+
|
|
116
|
+
Nodes come back with children before the parents that consume them. An `Edge`
|
|
117
|
+
points from the node that produces to the node that consumes, and its `reason` is
|
|
118
|
+
`value` for a consumed result, `continuation` for the sequencing edge a builder
|
|
119
|
+
or branch arm records, or `failure` for a recovery arm.
|
|
120
|
+
|
|
121
|
+
## Read the diagnostics
|
|
122
|
+
|
|
123
|
+
`Graph.inspect(flow)` exports JSON-safe nodes, edges, steps, diagnostics and,
|
|
124
|
+
for prompt declarations, the renderer's source. It supplies an unresolved
|
|
125
|
+
`Planned` input and uses the same graph builder. It never runs an action or
|
|
126
|
+
renders a prompt. Repository declarations must still be inspected in their
|
|
127
|
+
guest, because building a graph calls their plan-time bodies.
|
|
128
|
+
|
|
129
|
+
Inspect `diagnostics` before interpreting the steps. A body that computes on its
|
|
130
|
+
input can require a real payload; inspection reports `declaration_requires_input`
|
|
131
|
+
and shows the declaration as one opaque flow boundary, without declaring it
|
|
132
|
+
unloadable or borrowing another version’s steps. Use `Graph.build(flow, payload)` to plan
|
|
133
|
+
that invocation. Symbolic inputs have the same restrictions as planned step
|
|
134
|
+
results: use node combinators for branching, not JavaScript truthiness or
|
|
135
|
+
reference comparisons. Prompt source is code for inspection, not a rendered
|
|
136
|
+
prompt or an executable browser artifact.
|
|
137
|
+
|
|
138
|
+
`Graph.diagnostics(graph)` holds the recoverable topology issues, such as a
|
|
139
|
+
missing continuation builder or a continuation that produced no node. Fatal
|
|
140
|
+
refusals, including computing on a planned value and a recursive inline `call`,
|
|
141
|
+
throw from `Graph.build` and never appear here.
|
|
142
|
+
|
|
143
|
+
A graph carrying diagnostics is inspectable but deliberately not compilable, so
|
|
144
|
+
`Graph.drafts(graph)` throws the first typed build refusal rather than returning
|
|
145
|
+
partial drafts. Check diagnostics before asking for drafts:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const issues = Graph.diagnostics(graph)
|
|
149
|
+
if (issues.length === 0) {
|
|
150
|
+
const drafts = Graph.drafts(graph) // ready for Plan.compile or Plan.append
|
|
151
|
+
console.log(`${drafts.length} drafts`)
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Appended to `inspect.ts`, it prints `9 drafts`: one per node above.
|
|
156
|
+
[Diff two plans](../../../plan/docs/guides/diff-two-plans.md) compiles drafts like
|
|
157
|
+
these and compares two versions of a flow.
|
|
158
|
+
|
|
159
|
+
## Resolve layers while building
|
|
160
|
+
|
|
161
|
+
`BuildOptions.resolveLayers` is invoked once per node and is told a
|
|
162
|
+
`LayerRequest`: the node id, its authoring kind, its capabilities, its declared
|
|
163
|
+
effects, and its placement. It answers the identity of the implementation the
|
|
164
|
+
node would run against, never a layer value or a runtime handle:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
const planned = Graph.build(Release, { target: "web" }, {
|
|
168
|
+
resolveLayers: (request) => request.capabilities.map((name) => `layer:${name}`),
|
|
169
|
+
root: "root"
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The resolver must be pure. Planning performs no input or output, and a resolver
|
|
174
|
+
that read the world would make a plan a function of more than its declarations.
|
|
175
|
+
`root` defaults to `"root"` and names the address the walk starts from.
|
|
176
|
+
|
|
177
|
+
## Drive one interpretation
|
|
178
|
+
|
|
179
|
+
`Interpreter.interpret` builds the graph and walks it against real values,
|
|
180
|
+
without registering the flow. It is the walk `Interpreter.layer` runs for each
|
|
181
|
+
round of an execution, and it requires the `FlowInstance` the runtime provides
|
|
182
|
+
to an executing round, so a program reaches it through `execute` rather than by
|
|
183
|
+
calling it at top level. It answers an `Interpretation`:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
interface Interpretation {
|
|
187
|
+
/** The root's value. */
|
|
188
|
+
readonly value: unknown
|
|
189
|
+
/** Every node that settled. */
|
|
190
|
+
readonly settled: ReadonlyMap<string, unknown>
|
|
191
|
+
/** The typed failures observed before a catch recovered them. */
|
|
192
|
+
readonly failed: ReadonlyMap<string, unknown>
|
|
193
|
+
/** The nodes a branch went the other way on. */
|
|
194
|
+
readonly skipped: ReadonlyArray<string>
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`skipped` is the field that answers "why did nothing happen here". The walk is
|
|
199
|
+
demand driven from the root rather than a sweep over the node list, because
|
|
200
|
+
dependency order puts both branch arms before the branch that chooses between
|
|
201
|
+
them, and executing an arm to discover it was not taken is exactly what static
|
|
202
|
+
topology exists to avoid.
|
|
203
|
+
|
|
204
|
+
## The refusals the interpreter reports
|
|
205
|
+
|
|
206
|
+
`Interpreter.InterpreterError` carries a stable `code`, the flow, and the node:
|
|
207
|
+
|
|
208
|
+
| Code | What it means |
|
|
209
|
+
| --------------------------------- | ------------------------------------------------------------------------------------ |
|
|
210
|
+
| `incomplete_graph` | The build reported topology it could not complete. |
|
|
211
|
+
| `duplicate_node_id` | Two nodes answer to one dispatch address. |
|
|
212
|
+
| `unresolved_action` | An action the body names has no implementation wired up. |
|
|
213
|
+
| `implementation_version_mismatch` | A declaration and its registered implementation disagree on `implementationVersion`. |
|
|
214
|
+
| `missing_implementation_version` | A content-reusable sealed action declares no `implementationVersion`. |
|
|
215
|
+
| `unresolved_reference` | A payload reads a node this graph does not hold. |
|
|
216
|
+
| `unsupported_call` | A call whose declaration did not survive serialization. |
|
|
217
|
+
| `missing_operation` | A deferred function that did not survive serialization. |
|
|
218
|
+
|
|
219
|
+
Missing mappers, branch predicates, and catch schema filters are refused before
|
|
220
|
+
any action dispatch, including operations in untaken arms. `Node.catch` cannot
|
|
221
|
+
recover an `InterpreterError`, even without an error schema.
|
|
222
|
+
|
|
223
|
+
`unresolved_action` is the one an author meets most: it means a layer is missing
|
|
224
|
+
from the composition, or `Action.layerImplementations` was merged beside the
|
|
225
|
+
implementation layers instead of provided under them.
|
|
226
|
+
|
|
227
|
+
## Related pages
|
|
228
|
+
|
|
229
|
+
- [Diff two plans](../../../plan/docs/guides/diff-two-plans.md): compile two
|
|
230
|
+
versions of a flow and see which steps were added, removed, or re-keyed.
|
|
231
|
+
- [Bodies are plans](../concepts/bodies-and-plans.md): why the build is pure and
|
|
232
|
+
what it refuses.
|
|
233
|
+
- [Execution identity](../concepts/execution-identity.md): how a node id becomes
|
|
234
|
+
a durable step key.
|
|
235
|
+
- [Troubleshooting](../troubleshooting.md): the same refusals, sorted by symptom.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Poll until something is ready"
|
|
3
|
+
description: "Declare a durable poller whose attempts are rounds and whose waits are durable timers, choose its backoff and bound, and put a time limit on a check that can hang."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 7
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`Poll.make` declares an ordinary flow whose body is **one attempt**: run the
|
|
9
|
+
check, and either settle the lineage with the check's own output or sleep for
|
|
10
|
+
this attempt's delay and hand off to the next round with the attempt counter
|
|
11
|
+
raised.
|
|
12
|
+
|
|
13
|
+
That shape is what makes a poll durable. Each attempt is a round with its own
|
|
14
|
+
keyed plan nodes, a check that already ran replays from its recorded outcome, and
|
|
15
|
+
the wait between attempts is a durable timer that survives a process restart.
|
|
16
|
+
|
|
17
|
+
## Declare the poll
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { Action, Interpreter, Poll, Sleep } from "@smthrs/flow"
|
|
21
|
+
import { Node } from "@smthrs/plan"
|
|
22
|
+
import * as Effect from "effect/Effect"
|
|
23
|
+
import * as Layer from "effect/Layer"
|
|
24
|
+
import * as Schema from "effect/Schema"
|
|
25
|
+
|
|
26
|
+
const Status = Action.make("deploy/Status", {
|
|
27
|
+
payload: { id: Schema.String, attempt: Schema.Number },
|
|
28
|
+
success: Poll.CheckResult(Schema.String)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export const Deployment = Poll.make("deploy/Wait", {
|
|
32
|
+
input: { id: Schema.String },
|
|
33
|
+
result: Schema.String,
|
|
34
|
+
intervalMs: 5_000,
|
|
35
|
+
backoff: "exponential",
|
|
36
|
+
maxAttempts: 8,
|
|
37
|
+
onTimeout: "fail",
|
|
38
|
+
check: Node.capture(
|
|
39
|
+
{ action: Status.name, implementationVersion: "deploy/status-check/v1" },
|
|
40
|
+
({ attempt, id }) => Status.call({ attempt, id })
|
|
41
|
+
)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
export const layer = Interpreter.layerWithImplementations(
|
|
45
|
+
Deployment,
|
|
46
|
+
Layer.mergeAll(
|
|
47
|
+
Status.toLayer(({ attempt, id }) =>
|
|
48
|
+
Effect.map(readDeployment(id), (live) => ({
|
|
49
|
+
satisfied: live,
|
|
50
|
+
output: `attempt-${attempt}`
|
|
51
|
+
}))
|
|
52
|
+
),
|
|
53
|
+
Poll.layer,
|
|
54
|
+
Sleep.layer
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`check` must be capture-stable under the default policy of
|
|
60
|
+
`Interpreter.layerWithImplementations`. Use `Node.capture` with every semantic
|
|
61
|
+
capture and a version for imported behavior. Capture any mappers, predicates,
|
|
62
|
+
or planned continuations inside the check as well. JavaScript cannot verify
|
|
63
|
+
closure completeness. `Poll.make` captures its generated body and predicate
|
|
64
|
+
using the schedule and `Node.functionIdentity(check)`. An uncaptured check keeps
|
|
65
|
+
the poll process-local and stable admission refuses it. Explicit
|
|
66
|
+
`callbackIdentity: "process-local"` allows experimentation without a
|
|
67
|
+
cross-process callback identity guarantee.
|
|
68
|
+
|
|
69
|
+
`Sleep.layer` is not optional. The wait between attempts is an ordinary
|
|
70
|
+
`system/sleep` node, so a composition without it has a plan node no
|
|
71
|
+
implementation answers. `Poll.layer` implements the `system/poll-exhausted` step
|
|
72
|
+
the last unsatisfied attempt takes.
|
|
73
|
+
|
|
74
|
+
## The options
|
|
75
|
+
|
|
76
|
+
| Option | Meaning |
|
|
77
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
78
|
+
| `input` | Your payload fields. `attempt` is added to them and defaults to one. |
|
|
79
|
+
| `result` | The schema the poll settles with. |
|
|
80
|
+
| `check` | A body fragment returning `{ satisfied, output }`. It may not fail: state what a failure means with `Node.catch` inside the fragment. |
|
|
81
|
+
| `intervalMs` | The base wait before the next attempt. |
|
|
82
|
+
| `backoff` | `fixed`, `linear` (interval multiplied by attempt), or `exponential` (interval multiplied by 2 raised to attempt minus one). Defaults to `fixed`. |
|
|
83
|
+
| `maxAttempts` | The attempt bound. It is also the flow's `maxRounds`, so a lineage that opened another round is refused by the engine. |
|
|
84
|
+
| `onTimeout` | `fail` fails `PollExhausted` at the bound; `return-last` answers with the last check output. Defaults to `fail`. |
|
|
85
|
+
|
|
86
|
+
`Poll.CheckResult(schema)` is the success schema a check action declares, and
|
|
87
|
+
`Poll.delayMillis` is the exported schedule function if you want to compute the
|
|
88
|
+
same delays yourself.
|
|
89
|
+
|
|
90
|
+
## What a bad schedule earns
|
|
91
|
+
|
|
92
|
+
`Poll.make` refuses a schedule no clock can keep, at declaration time, naming the
|
|
93
|
+
option that is wrong:
|
|
94
|
+
|
|
95
|
+
- A `TypeError` when `input` declares the reserved `attempt` field. `Poll` owns
|
|
96
|
+
that counter across rounds.
|
|
97
|
+
- A `RangeError` when `intervalMs` is not a finite number of milliseconds that is
|
|
98
|
+
not negative, because that interval becomes a `system/sleep` node whose timer
|
|
99
|
+
never fires.
|
|
100
|
+
- A `RangeError` when `maxAttempts` is not a whole number of attempts of at least
|
|
101
|
+
one. A poll checks at least once.
|
|
102
|
+
- A `RangeError` when the interval under the declared backoff reaches a wait no
|
|
103
|
+
clock can be armed with before the budget is spent.
|
|
104
|
+
|
|
105
|
+
That last check is on the whole schedule rather than on the interval alone,
|
|
106
|
+
because the backoff multiplies the interval:
|
|
107
|
+
`{ intervalMs: 1000, maxAttempts: 2000, backoff: "exponential" }` states three
|
|
108
|
+
finite options and still asks for a wait of `Infinity`. The check looks at the
|
|
109
|
+
last wait a poll can arm, the one before the final attempt, since the attempt at
|
|
110
|
+
the budget gives up rather than sleeps. That wait must also be at most
|
|
111
|
+
`Number.MAX_SAFE_INTEGER` milliseconds, the latest deadline a durable timer
|
|
112
|
+
records, so a one-millisecond interval doubling allows at most 54 attempts.
|
|
113
|
+
|
|
114
|
+
## Handle exhaustion
|
|
115
|
+
|
|
116
|
+
Under `onTimeout: "fail"` a spent budget fails `Poll.PollExhausted`, carrying the
|
|
117
|
+
poll name and the attempt count under the stable code `poll_exhausted`. A body
|
|
118
|
+
catches it like any other declared failure.
|
|
119
|
+
|
|
120
|
+
`Poll.Failure` is the union a poll's rounds can fail with, and it includes
|
|
121
|
+
`Sleep.SleepRequestInvalid` as well: the wait between attempts is an ordinary
|
|
122
|
+
sleep node, and a round payload can carry an attempt that derives an invalid
|
|
123
|
+
wait.
|
|
124
|
+
|
|
125
|
+
## Bound a check that can hang
|
|
126
|
+
|
|
127
|
+
There is deliberately no per-attempt time limit option. A plan node's duration is
|
|
128
|
+
not something the body around it can bound, so the bound goes in the check's own
|
|
129
|
+
implementation, where a durable race puts it on the recorded step:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { DurableClock, DurableDeferred } from "@smthrs/flow"
|
|
133
|
+
import * as Duration from "effect/Duration"
|
|
134
|
+
|
|
135
|
+
const statusLayer = Status.toLayer(({ attempt, id }) =>
|
|
136
|
+
DurableDeferred.raceAll({
|
|
137
|
+
name: `deploy/status#${attempt}`,
|
|
138
|
+
success: Poll.CheckResult(Schema.String),
|
|
139
|
+
error: Schema.Never,
|
|
140
|
+
effects: [
|
|
141
|
+
readDeploymentStatus(id),
|
|
142
|
+
Effect.as(
|
|
143
|
+
DurableClock.sleep({
|
|
144
|
+
name: `deploy/status#${attempt}`,
|
|
145
|
+
duration: Duration.seconds(30),
|
|
146
|
+
inMemoryThreshold: Duration.zero
|
|
147
|
+
}),
|
|
148
|
+
{ satisfied: false, output: "unknown" }
|
|
149
|
+
)
|
|
150
|
+
]
|
|
151
|
+
})
|
|
152
|
+
)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Three things make that the durable bound rather than a wall-clock one:
|
|
156
|
+
|
|
157
|
+
1. The race records its winner under a name carrying the attempt, so a re-driven
|
|
158
|
+
round reads the recorded outcome instead of racing again.
|
|
159
|
+
2. The clock parks the execution rather than holding a fiber, so the bound
|
|
160
|
+
outlives the process waiting on it.
|
|
161
|
+
3. The clock's branch answers `satisfied: false`, so a check that ran out of time
|
|
162
|
+
costs the poll one attempt and nothing else. The round takes its declared
|
|
163
|
+
interval and hands off exactly as an unsatisfied check does.
|
|
164
|
+
|
|
165
|
+
## Related pages
|
|
166
|
+
|
|
167
|
+
- [Trampoline rounds](../concepts/trampoline-rounds.md): the lineage machinery a
|
|
168
|
+
poll is built out of.
|
|
169
|
+
- [Wait for a deadline](./wait-for-a-deadline.md): the timer the interval arms.
|