@smthrs/flow 0.0.0-stage → 1.0.0-rc.3
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 +160 -0
- package/LICENSE +21 -0
- package/README.md +210 -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 +373 -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 +105 -0
- package/dist/cjs/Deadline.d.ts.map +1 -0
- package/dist/cjs/Deadline.js +104 -0
- package/dist/cjs/Deadline.js.map +7 -0
- package/dist/cjs/DurableClock.d.ts +61 -0
- package/dist/cjs/DurableClock.d.ts.map +1 -0
- package/dist/cjs/DurableClock.js +90 -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 +338 -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 +160 -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 +134 -0
- package/dist/cjs/Flow/make.d.ts.map +1 -0
- package/dist/cjs/Flow/make.js +104 -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 +198 -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 +175 -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 +1022 -0
- package/dist/cjs/Graph.js.map +7 -0
- package/dist/cjs/HumanTask.d.ts +440 -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 +222 -0
- package/dist/cjs/Interpreter.d.ts.map +1 -0
- package/dist/cjs/Interpreter.js +888 -0
- package/dist/cjs/Interpreter.js.map +7 -0
- package/dist/cjs/Poll.d.ts +238 -0
- package/dist/cjs/Poll.d.ts.map +1 -0
- package/dist/cjs/Poll.js +150 -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 +133 -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 +405 -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 +105 -0
- package/dist/esm/Deadline.d.ts.map +1 -0
- package/dist/esm/Deadline.js +152 -0
- package/dist/esm/Deadline.js.map +1 -0
- package/dist/esm/DurableClock.d.ts +61 -0
- package/dist/esm/DurableClock.d.ts.map +1 -0
- package/dist/esm/DurableClock.js +75 -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 +231 -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 +134 -0
- package/dist/esm/Flow/make.d.ts.map +1 -0
- package/dist/esm/Flow/make.js +106 -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 +198 -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 +175 -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 +1482 -0
- package/dist/esm/Graph.js.map +1 -0
- package/dist/esm/HumanTask.d.ts +440 -0
- package/dist/esm/HumanTask.d.ts.map +1 -0
- package/dist/esm/HumanTask.js +794 -0
- package/dist/esm/HumanTask.js.map +1 -0
- package/dist/esm/Interpreter.d.ts +222 -0
- package/dist/esm/Interpreter.d.ts.map +1 -0
- package/dist/esm/Interpreter.js +1269 -0
- package/dist/esm/Interpreter.js.map +1 -0
- package/dist/esm/Poll.d.ts +238 -0
- package/dist/esm/Poll.d.ts.map +1 -0
- package/dist/esm/Poll.js +282 -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 +230 -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 +150 -0
- package/docs/api.md +436 -0
- package/docs/concepts/bodies-and-plans.md +157 -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 +161 -0
- package/docs/guides/cancel-and-roll-back.md +112 -0
- package/docs/guides/implement-an-action.md +147 -0
- package/docs/guides/inspect-the-plan.md +154 -0
- package/docs/guides/poll-until-ready.md +167 -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 +122 -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 +82 -0
- package/docs/quickstart.md +155 -0
- package/docs/reference/flow.md +1831 -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 +657 -0
- package/src/Action/raceAll.ts +48 -0
- package/src/Action/retry.ts +92 -0
- package/src/Deadline.ts +185 -0
- package/src/DurableClock.ts +133 -0
- package/src/DurableDeferred.ts +753 -0
- package/src/DurableQueue.ts +519 -0
- package/src/ExternalJob.ts +432 -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 +309 -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 +279 -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 +333 -0
- package/src/FlowRuntime/NodeRecord.ts +183 -0
- package/src/FlowRuntime/WaitingAnnotation.ts +85 -0
- package/src/FlowRuntime/index.ts +17 -0
- package/src/Graph.ts +1860 -0
- package/src/HumanTask.ts +1003 -0
- package/src/Interpreter.ts +1593 -0
- package/src/Poll.ts +414 -0
- package/src/RetryPolicy.ts +550 -0
- package/src/Sleep.ts +267 -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,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Hand work to a durable worker"
|
|
3
|
+
description: "Declare a durable queue, suspend a flow until a worker records its result, and run the worker as a layer with bounded concurrency."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 10
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
A `DurableQueue` moves work out of the flow that asked for it. The flow offers a
|
|
9
|
+
payload, parks, and resumes when a worker persists a result. Requests and recorded
|
|
10
|
+
results survive the process that made them.
|
|
11
|
+
|
|
12
|
+
## Declare the queue
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { DurableQueue } from "@smthrs/flow"
|
|
16
|
+
import * as Schema from "effect/Schema"
|
|
17
|
+
|
|
18
|
+
export const Renders = DurableQueue.make({
|
|
19
|
+
name: "Renders",
|
|
20
|
+
payload: Schema.Struct({ page: Schema.String }),
|
|
21
|
+
success: Schema.String,
|
|
22
|
+
idempotencyKey: ({ page }) => page
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`idempotencyKey` is required. The payload key scopes an occurrence counter;
|
|
27
|
+
the execution ID and occurrence ordinal also contribute to the queue item ID.
|
|
28
|
+
Distinct offers of the same page create distinct items, including within one
|
|
29
|
+
execution. Replaying the same occurrence derives the same ID for queue deduplication.
|
|
30
|
+
Business-level deduplication across distinct offers or runs is the caller's job.
|
|
31
|
+
`success` defaults to `Schema.Void` and `error` to `Schema.Never`.
|
|
32
|
+
|
|
33
|
+
## Offer work from a flow
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
const rendered = DurableQueue.process(Renders, { page: "home" })
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`process` offers the payload under the name `DurableQueue/<name>`, attaches a
|
|
40
|
+
completion token, and suspends the execution until a worker records the handler's
|
|
41
|
+
exit against it. The success and error channels are the queue's declared schemas,
|
|
42
|
+
so the caller sees the worker's own outcome. While suspended, the execution's
|
|
43
|
+
waiting annotation has reason `event` and the item's completion token.
|
|
44
|
+
|
|
45
|
+
Invalid payloads and offer encoding failures die with `SchemaError` without
|
|
46
|
+
retrying. The final offer failure of an exhausted retry schedule also becomes a
|
|
47
|
+
defect. The typed error channel is reserved for the worker's declared error.
|
|
48
|
+
|
|
49
|
+
`retrySchedule` bounds how a failing offer is retried. The default retries with
|
|
50
|
+
exponential delays capped at one minute and never gives up, so a caller that
|
|
51
|
+
wants a bound supplies its own:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import * as Schedule from "effect/Schedule"
|
|
55
|
+
|
|
56
|
+
const bounded = DurableQueue.process(Renders, { page: "home" }, {
|
|
57
|
+
retrySchedule: Schedule.recurs(5)
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Run the worker
|
|
62
|
+
|
|
63
|
+
`DurableQueue.worker` is the layer form: it forks the worker into the layer's
|
|
64
|
+
scope, so it starts with the composition and stops with it.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import * as Effect from "effect/Effect"
|
|
68
|
+
|
|
69
|
+
export const RendersWorker = DurableQueue.worker(
|
|
70
|
+
Renders,
|
|
71
|
+
({ page }) => Effect.succeed(`<html>${page}</html>`),
|
|
72
|
+
{ concurrency: 4, maxAttempts: 10 }
|
|
73
|
+
)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`concurrency` defaults to `1` and must be a positive safe integer;
|
|
77
|
+
`DurableQueue.makeWorker` and `DurableQueue.worker` throw a `RangeError`
|
|
78
|
+
otherwise. `makeWorker` is the underlying effect, for a host that wants to fork
|
|
79
|
+
it itself.
|
|
80
|
+
|
|
81
|
+
The handler's exit is what the waiting flow receives. A handler that fails with
|
|
82
|
+
the queue's declared error type resumes the caller with that typed failure; a
|
|
83
|
+
handler that dies resumes it with a defect. An interrupt-only handler exit records
|
|
84
|
+
nothing and requeues the item without consuming an attempt. Mixed failures are
|
|
85
|
+
recorded with interrupt reasons removed.
|
|
86
|
+
|
|
87
|
+
Handler execution is at least once: if recording its result fails, a subsequent
|
|
88
|
+
take runs the handler again. Make side effects idempotent using a business key in
|
|
89
|
+
the payload. `maxAttempts` is passed to the persisted queue and defaults to `10`
|
|
90
|
+
on both worker constructors. Failed takes consume attempts; interrupt-only exits
|
|
91
|
+
do not. A declared handler failure that is successfully recorded completes the
|
|
92
|
+
item instead of retrying it.
|
|
93
|
+
|
|
94
|
+
A worker completes only the wait its own `process` call created: an item stored
|
|
95
|
+
under ID `key` must carry a token for `DurableQueue/<name>/<key>`. An item whose
|
|
96
|
+
token is malformed or names any other wait point is logged at error level and
|
|
97
|
+
acknowledged without running the handler. The worker links its span to the
|
|
98
|
+
offering span only when the stored trace and span ids are 32 and 16 lowercase hex
|
|
99
|
+
characters.
|
|
100
|
+
|
|
101
|
+
A take failure after the handler produces a recordable exit is logged at error
|
|
102
|
+
level with the queue name, item ID, completion token, attempt, attempt limit, and
|
|
103
|
+
whether that limit was reached. At exhaustion the store drops or quarantines the
|
|
104
|
+
item according to its policy. If completion writes exhaust the attempts without
|
|
105
|
+
recording a result, the caller remains suspended and requires recovery by the
|
|
106
|
+
host. Raising `maxAttempts` allows more retries but does not guarantee completion.
|
|
107
|
+
|
|
108
|
+
## When to reach for it
|
|
109
|
+
|
|
110
|
+
A durable queue is the right shape when the work has a different lifetime or a
|
|
111
|
+
different scaling story from the flow that asked for it: a render farm, a batch
|
|
112
|
+
of uploads, anything where the caller should park rather than hold a slot. When
|
|
113
|
+
the work belongs to the same run, an action is simpler and keeps the step in the
|
|
114
|
+
plan. When it is its own unit of work with its own journal,
|
|
115
|
+
[a child execution](./run-a-child-flow.md) is the closer fit.
|
|
116
|
+
|
|
117
|
+
## Related pages
|
|
118
|
+
|
|
119
|
+
- [Wait for an external signal](./wait-for-an-external-signal.md): the deferred
|
|
120
|
+
and token machinery the queue's reply channel is built on.
|
|
121
|
+
- [Suspension and replay](../concepts/suspension-and-replay.md): what the caller
|
|
122
|
+
is doing while the worker works.
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Retry a failing action"
|
|
3
|
+
description: "Declare a retry policy, understand where the engine makes its retry decision, keep integrity failures unretried, and read the two terminal defects."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 3
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
A `RetryPolicy` is plain data, not a `Schedule`. That is deliberate: the next
|
|
9
|
+
delay is derived from a **persisted** attempt count rather than from fiber-local
|
|
10
|
+
state, so a backoff ladder survives a park, a resume, and the death of the
|
|
11
|
+
process that started it.
|
|
12
|
+
|
|
13
|
+
## Declare a policy
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { RetryPolicy } from "@smthrs/flow"
|
|
17
|
+
|
|
18
|
+
const policy = RetryPolicy.make({
|
|
19
|
+
initialMs: 200,
|
|
20
|
+
factor: 2,
|
|
21
|
+
maxMs: 10_000,
|
|
22
|
+
maxAttempts: 5,
|
|
23
|
+
expirationMs: 5 * 60_000,
|
|
24
|
+
jitterRatio: 0.2,
|
|
25
|
+
nonRetryable: ["payments/ChargeDeclined"]
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`RetryPolicy.make` checks every bound and throws a `RangeError` naming the field
|
|
30
|
+
that is wrong: `initialMs` finite and greater than zero, `factor` finite and
|
|
31
|
+
positive, `maxMs` finite and not below `initialMs`, `maxAttempts` a safe integer
|
|
32
|
+
of at least one, `expirationMs` finite and positive, and `jitterRatio` finite
|
|
33
|
+
and within zero and one inclusive. `initialMs: 0` is refused rather than read as
|
|
34
|
+
"retry immediately": every computed delay would be zero, which `nextDelay`
|
|
35
|
+
treats as exhausted, so the policy would give up on the first failure whatever
|
|
36
|
+
`maxAttempts` promised. Use `initialMs: 1` for a near-immediate retry.
|
|
37
|
+
`jitterRatio: 0` disables jitter. The
|
|
38
|
+
`nonRetryable` array is copied and frozen, so mutating your array later cannot
|
|
39
|
+
change what a parked policy means.
|
|
40
|
+
|
|
41
|
+
`RetryPolicy.defaultRetryPolicy` is `{ initialMs: 200, factor: 1.5, maxMs: 30000 }`.
|
|
42
|
+
It declares neither `maxAttempts` nor `expirationMs`, so it never gives up. Bound
|
|
43
|
+
a long-lived retry with `expirationMs` when a wall-clock give-up is required.
|
|
44
|
+
|
|
45
|
+
## Attach it to the work
|
|
46
|
+
|
|
47
|
+
The engine reads `action.retryPolicy` at dispatch. Both forms of `Action.make`
|
|
48
|
+
take it; the [`Action.make` reference](../reference/flow.md#actionmake) lists
|
|
49
|
+
every option. The inline form:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { Action } from "@smthrs/flow"
|
|
53
|
+
import * as Effect from "effect/Effect"
|
|
54
|
+
import * as Schema from "effect/Schema"
|
|
55
|
+
|
|
56
|
+
const settle = Action.make({
|
|
57
|
+
name: "payments/Settle",
|
|
58
|
+
success: Schema.String,
|
|
59
|
+
error: Schema.String,
|
|
60
|
+
tier: "irreversible",
|
|
61
|
+
idempotencyKey: "settle:checkout-v1",
|
|
62
|
+
retryPolicy: policy,
|
|
63
|
+
execute: Effect.suspend(() => callProvider())
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
A **declared** action, the kind a body names, takes the same option:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const Settle = Action.make("payments/Settle", {
|
|
71
|
+
payload: { orderId: Schema.String },
|
|
72
|
+
success: Schema.String,
|
|
73
|
+
error: Schema.String,
|
|
74
|
+
retryPolicy: policy
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Two other tools cover different needs:
|
|
79
|
+
|
|
80
|
+
- Dispatch an inline action from inside an implementation when a nested step
|
|
81
|
+
needs its own record and its own attempt sequence.
|
|
82
|
+
- Wrap work in `Action.retry`, which is `Effect.retry` with the durable attempt
|
|
83
|
+
context threaded through it, for a retry the policy does not describe.
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
const attempts = Action.retry(settle, { times: 3 })
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`Action.retry` updates `Action.CurrentAttempt` on each attempt and pins ordinals
|
|
90
|
+
per allocation scope, so every attempt of one sequence reuses its own action's
|
|
91
|
+
ordinals instead of drawing new step keys. A nested block shares the enclosing
|
|
92
|
+
block's pinned slot, so a completed inner dispatch replays rather than
|
|
93
|
+
re-executing.
|
|
94
|
+
|
|
95
|
+
## Infrastructure failures without a declared policy
|
|
96
|
+
|
|
97
|
+
When no `retryPolicy` is declared, Dispatch uses `RetryPolicy.transient` only
|
|
98
|
+
for a typed failure whose `Fault.of(error).class` is `infra`, and only when the
|
|
99
|
+
action has an `idempotencyKey` or explicitly declares an empty `effects.writes`.
|
|
100
|
+
A missing effect declaration does not promise repeat safety. Other failures
|
|
101
|
+
return immediately. A declared policy retains its existing behavior.
|
|
102
|
+
|
|
103
|
+
The transient policy starts at 5 seconds, doubles to a 5-minute cap, and expires
|
|
104
|
+
2 hours after the first attempt. Durable engines retain the origin and attempt
|
|
105
|
+
count across recovery. Exhaustion preserves the final error and its fault class.
|
|
106
|
+
An unkeyed irreversible action still cannot retry under the irreversible guard.
|
|
107
|
+
|
|
108
|
+
For plain effects that the caller knows are safe to repeat:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { Fault } from "@smthrs/flow"
|
|
112
|
+
|
|
113
|
+
const recovered = Fault.retryTransient(readStatus)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This helper retries typed infrastructure failures under the same bounded policy.
|
|
117
|
+
It preserves the final typed error; defects and cancellation propagate directly.
|
|
118
|
+
Host command adapters can use `Unreachable.classifyExit(stderr)` from
|
|
119
|
+
`@smthrs/kernel` to turn DNS, connection, HTTP 429, and HTTP 5xx failures into
|
|
120
|
+
typed infrastructure errors. Ordinary command failures remain domain errors.
|
|
121
|
+
|
|
122
|
+
## What the engine decides, and when
|
|
123
|
+
|
|
124
|
+
`RetryPolicy.decide` is the engine's single retry decision point, and
|
|
125
|
+
non-retryable classification happens there and nowhere else. On a failing
|
|
126
|
+
attempt the engine asks the policy, passing the current attempt, the error, and
|
|
127
|
+
the elapsed time since the first attempt:
|
|
128
|
+
|
|
129
|
+
| Decision | What happens |
|
|
130
|
+
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
131
|
+
| `RetryAfter(delayMs)` | The engine sleeps and dispatches attempt `n + 1`. An irreversible action with no `idempotencyKey` dies with `IrreversibleRetryRequiresIdempotencyKey` instead. |
|
|
132
|
+
| `GiveUp("nonRetryable")` | The original typed failure propagates unchanged. |
|
|
133
|
+
| `GiveUp("exhausted")` | The final declared failure propagates unchanged. |
|
|
134
|
+
| `GiveUp("expired")` | The final declared failure propagates unchanged. |
|
|
135
|
+
|
|
136
|
+
A spent retry policy preserves the action's error channel. `Node.catch` and
|
|
137
|
+
ordinary typed Effect recovery can handle the final failure. The execution span
|
|
138
|
+
records `retry.stopReason` and `retry.attempt`; adding retries does not turn a
|
|
139
|
+
business failure into a defect. Previously persisted exhaustion defects remain
|
|
140
|
+
historical outcomes and are not rewritten.
|
|
141
|
+
|
|
142
|
+
A durable engine persists the first attempt's start time and the attempt
|
|
143
|
+
sequence, so `expirationMs` is measured from the true first attempt and a
|
|
144
|
+
resumed run does not re-sleep the ladder from attempt one.
|
|
145
|
+
|
|
146
|
+
## Failures that are never retried
|
|
147
|
+
|
|
148
|
+
`RetryPolicy.defaultNonRetryable` lists error tags that are non-retryable under
|
|
149
|
+
**every** policy, with no per-callsite opt-out. They are integrity verdicts from
|
|
150
|
+
[`@smthrs/engine-store`](/api/engine-store), and they must reach the driver
|
|
151
|
+
without an action-level retry hiding the first detection.
|
|
152
|
+
|
|
153
|
+
Your own tags go in `nonRetryable`. `RetryPolicy.errorTag` is how a tag is read
|
|
154
|
+
off an error: an own string `_tag` when present, otherwise the first own `name`
|
|
155
|
+
descriptor found while walking a bounded prototype chain.
|
|
156
|
+
|
|
157
|
+
## Bound a hung attempt
|
|
158
|
+
|
|
159
|
+
A retry policy only sees attempts that end. Declare `attemptTimeoutMs` to end
|
|
160
|
+
one that hangs, or `heartbeatTimeoutMs` to end one that stops reporting
|
|
161
|
+
progress through `Action.heartbeat`. Both forms of `Action.make` take them, as
|
|
162
|
+
positive integers:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const Fetch = Action.make("sandbox/Fetch", {
|
|
166
|
+
payload: { url: Schema.String },
|
|
167
|
+
success: Schema.String,
|
|
168
|
+
retryPolicy: policy,
|
|
169
|
+
attemptTimeoutMs: 30_000,
|
|
170
|
+
heartbeatTimeoutMs: 5_000
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const layer = Fetch.toLayer(({ url }) =>
|
|
174
|
+
Effect.gen(function*() {
|
|
175
|
+
const stream = yield* openStream(url)
|
|
176
|
+
// Each heartbeat restarts the 5 second gap.
|
|
177
|
+
return yield* readChunks(stream, { onChunk: () => Action.heartbeat })
|
|
178
|
+
})
|
|
179
|
+
)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
An expired bound interrupts the body and dies with `Action.AttemptTimedOut`,
|
|
183
|
+
naming the action, the attempt, the `bound` that expired (`"attempt"` or
|
|
184
|
+
`"heartbeat"`), and its `timeoutMs`. The engine counts that defect as a failed
|
|
185
|
+
attempt: `retryPolicy` decides on it like a typed failure, a durable engine
|
|
186
|
+
records it as a failed attempt row, and listing `"@smthrs/flow/AttemptTimedOut"`
|
|
187
|
+
in `nonRetryable` stops the retries. Without a retry policy, or once the policy
|
|
188
|
+
gives up, the defect is the action's outcome. Every other defect stays
|
|
189
|
+
unretried.
|
|
190
|
+
|
|
191
|
+
## Infrastructure interrupts
|
|
192
|
+
|
|
193
|
+
An action implementation or transport adapter may fail with
|
|
194
|
+
`Action.InfraInterrupt` when it can identify a retryable infrastructure event.
|
|
195
|
+
It is not an ordinary domain failure and `retryPolicy` does not see it. Only an
|
|
196
|
+
inline action's `interruptRetryPolicy`, an Effect `Schedule`, retries the
|
|
197
|
+
explicit marker. The shipped engines do not convert owner loss, host shutdown,
|
|
198
|
+
or ordinary fiber interruption into it:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import * as Schedule from "effect/Schedule"
|
|
202
|
+
|
|
203
|
+
const resilient = Action.make({
|
|
204
|
+
name: "payments/Settle",
|
|
205
|
+
success: Schema.String,
|
|
206
|
+
error: Schema.String,
|
|
207
|
+
interruptRetryPolicy: Schedule.recurs(3),
|
|
208
|
+
execute: callProvider().pipe(
|
|
209
|
+
Effect.catchTag(
|
|
210
|
+
"TransportUnavailable",
|
|
211
|
+
(error) => Effect.fail(new Action.InfraInterrupt({ reason: error.message }))
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Spending that schedule without reaching an ordinary success or failure dies with
|
|
218
|
+
`Action.InfraInterruptRetriesExhausted`, carrying the action name, the attempt
|
|
219
|
+
count, and the final interrupt.
|
|
220
|
+
|
|
221
|
+
## Deciding without an engine
|
|
222
|
+
|
|
223
|
+
The policy functions are pure and exported, so a host can ask the same questions
|
|
224
|
+
the engine asks:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
RetryPolicy.nextDelay(policy, 2) // Option<number>; None means give up
|
|
228
|
+
RetryPolicy.isNonRetryable(policy, error)
|
|
229
|
+
RetryPolicy.decide(policy, { attempt: 2, error })
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`nextDelay` is total even for a policy decoded from a persisted row: a
|
|
233
|
+
non-finite attempt, elapsed time, bound, or computed delay answers `None` rather
|
|
234
|
+
than handing a caller a negative or `NaN` duration. `RetryPolicy.nextDelayEffect`
|
|
235
|
+
and `RetryPolicy.decideEffect` are the variants that sample the `Random` service
|
|
236
|
+
for jitter.
|
|
237
|
+
|
|
238
|
+
## Related pages
|
|
239
|
+
|
|
240
|
+
- [Attach an implementation to an action](./implement-an-action.md): the tiers a
|
|
241
|
+
retry has to respect.
|
|
242
|
+
- [Suspension and replay](../concepts/suspension-and-replay.md): why
|
|
243
|
+
`suspendedRetryPolicy` on a flow is a different thing entirely.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Reuse a recorded result"
|
|
3
|
+
description: "Declare a cache policy on a sealed action, supply the composition's complete cache environment, and declare the file boundary that makes a result shareable across runs."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 12
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Every sealed action's result is recorded and replayed inside its own execution.
|
|
9
|
+
Reusing one across executions is a stronger claim, and it takes three
|
|
10
|
+
declarations. Missing any one of them scopes the key to the run that produced it,
|
|
11
|
+
which is safe and does nothing.
|
|
12
|
+
|
|
13
|
+
1. **An identity a second run can derive.** The action's `idempotencyKey`.
|
|
14
|
+
2. **A hermetic boundary.** The action's declared `FileBoundary`, with
|
|
15
|
+
`boundaryMode: "hard"`.
|
|
16
|
+
3. **A complete environment.** The composition's `Action.CacheEnvironment`.
|
|
17
|
+
|
|
18
|
+
## Declare how long the result stays good
|
|
19
|
+
|
|
20
|
+
`Action.withCache` returns a copy of the action annotated with a `CachePolicy`.
|
|
21
|
+
The action is not mutated: `annotate` returns a separate declaration, and that
|
|
22
|
+
copy is what a plan captures.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { Action } from "@smthrs/flow"
|
|
26
|
+
import * as Effect from "effect/Effect"
|
|
27
|
+
import * as Schema from "effect/Schema"
|
|
28
|
+
|
|
29
|
+
const compile = Action.withCache(
|
|
30
|
+
Action.make({
|
|
31
|
+
name: "build/Compile",
|
|
32
|
+
success: Schema.String,
|
|
33
|
+
tier: "sealed",
|
|
34
|
+
idempotencyKey: "build/compile/v1",
|
|
35
|
+
fileBoundary: { readSet: [], writeSet: [], boundaryMode: "hard" },
|
|
36
|
+
execute: Effect.sync(() => "dist/server.js")
|
|
37
|
+
}),
|
|
38
|
+
{ ttlMs: 15 * 60_000, scope: "shared" }
|
|
39
|
+
)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Both policy fields are optional and both defaults are the behavior you get
|
|
43
|
+
without a policy: no age bound, and the reach the composition's environment
|
|
44
|
+
already granted.
|
|
45
|
+
|
|
46
|
+
| Field | Meaning |
|
|
47
|
+
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
48
|
+
| `ttlMs` | A positive whole number of milliseconds bounding the age of a row the engine may serve. Past it the dispatch executes again. |
|
|
49
|
+
| `scope` | `shared` names the inputs and the environment, so any run on any host that would have produced the same bytes may reuse the row. `flow` and `run` narrow that, folding the flow or the execution into the key so a sibling never reads it. |
|
|
50
|
+
|
|
51
|
+
The engine journals its age judgement as a `flows.engine.cache-provenance`
|
|
52
|
+
record before acting on it, so a reader can tell an expiry from a plain miss, and
|
|
53
|
+
a resumed run reads the verdict it already took instead of re-judging it against
|
|
54
|
+
a fresh clock.
|
|
55
|
+
|
|
56
|
+
`Action.cachePolicyOf(annotations)` reads a policy back off an annotation bag,
|
|
57
|
+
and `Action.CachePolicyAnnotation` is the key it is carried under.
|
|
58
|
+
|
|
59
|
+
## Declare the file boundary
|
|
60
|
+
|
|
61
|
+
An action's typed `fileBoundary` declares its `Action.FileBoundary`, and the engine folds
|
|
62
|
+
that boundary into the key rather than trusting a caller-supplied field:
|
|
63
|
+
|
|
64
|
+
| Field | Meaning |
|
|
65
|
+
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
66
|
+
| `readSet` | Exact files already measured (`Action.FileInput`, a workspace-relative path plus its content digest), or globs to expand while preparing. |
|
|
67
|
+
| `writeSet` | The files or patterns the action may write. |
|
|
68
|
+
| `removes` | The paths the action may delete. Optional, empty by default, and disjoint from `writeSet`: a path cannot be both promised and disclaimed. |
|
|
69
|
+
| `boundaryMode` | `hard` rejects undeclared access immediately. `expected` validates it later. |
|
|
70
|
+
|
|
71
|
+
`removes` exists because a declared write that is absent when the action
|
|
72
|
+
finishes is a defect: recording the absence as valid evidence would cache the
|
|
73
|
+
claim that the file should not exist, and a later replay would act on it by
|
|
74
|
+
deleting the path. A declared removal is what makes an absent path legitimate.
|
|
75
|
+
|
|
76
|
+
`Action.Filegroup`, `Action.Glob`, and `Action.TreeArtifact` are the reusable
|
|
77
|
+
vocabulary those sets are written in: named groups of declarations,
|
|
78
|
+
Bazel-style include and exclude patterns, and a directory output captured and
|
|
79
|
+
replayed as one tree artifact.
|
|
80
|
+
|
|
81
|
+
Both inline and declared actions accept `fileBoundary`. Declared actions may
|
|
82
|
+
compute it from decoded payload fields, and can derive `idempotencyKey` from
|
|
83
|
+
the same payload. They also accept `retryPolicy` and `interruptRetryPolicy`;
|
|
84
|
+
see the [`Action.make` reference](../reference/flow.md#actionmake) for every
|
|
85
|
+
option. A new typed boundary is validated before dispatch. Historical
|
|
86
|
+
inline `metadata` boundary declarations remain readable for existing callers.
|
|
87
|
+
|
|
88
|
+
## Declare the composition's environment
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const environment = Action.layerCacheEnvironment({
|
|
92
|
+
layers: ["node@26.4.0", "toolchain@3.1.0"],
|
|
93
|
+
capabilities: { filesystem: ["read", "write"] }
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`Action.CacheEnvironment` is `{ layers, capabilities }`: the ordered semantic
|
|
98
|
+
runtime layers, including versions and configuration, and the complete effective
|
|
99
|
+
capability groups. A composition either provides a **complete** value or leaves
|
|
100
|
+
it absent. When it is absent, the engine scopes action keys to the current
|
|
101
|
+
execution rather than presenting incomplete environment data as reusable
|
|
102
|
+
identity, and `Action.CurrentCacheEnvironment` reads `undefined`.
|
|
103
|
+
|
|
104
|
+
That is the safe default and it is doing real work: a half-declared environment
|
|
105
|
+
would let a result computed under one toolchain be served to a run under
|
|
106
|
+
another.
|
|
107
|
+
|
|
108
|
+
## What cannot enter a key
|
|
109
|
+
|
|
110
|
+
An object-form `idempotencyKey` is caller-owned canonical JSON. Material that
|
|
111
|
+
canonical serialization rejects, such as a `Date`, an `undefined`, a class
|
|
112
|
+
instance, or a `Redacted`, is refused with `Action.UncanonicalIdempotencyKey`
|
|
113
|
+
naming the offending path. The refusal is a typed, non-retryable recorded
|
|
114
|
+
completion rather than an untyped defect, because the same declaration derives
|
|
115
|
+
the same rejection on every attempt and the body never runs.
|
|
116
|
+
|
|
117
|
+
## Related pages
|
|
118
|
+
|
|
119
|
+
- [Execution identity](../concepts/execution-identity.md): the full account of
|
|
120
|
+
what enters a key, and the one limit of schema-shaped key material.
|
|
121
|
+
- [Attach an implementation to an action](./implement-an-action.md): tiers, and
|
|
122
|
+
when an inline action is the right form.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Run a flow as a child execution"
|
|
3
|
+
description: "Choose between splicing a callee inline, opening a real child execution, and handing off to the next round, and know which build refusals force a boundary."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 8
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
A flow can reach another flow in three ways, and they are three different things.
|
|
9
|
+
|
|
10
|
+
| Call | What the caller's plan holds | Requirements | Identity |
|
|
11
|
+
| ----------------------- | ---------------------------------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------- |
|
|
12
|
+
| `callee.call(payload)` | The callee's whole body, spliced in. Every inner step is visible and individually keyed. | Propagate to the caller. | The caller's execution. |
|
|
13
|
+
| `callee.child(payload)` | One leaf. | Dropped. | A separate execution, with its own row, journal lineage, retry policy, and placement. |
|
|
14
|
+
| `callee.to(payload)` | The settlement of this round. | Dropped. | The next round of this trampoline lineage. |
|
|
15
|
+
|
|
16
|
+
## Splice a callee inline
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { Action, Flow } from "@smthrs/flow"
|
|
20
|
+
import { Node } from "@smthrs/plan"
|
|
21
|
+
import * as Schema from "effect/Schema"
|
|
22
|
+
|
|
23
|
+
const Build = Action.make("release/Build", {
|
|
24
|
+
payload: { target: Schema.String },
|
|
25
|
+
success: Schema.String
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export const Compile = Flow.make("release/Compile", {
|
|
29
|
+
payload: { target: Schema.String },
|
|
30
|
+
success: Schema.String,
|
|
31
|
+
body: (payload) => Build.call(payload)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
export const Release = Flow.make("release/Release", {
|
|
35
|
+
payload: { target: Schema.String },
|
|
36
|
+
success: Schema.String,
|
|
37
|
+
body: ({ target }) => Compile.call({ target })
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Inline is the default choice. One plan, one run, and every step of the callee is
|
|
42
|
+
a node the caller's operator can see, key, and replay. The callee's obligations
|
|
43
|
+
become the caller's, which is exactly right: they are running in the caller's
|
|
44
|
+
execution.
|
|
45
|
+
|
|
46
|
+
## Open a real child
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
export const Fanout = Flow.make("release/Fanout", {
|
|
50
|
+
payload: { targets: Schema.Array(Schema.String) },
|
|
51
|
+
success: Schema.Struct({ web: Schema.String, api: Schema.String }),
|
|
52
|
+
body: () =>
|
|
53
|
+
Node.all({
|
|
54
|
+
web: Compile.child({ target: "web" }),
|
|
55
|
+
api: Compile.child({ target: "api" })
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Choose `child` when the callee should be its own unit of work: its own run row to
|
|
61
|
+
watch, its own journal lineage, its own retry and placement decisions. The
|
|
62
|
+
parent's plan holds one leaf naming it, the parent suspends while the child is
|
|
63
|
+
unsettled, and it resumes when the child settles.
|
|
64
|
+
|
|
65
|
+
The identity is derived rather than minted. `Interpreter.childExecutionId`
|
|
66
|
+
combines the parent execution id, the node's address, the callee tag, and a digest
|
|
67
|
+
of the payload, so a re-driven parent lands on the child it already started
|
|
68
|
+
instead of opening a second one. That is what makes a child at most once without
|
|
69
|
+
the caller naming an id.
|
|
70
|
+
|
|
71
|
+
Requirements are dropped at the boundary because the child runs under its own
|
|
72
|
+
driver, which provides its own context. The caller's composition does not have to
|
|
73
|
+
carry the child's implementations, and the child's driver does.
|
|
74
|
+
|
|
75
|
+
## Hand off to the next round
|
|
76
|
+
|
|
77
|
+
`callee.to(payload)` ends the current round and names the next one. It is the
|
|
78
|
+
loop construct, not a call: nothing comes back, because this execution is over.
|
|
79
|
+
See [Trampoline rounds](../concepts/trampoline-rounds.md).
|
|
80
|
+
|
|
81
|
+
## When a boundary is required
|
|
82
|
+
|
|
83
|
+
Two build refusals exist to send you to `child` or `to`, and both throw from
|
|
84
|
+
`Graph.build` rather than landing in diagnostics:
|
|
85
|
+
|
|
86
|
+
- `recursion_requires_boundary`: a flow called itself inline. Inline expansion
|
|
87
|
+
would never terminate. Use `to` for a loop or `child` for a nested run.
|
|
88
|
+
- `placement_requires_boundary`: an inline callee declares a `Flow.Placement`
|
|
89
|
+
the enclosing flow cannot satisfy. A placement is a property of an execution,
|
|
90
|
+
so a callee that needs a different one needs its own execution.
|
|
91
|
+
|
|
92
|
+
At run time, `FlowRuntime.FlowCycleDetected` is the separate refusal for a child
|
|
93
|
+
whose execution would close a cycle in the persisted parent chain. Its `path`
|
|
94
|
+
holds the ordered execution ids from the cycle's target back to itself.
|
|
95
|
+
|
|
96
|
+
## Cancellation and cleanup travel
|
|
97
|
+
|
|
98
|
+
A parent's interruption reaches its children, and a child's suspension reaches
|
|
99
|
+
its parent, because the engine records the lineage edge. Cleanup follows the
|
|
100
|
+
same edges: see
|
|
101
|
+
[Cancel a run and undo its effects](./cancel-and-roll-back.md).
|
|
102
|
+
|
|
103
|
+
## Related pages
|
|
104
|
+
|
|
105
|
+
- [Flows and actions](../concepts/flows-and-actions.md): the propagation rules,
|
|
106
|
+
stated once.
|
|
107
|
+
- [Execution identity](../concepts/execution-identity.md): how a child's id is
|
|
108
|
+
derived.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Run an external job"
|
|
3
|
+
description: "Start external work once, park between probes, and reattach after a host restart."
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 8
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`ExternalJob.make` composes recorded Start, Status, Collect and Cancel actions
|
|
9
|
+
with ordinary flow handoffs and durable timers. The adapter owns the external
|
|
10
|
+
worker; a parked Smithers execution owns no worker process scope.
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { Action, ExternalJob, Flow, Interpreter } from "@smthrs/flow"
|
|
14
|
+
import { Node } from "@smthrs/plan"
|
|
15
|
+
import { RemoteChildProcessSpawner, Sandbox } from "@smthrs/sandbox"
|
|
16
|
+
import { Effect, Layer, Schema } from "effect"
|
|
17
|
+
|
|
18
|
+
const Build = ExternalJob.make("build/external", {
|
|
19
|
+
payload: { source: Schema.String },
|
|
20
|
+
handle: Sandbox.JobHandle,
|
|
21
|
+
success: Sandbox.JobResult,
|
|
22
|
+
error: Schema.Union([RemoteChildProcessSpawner.ProviderError, Sandbox.CaptureError]),
|
|
23
|
+
probe: { every: "15 seconds", max: "2 minutes" },
|
|
24
|
+
timeout: "2 hours",
|
|
25
|
+
restarts: 1
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
// The provider adapter supplies create-or-get, observation, collection and
|
|
29
|
+
// cancellation. Convert cleanup transport errors to visible defects.
|
|
30
|
+
const adapter = Sandbox.job(provider, { command: "make" })
|
|
31
|
+
const buildLayer = Build.toLayer({
|
|
32
|
+
...adapter,
|
|
33
|
+
cancel: (handle, key) => adapter.cancel(handle, key).pipe(Effect.orDie)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const Pipeline = Flow.make("build/pipeline", {
|
|
37
|
+
payload: { source: Schema.String },
|
|
38
|
+
success: Sandbox.JobResult,
|
|
39
|
+
error: Build.errorSchema,
|
|
40
|
+
body: Node.capture({ version: "build/pipeline/v1", build: Build._tag }, (payload) => Build.call(payload))
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const implementations = Layer.mergeAll(buildLayer, Interpreter.layer(Pipeline))
|
|
44
|
+
.pipe(Layer.provideMerge(Action.layerImplementations))
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use a retained provider. Supply the runtime and the adapter's services, including durable capture receipt
|
|
48
|
+
storage, to that layer. Declare the complete adapter failure union in `error`;
|
|
49
|
+
errors are encoded in durable action outcomes.
|
|
50
|
+
|
|
51
|
+
## Identity and replay
|
|
52
|
+
|
|
53
|
+
`Build.call` uses the existing child boundary, so each call has its own durable
|
|
54
|
+
execution identity. It does not inline the job into its caller. `.child` and
|
|
55
|
+
`.execute` also retain the ordinary flow APIs. Two calls with identical payloads
|
|
56
|
+
start separate jobs. `.execute` with the same execution id rejoins its lineage.
|
|
57
|
+
|
|
58
|
+
The initial action journals the enclosing job execution id and start time.
|
|
59
|
+
Adapters receive `<execution id>#g1`, then `#g2` for one allowed replacement.
|
|
60
|
+
The public payload cannot select an identity or supply a continuation handle.
|
|
61
|
+
`start` must atomically create-or-get by that key. Smithers replay alone cannot
|
|
62
|
+
make a provider's non-idempotent spawn safe.
|
|
63
|
+
|
|
64
|
+
Status actions have separate probe keys, while the provider receives the same
|
|
65
|
+
job key throughout one generation. Delays double from `probe.every` up to
|
|
66
|
+
`probe.max`, and stop at the original timeout deadline. That deadline is carried
|
|
67
|
+
through every generation and survives a host restart.
|
|
68
|
+
|
|
69
|
+
## Replacement and cancellation
|
|
70
|
+
|
|
71
|
+
Status returns `Running`, `Exited` with `exitCode`, or `Lost`. `Exited` calls
|
|
72
|
+
`collect`. A collected exit can fail with `ExternalJob.Again` to request a
|
|
73
|
+
replacement. Both Lost and Again complete Cancel before a durable backoff and
|
|
74
|
+
the next Start. A failed cancellation cannot launch another worker.
|
|
75
|
+
`Again` is a dependency fault if it escapes the replacement boundary. A flow's
|
|
76
|
+
own `DeadlineExceeded` is a policy fault: its elapsed deadline is terminal.
|
|
77
|
+
|
|
78
|
+
Exhaustion fails with `ExternalJobLost` (`infra`). Timeout completes Cancel and
|
|
79
|
+
fails with `ExternalJobTimedOut` (`dependency`). `restarts: 0`, the default,
|
|
80
|
+
permits only the first generation. Adapter infrastructure errors retain their
|
|
81
|
+
declared type and use the runtime's repeat-safe retry policy.
|
|
82
|
+
|
|
83
|
+
The actual flow scope retains `Flow.withRollback` cancellation. Timer parking,
|
|
84
|
+
replay and host release preserve the external worker. Explicit cancellation
|
|
85
|
+
cancels it, including a retained parked scope. The rollback is process-local;
|
|
86
|
+
providers still need their retained-machine lease or reaper after a host dies.
|