@temelj/workflow 0.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/attributes.d.mts +15 -0
- package/dist/attributes.mjs +30 -0
- package/dist/client/create.d.mts +31 -0
- package/dist/client/create.mjs +67 -0
- package/dist/client/facades.d.mts +21 -0
- package/dist/client/facades.mjs +142 -0
- package/dist/client/mod.d.mts +2 -0
- package/dist/client/mod.mjs +2 -0
- package/dist/client/run-handle.d.mts +66 -0
- package/dist/client/run-handle.mjs +156 -0
- package/dist/client/worker-options.d.mts +17 -0
- package/dist/client/worker-options.mjs +25 -0
- package/dist/collection.d.mts +15 -0
- package/dist/collection.mjs +33 -0
- package/dist/compiled-function.d.mts +27 -0
- package/dist/compiled-function.mjs +54 -0
- package/dist/definition.d.mts +37 -0
- package/dist/definition.mjs +83 -0
- package/dist/engine/child-workflow.d.mts +10 -0
- package/dist/engine/child-workflow.mjs +333 -0
- package/dist/engine/command-identity.d.mts +9 -0
- package/dist/engine/command-identity.mjs +14 -0
- package/dist/engine/create.d.mts +106 -0
- package/dist/engine/create.mjs +402 -0
- package/dist/engine/deterministic.d.mts +12 -0
- package/dist/engine/deterministic.mjs +102 -0
- package/dist/engine/durable-command.d.mts +10 -0
- package/dist/engine/durable-command.mjs +17 -0
- package/dist/engine/execution-api.d.mts +29 -0
- package/dist/engine/execution-api.mjs +33 -0
- package/dist/engine/execution-service.d.mts +41 -0
- package/dist/engine/execution-service.mjs +288 -0
- package/dist/engine/hooks.d.mts +56 -0
- package/dist/engine/hooks.mjs +237 -0
- package/dist/engine/inspection-api.d.mts +34 -0
- package/dist/engine/inspection-api.mjs +77 -0
- package/dist/engine/inspection.d.mts +18 -0
- package/dist/engine/inspection.mjs +149 -0
- package/dist/engine/lifecycle.d.mts +18 -0
- package/dist/engine/lifecycle.mjs +38 -0
- package/dist/engine/lock-replay.d.mts +30 -0
- package/dist/engine/lock-replay.mjs +38 -0
- package/dist/engine/lock.d.mts +21 -0
- package/dist/engine/lock.mjs +197 -0
- package/dist/engine/message.d.mts +47 -0
- package/dist/engine/message.mjs +357 -0
- package/dist/engine/mod.d.mts +4 -0
- package/dist/engine/mod.mjs +2 -0
- package/dist/engine/observation.d.mts +35 -0
- package/dist/engine/observation.mjs +201 -0
- package/dist/engine/recovery.d.mts +26 -0
- package/dist/engine/recovery.mjs +92 -0
- package/dist/engine/replay.d.mts +41 -0
- package/dist/engine/replay.mjs +122 -0
- package/dist/engine/retry-policy.d.mts +4 -0
- package/dist/engine/retry-policy.mjs +4 -0
- package/dist/engine/retry.d.mts +23 -0
- package/dist/engine/retry.mjs +75 -0
- package/dist/engine/run-data.d.mts +9 -0
- package/dist/engine/run-data.mjs +74 -0
- package/dist/engine/run-service.d.mts +38 -0
- package/dist/engine/run-service.mjs +133 -0
- package/dist/engine/run-utils.d.mts +16 -0
- package/dist/engine/run-utils.mjs +83 -0
- package/dist/engine/schedule.d.mts +25 -0
- package/dist/engine/schedule.mjs +207 -0
- package/dist/engine/serialization.d.mts +9 -0
- package/dist/engine/serialization.mjs +85 -0
- package/dist/engine/start-api.d.mts +30 -0
- package/dist/engine/start-api.mjs +98 -0
- package/dist/engine/state.d.mts +77 -0
- package/dist/engine/state.mjs +464 -0
- package/dist/engine/step-api.d.mts +9 -0
- package/dist/engine/step-api.mjs +25 -0
- package/dist/engine/stream.d.mts +55 -0
- package/dist/engine/stream.mjs +333 -0
- package/dist/engine/summary/active-events.d.mts +34 -0
- package/dist/engine/summary/active-events.mjs +69 -0
- package/dist/engine/summary/child-workflow-runs.d.mts +24 -0
- package/dist/engine/summary/child-workflow-runs.mjs +138 -0
- package/dist/engine/summary/child-workflow-waits.d.mts +21 -0
- package/dist/engine/summary/child-workflow-waits.mjs +67 -0
- package/dist/engine/summary/recovery-child-workflow-waits.d.mts +11 -0
- package/dist/engine/summary/recovery-child-workflow-waits.mjs +89 -0
- package/dist/engine/summary/recovery-due-runs.d.mts +16 -0
- package/dist/engine/summary/recovery-due-runs.mjs +52 -0
- package/dist/engine/summary/recovery-failed-runs.d.mts +14 -0
- package/dist/engine/summary/recovery-failed-runs.mjs +33 -0
- package/dist/engine/summary/recovery-lease-runs.d.mts +16 -0
- package/dist/engine/summary/recovery-lease-runs.mjs +69 -0
- package/dist/engine/summary/recovery-locks.d.mts +18 -0
- package/dist/engine/summary/recovery-locks.mjs +100 -0
- package/dist/engine/summary/recovery-message-waits.d.mts +11 -0
- package/dist/engine/summary/recovery-message-waits.mjs +74 -0
- package/dist/engine/summary/recovery-retry-runs.d.mts +17 -0
- package/dist/engine/summary/recovery-retry-runs.mjs +65 -0
- package/dist/engine/summary/recovery-run-timestamps.d.mts +13 -0
- package/dist/engine/summary/recovery-run-timestamps.mjs +18 -0
- package/dist/engine/summary/recovery-runs.d.mts +23 -0
- package/dist/engine/summary/recovery-runs.mjs +54 -0
- package/dist/engine/summary/recovery-schedules.d.mts +10 -0
- package/dist/engine/summary/recovery-schedules.mjs +46 -0
- package/dist/engine/summary/recovery-sleep-waits.d.mts +10 -0
- package/dist/engine/summary/recovery-sleep-waits.mjs +53 -0
- package/dist/engine/summary/recovery-waits.d.mts +21 -0
- package/dist/engine/summary/recovery-waits.mjs +29 -0
- package/dist/engine/summary/run-availability.d.mts +13 -0
- package/dist/engine/summary/run-availability.mjs +37 -0
- package/dist/engine/summary/run-cleanup.d.mts +14 -0
- package/dist/engine/summary/run-cleanup.mjs +44 -0
- package/dist/engine/summary/run-failure.d.mts +14 -0
- package/dist/engine/summary/run-failure.mjs +62 -0
- package/dist/engine/summary/run-hooks.d.mts +14 -0
- package/dist/engine/summary/run-hooks.mjs +63 -0
- package/dist/engine/summary/run-lease.d.mts +11 -0
- package/dist/engine/summary/run-lease.mjs +64 -0
- package/dist/engine/summary/run-message-waits.d.mts +15 -0
- package/dist/engine/summary/run-message-waits.mjs +62 -0
- package/dist/engine/summary/run-metrics.d.mts +31 -0
- package/dist/engine/summary/run-metrics.mjs +93 -0
- package/dist/engine/summary/run-retry.d.mts +9 -0
- package/dist/engine/summary/run-retry.mjs +69 -0
- package/dist/engine/summary/run-sleeps.d.mts +15 -0
- package/dist/engine/summary/run-sleeps.mjs +61 -0
- package/dist/engine/summary/run-state.d.mts +26 -0
- package/dist/engine/summary/run-state.mjs +48 -0
- package/dist/engine/summary/run-status.d.mts +16 -0
- package/dist/engine/summary/run-status.mjs +35 -0
- package/dist/engine/summary/run-streams.d.mts +14 -0
- package/dist/engine/summary/run-streams.mjs +46 -0
- package/dist/engine/summary/run-transition.d.mts +9 -0
- package/dist/engine/summary/run-transition.mjs +39 -0
- package/dist/engine/summary/run-workflow.d.mts +9 -0
- package/dist/engine/summary/run-workflow.mjs +47 -0
- package/dist/engine/summary/step-attempt-active-child-workflows.d.mts +13 -0
- package/dist/engine/summary/step-attempt-active-child-workflows.mjs +55 -0
- package/dist/engine/summary/step-attempt-active-fields.d.mts +23 -0
- package/dist/engine/summary/step-attempt-active-fields.mjs +14 -0
- package/dist/engine/summary/step-attempt-active-message-waits.d.mts +12 -0
- package/dist/engine/summary/step-attempt-active-message-waits.mjs +47 -0
- package/dist/engine/summary/step-attempt-active-sleeps.d.mts +19 -0
- package/dist/engine/summary/step-attempt-active-sleeps.mjs +44 -0
- package/dist/engine/summary/step-attempt-buckets.d.mts +22 -0
- package/dist/engine/summary/step-attempt-buckets.mjs +152 -0
- package/dist/engine/summary/step-attempt-failure.d.mts +12 -0
- package/dist/engine/summary/step-attempt-failure.mjs +61 -0
- package/dist/engine/summary/step-attempt-lifecycle.d.mts +13 -0
- package/dist/engine/summary/step-attempt-lifecycle.mjs +19 -0
- package/dist/engine/summary/step-attempts.d.mts +11 -0
- package/dist/engine/summary/step-attempts.mjs +43 -0
- package/dist/engine/summary.d.mts +32 -0
- package/dist/engine/summary.mjs +37 -0
- package/dist/engine/task.d.mts +6 -0
- package/dist/engine/task.mjs +207 -0
- package/dist/errors/base.d.mts +99 -0
- package/dist/errors/base.mjs +426 -0
- package/dist/errors/capability.d.mts +11 -0
- package/dist/errors/capability.mjs +23 -0
- package/dist/errors/definition.d.mts +21 -0
- package/dist/errors/definition.mjs +51 -0
- package/dist/errors/details.d.mts +13 -0
- package/dist/errors/details.mjs +65 -0
- package/dist/errors/failures.d.mts +81 -0
- package/dist/errors/failures.mjs +168 -0
- package/dist/errors/hook.d.mts +14 -0
- package/dist/errors/hook.mjs +30 -0
- package/dist/errors/implementation.d.mts +11 -0
- package/dist/errors/implementation.mjs +25 -0
- package/dist/errors/lock.d.mts +28 -0
- package/dist/errors/lock.mjs +70 -0
- package/dist/errors/message.d.mts +106 -0
- package/dist/errors/message.mjs +122 -0
- package/dist/errors/mod.d.mts +17 -0
- package/dist/errors/mod.mjs +17 -0
- package/dist/errors/record-view.d.mts +11 -0
- package/dist/errors/record-view.mjs +24 -0
- package/dist/errors/records.d.mts +7 -0
- package/dist/errors/records.mjs +280 -0
- package/dist/errors/run.d.mts +116 -0
- package/dist/errors/run.mjs +232 -0
- package/dist/errors/runtime.d.mts +12 -0
- package/dist/errors/runtime.mjs +24 -0
- package/dist/errors/schedule.d.mts +27 -0
- package/dist/errors/schedule.mjs +65 -0
- package/dist/errors/step.d.mts +76 -0
- package/dist/errors/step.mjs +113 -0
- package/dist/errors/stream.d.mts +24 -0
- package/dist/errors/stream.mjs +64 -0
- package/dist/esbuild.d.mts +7 -0
- package/dist/esbuild.mjs +6 -0
- package/dist/events/descriptors.d.mts +245 -0
- package/dist/events/descriptors.mjs +405 -0
- package/dist/events/mod.d.mts +3 -0
- package/dist/events/mod.mjs +2 -0
- package/dist/history/attempt-key.d.mts +6 -0
- package/dist/history/attempt-key.mjs +7 -0
- package/dist/history/mod.d.mts +71 -0
- package/dist/history/mod.mjs +195 -0
- package/dist/history/projection.d.mts +8 -0
- package/dist/history/projection.mjs +259 -0
- package/dist/history/replay-projection.d.mts +88 -0
- package/dist/history/replay-projection.mjs +369 -0
- package/dist/history/sequencer.d.mts +16 -0
- package/dist/history/sequencer.mjs +78 -0
- package/dist/history/step-attempts.d.mts +9 -0
- package/dist/history/step-attempts.mjs +50 -0
- package/dist/history/timeline.d.mts +16 -0
- package/dist/history/timeline.mjs +272 -0
- package/dist/history/validator.d.mts +9 -0
- package/dist/history/validator.mjs +110 -0
- package/dist/inspection/mod.d.mts +5 -0
- package/dist/inspection/mod.mjs +3 -0
- package/dist/message-options.d.mts +8 -0
- package/dist/message-options.mjs +25 -0
- package/dist/mod.d.mts +52 -0
- package/dist/mod.mjs +26 -0
- package/dist/otel/support.d.mts +18 -0
- package/dist/otel/support.mjs +102 -0
- package/dist/otel.d.mts +30 -0
- package/dist/otel.mjs +588 -0
- package/dist/pagination.d.mts +25 -0
- package/dist/pagination.mjs +73 -0
- package/dist/registry.d.mts +20 -0
- package/dist/registry.mjs +48 -0
- package/dist/rolldown.d.mts +7 -0
- package/dist/rolldown.mjs +6 -0
- package/dist/rollup.d.mts +7 -0
- package/dist/rollup.mjs +6 -0
- package/dist/rspack.d.mts +7 -0
- package/dist/rspack.mjs +6 -0
- package/dist/runtime.d.mts +34 -0
- package/dist/runtime.mjs +194 -0
- package/dist/step-definition.d.mts +10 -0
- package/dist/step-definition.mjs +15 -0
- package/dist/store/append-projection.d.mts +15 -0
- package/dist/store/append-projection.mjs +26 -0
- package/dist/store/capabilities.d.mts +14 -0
- package/dist/store/capabilities.mjs +42 -0
- package/dist/store/cleanup.d.mts +18 -0
- package/dist/store/cleanup.mjs +338 -0
- package/dist/store/compaction.d.mts +5 -0
- package/dist/store/compaction.mjs +8 -0
- package/dist/store/create.d.mts +52 -0
- package/dist/store/create.mjs +159 -0
- package/dist/store/event-append-project.d.mts +15 -0
- package/dist/store/event-append-project.mjs +77 -0
- package/dist/store/event-append.d.mts +37 -0
- package/dist/store/event-append.mjs +80 -0
- package/dist/store/event-history.d.mts +22 -0
- package/dist/store/event-history.mjs +75 -0
- package/dist/store/event.d.mts +10 -0
- package/dist/store/event.mjs +28 -0
- package/dist/store/idempotency.d.mts +10 -0
- package/dist/store/idempotency.mjs +167 -0
- package/dist/store/instrumentation.d.mts +7 -0
- package/dist/store/instrumentation.mjs +123 -0
- package/dist/store/lock.d.mts +8 -0
- package/dist/store/lock.mjs +28 -0
- package/dist/store/materialization.d.mts +30 -0
- package/dist/store/materialization.mjs +127 -0
- package/dist/store/message-index.d.mts +21 -0
- package/dist/store/message-index.mjs +121 -0
- package/dist/store/mod.d.mts +5 -0
- package/dist/store/mod.mjs +4 -0
- package/dist/store/query.d.mts +24 -0
- package/dist/store/query.mjs +82 -0
- package/dist/store/revision.d.mts +4 -0
- package/dist/store/revision.mjs +7 -0
- package/dist/store/run.d.mts +49 -0
- package/dist/store/run.mjs +236 -0
- package/dist/store/schedule.d.mts +12 -0
- package/dist/store/schedule.mjs +41 -0
- package/dist/store/schema.d.mts +14 -0
- package/dist/store/schema.mjs +17 -0
- package/dist/store/step-attempt.d.mts +14 -0
- package/dist/store/step-attempt.mjs +23 -0
- package/dist/store/storage-value.d.mts +5 -0
- package/dist/store/storage-value.mjs +6 -0
- package/dist/store/validation.d.mts +35 -0
- package/dist/store/validation.mjs +77 -0
- package/dist/store-keys.d.mts +49 -0
- package/dist/store-keys.mjs +63 -0
- package/dist/telemetry.d.mts +132 -0
- package/dist/telemetry.mjs +172 -0
- package/dist/temporal.d.mts +23 -0
- package/dist/temporal.mjs +59 -0
- package/dist/timer.d.mts +12 -0
- package/dist/timer.mjs +28 -0
- package/dist/types/cleanup.d.mts +112 -0
- package/dist/types/cleanup.mjs +22 -0
- package/dist/types/client.d.mts +270 -0
- package/dist/types/client.mjs +1 -0
- package/dist/types/common.d.mts +19 -0
- package/dist/types/common.mjs +15 -0
- package/dist/types/definition.d.mts +92 -0
- package/dist/types/definition.mjs +1 -0
- package/dist/types/engine-options.d.mts +76 -0
- package/dist/types/engine-options.mjs +1 -0
- package/dist/types/engine.d.mts +309 -0
- package/dist/types/engine.mjs +1 -0
- package/dist/types/error-code.d.mts +256 -0
- package/dist/types/error-code.mjs +131 -0
- package/dist/types/error.d.mts +236 -0
- package/dist/types/error.mjs +48 -0
- package/dist/types/events.d.mts +2869 -0
- package/dist/types/events.mjs +283 -0
- package/dist/types/hook.d.mts +149 -0
- package/dist/types/hook.mjs +66 -0
- package/dist/types/lock.d.mts +63 -0
- package/dist/types/lock.mjs +18 -0
- package/dist/types/message-id.d.mts +7 -0
- package/dist/types/message-id.mjs +5 -0
- package/dist/types/message.d.mts +87 -0
- package/dist/types/message.mjs +1 -0
- package/dist/types/observation.d.mts +146 -0
- package/dist/types/observation.mjs +1 -0
- package/dist/types/pagination.d.mts +32 -0
- package/dist/types/pagination.mjs +13 -0
- package/dist/types/result.d.mts +62 -0
- package/dist/types/result.mjs +1 -0
- package/dist/types/retry.d.mts +48 -0
- package/dist/types/retry.mjs +1 -0
- package/dist/types/run-id.d.mts +7 -0
- package/dist/types/run-id.mjs +5 -0
- package/dist/types/run-list.d.mts +43 -0
- package/dist/types/run-list.mjs +1 -0
- package/dist/types/run-options.d.mts +86 -0
- package/dist/types/run-options.mjs +1 -0
- package/dist/types/run.d.mts +355 -0
- package/dist/types/run.mjs +207 -0
- package/dist/types/runtime.d.mts +143 -0
- package/dist/types/runtime.mjs +21 -0
- package/dist/types/schedule.d.mts +127 -0
- package/dist/types/schedule.mjs +48 -0
- package/dist/types/step-attempts.d.mts +326 -0
- package/dist/types/step-attempts.mjs +43 -0
- package/dist/types/step-id.d.mts +7 -0
- package/dist/types/step-id.mjs +5 -0
- package/dist/types/step.d.mts +183 -0
- package/dist/types/step.mjs +5 -0
- package/dist/types/store.d.mts +254 -0
- package/dist/types/store.mjs +1 -0
- package/dist/types/stream-id.d.mts +7 -0
- package/dist/types/stream-id.mjs +5 -0
- package/dist/types/stream.d.mts +126 -0
- package/dist/types/stream.mjs +1 -0
- package/dist/types/summary.d.mts +318 -0
- package/dist/types/summary.mjs +1 -0
- package/dist/types/telemetry.d.mts +74 -0
- package/dist/types/telemetry.mjs +9 -0
- package/dist/types/timeline.d.mts +237 -0
- package/dist/types/timeline.mjs +1 -0
- package/dist/types/vite.d.mts +65 -0
- package/dist/types/vite.mjs +1 -0
- package/dist/types/worker-id.d.mts +7 -0
- package/dist/types/worker-id.mjs +5 -0
- package/dist/types/worker.d.mts +94 -0
- package/dist/types/worker.mjs +1 -0
- package/dist/utility.d.mts +49 -0
- package/dist/utility.mjs +122 -0
- package/dist/vite/ast.d.mts +23 -0
- package/dist/vite/ast.mjs +73 -0
- package/dist/vite/error.d.mts +19 -0
- package/dist/vite/error.mjs +47 -0
- package/dist/vite/generated-name.d.mts +7 -0
- package/dist/vite/generated-name.mjs +9 -0
- package/dist/vite/manifest.d.mts +7 -0
- package/dist/vite/manifest.mjs +106 -0
- package/dist/vite/plugin.d.mts +7 -0
- package/dist/vite/plugin.mjs +190 -0
- package/dist/vite/safety.d.mts +12 -0
- package/dist/vite/safety.mjs +96 -0
- package/dist/vite/source-edit.d.mts +12 -0
- package/dist/vite/source-edit.mjs +44 -0
- package/dist/vite/source-map.d.mts +11 -0
- package/dist/vite/source-map.mjs +53 -0
- package/dist/vite/source.d.mts +7 -0
- package/dist/vite/source.mjs +14 -0
- package/dist/vite/transform.d.mts +7 -0
- package/dist/vite/transform.mjs +405 -0
- package/dist/vite.d.mts +6 -0
- package/dist/vite.mjs +5 -0
- package/dist/webhook.d.mts +16 -0
- package/dist/webhook.mjs +17 -0
- package/dist/webpack.d.mts +7 -0
- package/dist/webpack.mjs +6 -0
- package/dist/worker/error.d.mts +11 -0
- package/dist/worker/error.mjs +40 -0
- package/dist/worker.d.mts +18 -0
- package/dist/worker.mjs +427 -0
- package/package.json +144 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { normalizeWorkflowAttributePatch, workflowAttributeEventPatch, workflowAttributePatchFromEvent } from "../attributes.mjs";
|
|
2
|
+
import { toPersistedValue } from "./serialization.mjs";
|
|
3
|
+
import { WorkflowStaleExecutionError, appendEventIfCurrentExecution, patchCurrentExecutionRun, patchCurrentExecutionRunAttributes } from "./state.mjs";
|
|
4
|
+
import { resolveWorkflowCommandIdentity } from "./command-identity.mjs";
|
|
5
|
+
import { requireAttributesReplayMatches, requireMetadataReplayMatches } from "./replay.mjs";
|
|
6
|
+
//#region src/engine/run-data.ts
|
|
7
|
+
function createWorkflowRunDataApi(environment) {
|
|
8
|
+
return {
|
|
9
|
+
async setMetadata(commandId, metadata) {
|
|
10
|
+
await setWorkflowRunMetadata(environment, commandId, metadata);
|
|
11
|
+
},
|
|
12
|
+
async setAttributes(commandId, attributes) {
|
|
13
|
+
await setWorkflowRunAttributes(environment, commandId, attributes);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async function setWorkflowRunMetadata(environment, commandId, metadata) {
|
|
18
|
+
const { store, runId, history, now, limits, executionOwner } = environment;
|
|
19
|
+
const identity = resolveWorkflowCommandIdentity(history, "metadata", commandId);
|
|
20
|
+
const persistedMetadata = toPersistedValue(metadata, "workflow run metadata", limits);
|
|
21
|
+
const recorded = history.metadataSet(identity.id);
|
|
22
|
+
if (recorded !== void 0) {
|
|
23
|
+
requireMetadataReplayMatches(identity, recorded, persistedMetadata);
|
|
24
|
+
const updated = await patchCurrentExecutionRun(store, executionOwner, {
|
|
25
|
+
metadata: recorded.metadata,
|
|
26
|
+
updatedAt: recorded.timestamp
|
|
27
|
+
});
|
|
28
|
+
if (updated === void 0) WorkflowStaleExecutionError.stale(executionOwner.id);
|
|
29
|
+
Object.assign(executionOwner, updated);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const timestamp = now();
|
|
33
|
+
await appendEventIfCurrentExecution(store, history, {
|
|
34
|
+
kind: "metadata_set",
|
|
35
|
+
timestamp,
|
|
36
|
+
stepId: identity.id,
|
|
37
|
+
stepName: identity.name,
|
|
38
|
+
count: identity.count,
|
|
39
|
+
metadata: persistedMetadata
|
|
40
|
+
}, executionOwner, limits, void 0, (event, events) => environment.observeDurableEventAppended?.(runId, event, events));
|
|
41
|
+
const updated = await patchCurrentExecutionRun(store, executionOwner, {
|
|
42
|
+
metadata: persistedMetadata,
|
|
43
|
+
updatedAt: timestamp
|
|
44
|
+
});
|
|
45
|
+
if (updated === void 0) WorkflowStaleExecutionError.stale(executionOwner.id);
|
|
46
|
+
Object.assign(executionOwner, updated);
|
|
47
|
+
}
|
|
48
|
+
async function setWorkflowRunAttributes(environment, commandId, attributes) {
|
|
49
|
+
const { store, runId, history, now, limits, executionOwner } = environment;
|
|
50
|
+
const identity = resolveWorkflowCommandIdentity(history, "attributes", commandId);
|
|
51
|
+
const normalized = normalizeWorkflowAttributePatch(attributes);
|
|
52
|
+
const recorded = history.attributesSet(identity.id);
|
|
53
|
+
if (recorded !== void 0) {
|
|
54
|
+
requireAttributesReplayMatches(identity, recorded, normalized);
|
|
55
|
+
const updated = await patchCurrentExecutionRunAttributes(store, executionOwner, workflowAttributePatchFromEvent(recorded), recorded.timestamp);
|
|
56
|
+
if (updated === void 0) WorkflowStaleExecutionError.stale(executionOwner.id);
|
|
57
|
+
Object.assign(executionOwner, updated);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const timestamp = now();
|
|
61
|
+
await appendEventIfCurrentExecution(store, history, {
|
|
62
|
+
kind: "attributes_set",
|
|
63
|
+
timestamp,
|
|
64
|
+
stepId: identity.id,
|
|
65
|
+
stepName: identity.name,
|
|
66
|
+
count: identity.count,
|
|
67
|
+
...workflowAttributeEventPatch(normalized)
|
|
68
|
+
}, executionOwner, limits, void 0, (event, events) => environment.observeDurableEventAppended?.(runId, event, events));
|
|
69
|
+
const updated = await patchCurrentExecutionRunAttributes(store, executionOwner, normalized, timestamp);
|
|
70
|
+
if (updated === void 0) WorkflowStaleExecutionError.stale(executionOwner.id);
|
|
71
|
+
Object.assign(executionOwner, updated);
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { createWorkflowRunDataApi, setWorkflowRunAttributes, setWorkflowRunMetadata };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { RunId } from "../types/run-id.mjs";
|
|
2
|
+
import { WorkflowDefinition } from "../types/definition.mjs";
|
|
3
|
+
import { WorkflowHandle } from "../types/result.mjs";
|
|
4
|
+
import { WorkflowAttributePatch, WorkflowRunRecord, WorkflowRunWorkflowName, WorkflowRunWorkflowVersion } from "../types/run.mjs";
|
|
5
|
+
import { WorkflowMarkRunPermanentlyFailedOptions, WorkflowReleaseStaleLeaseOptions, WorkflowRerunOptions, WorkflowRescheduleRunOptions, WorkflowRetryFailedRunOptions, WorkflowStartOptions } from "../types/run-options.mjs";
|
|
6
|
+
import { WorkflowEventReader, WorkflowLockConditionalWriterRepository, WorkflowLockListerRepository, WorkflowRunReaderRepository, WorkflowRunWriterRepository, WorkflowStepAttemptLookup } from "../types/store.mjs";
|
|
7
|
+
//#region src/engine/run-service.d.ts
|
|
8
|
+
type WorkflowRunServiceStore = WorkflowRunReaderRepository & WorkflowRunWriterRepository & WorkflowEventReader & WorkflowStepAttemptLookup & WorkflowLockListerRepository & WorkflowLockConditionalWriterRepository;
|
|
9
|
+
interface WorkflowRunServiceOptions {
|
|
10
|
+
readonly store: WorkflowRunServiceStore;
|
|
11
|
+
readonly now: () => Temporal.Instant;
|
|
12
|
+
readonly limits: {
|
|
13
|
+
readonly maximumPersistedValueBytes?: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
interface WorkflowRunLifecycleEmitter {
|
|
17
|
+
readonly emitLifecycleEvent: (next: WorkflowRunRecord, previous: WorkflowRunRecord) => void | Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
interface WorkflowRunMetadataUpdateEmitter {
|
|
20
|
+
readonly emitRunMetadataUpdated: (next: WorkflowRunRecord, previous: WorkflowRunRecord) => void;
|
|
21
|
+
}
|
|
22
|
+
declare function rerunWorkflowRun(service: WorkflowRunServiceOptions, startWorkflow: <TOutput = unknown>(definition: WorkflowDefinition<unknown, TOutput, unknown>, input: unknown, options?: WorkflowStartOptions) => Promise<WorkflowHandle<TOutput>>, runId: RunId, rerunOptions: WorkflowRerunOptions | undefined): Promise<WorkflowHandle<unknown>>;
|
|
23
|
+
declare function resolveRerunWorkflowDefinition(sourceRun: WorkflowRerunSourceRun, options: WorkflowRerunOptions | undefined): Promise<WorkflowDefinition<unknown, unknown, unknown>>;
|
|
24
|
+
interface WorkflowRerunSourceRun {
|
|
25
|
+
readonly workflowName: WorkflowRunWorkflowName;
|
|
26
|
+
readonly workflowVersion?: WorkflowRunWorkflowVersion;
|
|
27
|
+
}
|
|
28
|
+
declare function rescheduleWorkflowRun(service: WorkflowRunServiceOptions, lifecycle: WorkflowRunLifecycleEmitter, runId: RunId, rescheduleOptions: WorkflowRescheduleRunOptions | undefined): Promise<WorkflowRunRecord>;
|
|
29
|
+
declare function releaseStaleWorkflowRunLease(service: WorkflowRunServiceOptions, lifecycle: WorkflowRunLifecycleEmitter, runId: RunId, releaseOptions: WorkflowReleaseStaleLeaseOptions | undefined): Promise<WorkflowRunRecord>;
|
|
30
|
+
declare function retryFailedWorkflowRun(service: WorkflowRunServiceOptions, lifecycle: WorkflowRunLifecycleEmitter, runId: RunId, retryOptions: WorkflowRetryFailedRunOptions | undefined): Promise<WorkflowRunRecord>;
|
|
31
|
+
declare function markWorkflowRunPermanentlyFailed(service: WorkflowRunServiceOptions, lifecycle: WorkflowRunLifecycleEmitter, runId: RunId, permanentFailureOptions: WorkflowMarkRunPermanentlyFailedOptions): Promise<WorkflowRunRecord>;
|
|
32
|
+
declare function updateWorkflowRunMetadata(service: WorkflowRunServiceOptions, lifecycle: WorkflowRunMetadataUpdateEmitter, runId: RunId, metadata: unknown): Promise<WorkflowRunRecord>;
|
|
33
|
+
declare function setWorkflowRunAttributes(service: WorkflowRunServiceOptions, runId: RunId, attributes: WorkflowAttributePatch): Promise<WorkflowRunRecord>;
|
|
34
|
+
declare function cancelWorkflowRun(service: WorkflowRunServiceOptions, lifecycle: WorkflowRunLifecycleEmitter, runId: RunId): Promise<WorkflowRunRecord>;
|
|
35
|
+
declare function resolveWorkflowVersion(workflowName: string, fallbackVersion: string | undefined, resolver: ((workflowName: string, definition: WorkflowDefinition<unknown, unknown, unknown>) => string | undefined | Promise<string | undefined>) | undefined): Promise<string | undefined>;
|
|
36
|
+
declare function resolveWorkflowStartSpec<TInput, TOutput, TRawInput>(definition: WorkflowDefinition<TInput, TOutput, TRawInput>, options: WorkflowStartOptions | undefined): Promise<WorkflowDefinition<TInput, TOutput, TRawInput>>;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { cancelWorkflowRun, markWorkflowRunPermanentlyFailed, releaseStaleWorkflowRunLease, rerunWorkflowRun, rescheduleWorkflowRun, resolveRerunWorkflowDefinition, resolveWorkflowStartSpec, resolveWorkflowVersion, retryFailedWorkflowRun, setWorkflowRunAttributes, updateWorkflowRunMetadata };
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { WorkflowStateError } from "../errors/base.mjs";
|
|
2
|
+
import { WorkflowPermanentFailureError } from "../errors/failures.mjs";
|
|
3
|
+
import { getRequiredRun, isScheduledWorkflowRunStatus, nextRunAttempt } from "../utility.mjs";
|
|
4
|
+
import { normalizeWorkflowAttributePatch } from "../attributes.mjs";
|
|
5
|
+
import "../errors/mod.mjs";
|
|
6
|
+
import { defineWorkflowFromName } from "../definition.mjs";
|
|
7
|
+
import "./retry-policy.mjs";
|
|
8
|
+
import { serializeError, toPersistedValue } from "./serialization.mjs";
|
|
9
|
+
import { cancelRunWithChildren, releaseLocksForRun, setRunAttributesIfCurrent, transitionRunAfterStaleLeaseRelease, transitionRunToManualRetry, transitionRunToPermanentFailure, transitionRunToRescheduled, updateRunMetadataIfCurrent } from "./state.mjs";
|
|
10
|
+
//#region src/engine/run-service.ts
|
|
11
|
+
async function rerunWorkflowRun(service, startWorkflow, runId, rerunOptions) {
|
|
12
|
+
const sourceRun = await getRequiredRun(service.store, runId);
|
|
13
|
+
const options = rerunOptions;
|
|
14
|
+
const definition = await resolveRerunWorkflowDefinition(sourceRun, options);
|
|
15
|
+
const start = options?.start;
|
|
16
|
+
return await startWorkflow(definition, sourceRun.input, {
|
|
17
|
+
...sourceRun.context === void 0 ? {} : { context: sourceRun.context },
|
|
18
|
+
...start
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async function resolveRerunWorkflowDefinition(sourceRun, options) {
|
|
22
|
+
const workflowName = options?.workflowName ?? sourceRun.workflowName;
|
|
23
|
+
return defineWorkflowFromName(workflowName, await resolveWorkflowVersion(workflowName, options !== void 0 && "workflowVersion" in options ? options.workflowVersion : sourceRun.workflowVersion, options?.workflowVersionResolver));
|
|
24
|
+
}
|
|
25
|
+
async function rescheduleWorkflowRun(service, lifecycle, runId, rescheduleOptions) {
|
|
26
|
+
const options = rescheduleOptions;
|
|
27
|
+
const now = service.now();
|
|
28
|
+
const availableAt = options?.availableAt ?? now;
|
|
29
|
+
for (let attempt = 0; attempt < 16; attempt++) {
|
|
30
|
+
const current = await getRequiredRun(service.store, runId);
|
|
31
|
+
if (!isScheduledWorkflowRunStatus(current.status)) WorkflowStateError.runCannotBeRescheduled(runId);
|
|
32
|
+
if (current.availableAt !== void 0 && Temporal.Instant.compare(current.availableAt, availableAt) === 0 && current.lastTransitionReason === "rescheduled") return current;
|
|
33
|
+
const updated = await service.store.updateRunIfCurrent(current, transitionRunToRescheduled(current, now, availableAt));
|
|
34
|
+
if (updated !== void 0) {
|
|
35
|
+
await releaseLocksForRun(service.store, updated.id, now);
|
|
36
|
+
await lifecycle.emitLifecycleEvent(updated, current);
|
|
37
|
+
return updated;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
WorkflowStateError.failedRunReschedule(runId);
|
|
41
|
+
}
|
|
42
|
+
async function releaseStaleWorkflowRunLease(service, lifecycle, runId, releaseOptions) {
|
|
43
|
+
const options = releaseOptions;
|
|
44
|
+
const now = service.now();
|
|
45
|
+
const availableAt = options?.availableAt ?? now;
|
|
46
|
+
for (let attempt = 0; attempt < 16; attempt++) {
|
|
47
|
+
const current = await getRequiredRun(service.store, runId);
|
|
48
|
+
if (isScheduledWorkflowRunStatus(current.status)) return current;
|
|
49
|
+
if (current.status !== "running") WorkflowStateError.staleLeaseReleaseRequiresRunning(runId);
|
|
50
|
+
if (current.workerId !== void 0 && typeof current.workerId === "string" && current.workerId.trim() !== "" && current.leaseExpiresAt !== void 0 && Temporal.Instant.compare(current.leaseExpiresAt, now) > 0) WorkflowStateError.runLeaseStillActive(runId);
|
|
51
|
+
const updated = await service.store.updateRunIfCurrent(current, transitionRunAfterStaleLeaseRelease(current, now, availableAt));
|
|
52
|
+
if (updated !== void 0) {
|
|
53
|
+
await lifecycle.emitLifecycleEvent(updated, current);
|
|
54
|
+
return updated;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
WorkflowStateError.failedStaleRunLeaseRelease(runId);
|
|
58
|
+
}
|
|
59
|
+
async function retryFailedWorkflowRun(service, lifecycle, runId, retryOptions) {
|
|
60
|
+
const options = retryOptions;
|
|
61
|
+
const now = service.now();
|
|
62
|
+
const availableAt = options?.availableAt ?? now;
|
|
63
|
+
for (let attempt = 0; attempt < 16; attempt++) {
|
|
64
|
+
const current = await getRequiredRun(service.store, runId);
|
|
65
|
+
if (isScheduledWorkflowRunStatus(current.status)) return current;
|
|
66
|
+
if (current.status !== "failed") WorkflowStateError.runRetryRequiresFailed(runId);
|
|
67
|
+
if (current.lastTransitionReason === "permanent_failure" && options?.force !== true) WorkflowStateError.runRetryRequiresForceAfterPermanentFailure(runId);
|
|
68
|
+
if (options?.force !== true && current.retryReason === void 0 && current.retryAt === void 0) WorkflowStateError.failedRunRetryRequiresForce(runId);
|
|
69
|
+
const retryAttempt = nextRunAttempt(current.retryAttempt);
|
|
70
|
+
const updated = await service.store.updateRunIfCurrent(current, transitionRunToManualRetry(current, now, availableAt, retryAttempt));
|
|
71
|
+
if (updated !== void 0) {
|
|
72
|
+
await lifecycle.emitLifecycleEvent(updated, current);
|
|
73
|
+
return updated;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
WorkflowStateError.failedRunRetry(runId);
|
|
77
|
+
}
|
|
78
|
+
async function markWorkflowRunPermanentlyFailed(service, lifecycle, runId, permanentFailureOptions) {
|
|
79
|
+
const now = service.now();
|
|
80
|
+
const reason = permanentFailureOptions.reason;
|
|
81
|
+
for (let attempt = 0; attempt < 16; attempt++) {
|
|
82
|
+
const current = await getRequiredRun(service.store, runId);
|
|
83
|
+
if (current.status === "completed" || current.status === "canceled") WorkflowStateError.permanentFailureInvalidStatus(runId, current.status);
|
|
84
|
+
if (current.status === "failed" && current.lastTransitionReason === "permanent_failure" && current.error?.details?.reason === reason) return current;
|
|
85
|
+
const updated = await service.store.updateRunIfCurrent(current, transitionRunToPermanentFailure(current, serializeError(WorkflowPermanentFailureError.create({
|
|
86
|
+
runId,
|
|
87
|
+
reason
|
|
88
|
+
})), now));
|
|
89
|
+
if (updated !== void 0) {
|
|
90
|
+
await lifecycle.emitLifecycleEvent(updated, current);
|
|
91
|
+
return updated;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
WorkflowStateError.failedPermanentRunFailure(runId);
|
|
95
|
+
}
|
|
96
|
+
async function updateWorkflowRunMetadata(service, lifecycle, runId, metadata) {
|
|
97
|
+
const persistedMetadata = toPersistedValue(metadata, "workflow run metadata", service.limits);
|
|
98
|
+
const timestamp = service.now();
|
|
99
|
+
const previousRun = await getRequiredRun(service.store, runId);
|
|
100
|
+
const updatedRun = await updateRunMetadataIfCurrent(service.store, runId, persistedMetadata, timestamp);
|
|
101
|
+
lifecycle.emitRunMetadataUpdated(updatedRun, previousRun);
|
|
102
|
+
return updatedRun;
|
|
103
|
+
}
|
|
104
|
+
async function setWorkflowRunAttributes(service, runId, attributes) {
|
|
105
|
+
const normalized = normalizeWorkflowAttributePatch(attributes);
|
|
106
|
+
const timestamp = service.now();
|
|
107
|
+
return await setRunAttributesIfCurrent(service.store, runId, normalized, timestamp);
|
|
108
|
+
}
|
|
109
|
+
async function cancelWorkflowRun(service, lifecycle, runId) {
|
|
110
|
+
const previousRun = await getRequiredRun(service.store, runId);
|
|
111
|
+
const canceledRun = await cancelRunWithChildren(service.store, runId, service.now());
|
|
112
|
+
if (previousRun.status !== "canceled") await lifecycle.emitLifecycleEvent(canceledRun, previousRun);
|
|
113
|
+
return canceledRun;
|
|
114
|
+
}
|
|
115
|
+
async function resolveWorkflowVersion(workflowName, fallbackVersion, resolver) {
|
|
116
|
+
if (resolver === void 0) return fallbackVersion;
|
|
117
|
+
const resolved = await resolver(workflowName, defineWorkflowFromName(workflowName, fallbackVersion));
|
|
118
|
+
return typeof resolved === "string" && resolved.trim() !== "" ? resolved : fallbackVersion;
|
|
119
|
+
}
|
|
120
|
+
async function resolveWorkflowStartSpec(definition, options) {
|
|
121
|
+
const version = await resolveWorkflowVersion(definition.name, options?.workflowVersion ?? definition.version, options?.workflowVersionResolver);
|
|
122
|
+
if (version === definition.version) return definition;
|
|
123
|
+
return {
|
|
124
|
+
...definition,
|
|
125
|
+
version,
|
|
126
|
+
config: {
|
|
127
|
+
...definition.config,
|
|
128
|
+
...version === void 0 ? { version: void 0 } : { version }
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
export { cancelWorkflowRun, markWorkflowRunPermanentlyFailed, releaseStaleWorkflowRunLease, rerunWorkflowRun, rescheduleWorkflowRun, resolveRerunWorkflowDefinition, resolveWorkflowStartSpec, resolveWorkflowVersion, retryFailedWorkflowRun, setWorkflowRunAttributes, updateWorkflowRunMetadata };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RunId } from "../types/run-id.mjs";
|
|
2
|
+
import { CleanupRunsOptions, RetentionPolicyOptions } from "../types/cleanup.mjs";
|
|
3
|
+
import { WorkflowDefinition } from "../types/definition.mjs";
|
|
4
|
+
import { CompletedResult, ExecutionResult, HandleOperations, WorkflowHandle } from "../types/result.mjs";
|
|
5
|
+
import { WorkflowRunRecord } from "../types/run.mjs";
|
|
6
|
+
import { WorkflowEventReader, WorkflowRunReaderRepository } from "../types/store.mjs";
|
|
7
|
+
//#region src/engine/run-utils.d.ts
|
|
8
|
+
type WorkflowRunLookup = WorkflowRunReaderRepository;
|
|
9
|
+
type WorkflowHandleStore = WorkflowRunLookup & WorkflowEventReader;
|
|
10
|
+
declare function retentionCleanupOptions(options: RetentionPolicyOptions, engineNow: () => Temporal.Instant): CleanupRunsOptions;
|
|
11
|
+
declare function workflowHandle<TOutput>(store: WorkflowHandleStore, definition: WorkflowDefinition<unknown, TOutput>, runId: RunId, now: () => Temporal.Instant, operations: HandleOperations): WorkflowHandle<TOutput>;
|
|
12
|
+
declare function readRunResult<TOutput>(store: WorkflowRunLookup, runId: RunId, fallbackAvailableAt: Temporal.Instant): Promise<ExecutionResult<TOutput>>;
|
|
13
|
+
declare function makeCompletedRunResult<TOutput>(run: WorkflowRunRecord): CompletedResult<TOutput>;
|
|
14
|
+
declare function makeCanceledRunResult<TOutput>(run: WorkflowRunRecord): ExecutionResult<TOutput>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { makeCanceledRunResult, makeCompletedRunResult, readRunResult, retentionCleanupOptions, workflowHandle };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { WorkflowRunCanceledError } from "../errors/run.mjs";
|
|
2
|
+
import { getRequiredRun } from "../utility.mjs";
|
|
3
|
+
import "../errors/mod.mjs";
|
|
4
|
+
import { serializeError } from "./serialization.mjs";
|
|
5
|
+
//#region src/engine/run-utils.ts
|
|
6
|
+
function retentionCleanupOptions(options, engineNow) {
|
|
7
|
+
return {
|
|
8
|
+
finishedAtBefore: (options.now === void 0 ? engineNow() : options.now).toZonedDateTimeISO("UTC").subtract(options.olderThan).toInstant(),
|
|
9
|
+
...options.status === void 0 ? {} : { status: options.status },
|
|
10
|
+
...options.workflowName === void 0 ? {} : { workflowName: options.workflowName },
|
|
11
|
+
...options.workflowVersion === void 0 ? {} : { workflowVersion: options.workflowVersion },
|
|
12
|
+
...options.idempotencyKey === void 0 ? {} : { idempotencyKey: options.idempotencyKey },
|
|
13
|
+
...options.parentRunId === void 0 ? {} : { parentRunId: options.parentRunId },
|
|
14
|
+
...options.parentStepId === void 0 ? {} : { parentStepId: options.parentStepId },
|
|
15
|
+
...options.parentStepName === void 0 ? {} : { parentStepName: options.parentStepName },
|
|
16
|
+
...options.parentStepAttempt === void 0 ? {} : { parentStepAttempt: options.parentStepAttempt },
|
|
17
|
+
...options.dryRun === void 0 ? {} : { dryRun: options.dryRun },
|
|
18
|
+
...options.limit === void 0 ? {} : { limit: options.limit }
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function workflowHandle(store, definition, runId, now, operations) {
|
|
22
|
+
return {
|
|
23
|
+
runId,
|
|
24
|
+
workflowName: definition.name,
|
|
25
|
+
...definition.version === void 0 ? {} : { workflowVersion: definition.version },
|
|
26
|
+
async getRun() {
|
|
27
|
+
return await getRequiredRun(store, runId);
|
|
28
|
+
},
|
|
29
|
+
async status() {
|
|
30
|
+
return (await getRequiredRun(store, runId)).status;
|
|
31
|
+
},
|
|
32
|
+
async events() {
|
|
33
|
+
return await store.getEvents(runId);
|
|
34
|
+
},
|
|
35
|
+
async timeline() {
|
|
36
|
+
return await operations.getTimeline(runId);
|
|
37
|
+
},
|
|
38
|
+
result: async () => await readRunResult(store, runId, now()),
|
|
39
|
+
async setMetadata(metadata) {
|
|
40
|
+
return await operations.setMetadata(runId, metadata);
|
|
41
|
+
},
|
|
42
|
+
async setAttributes(attributes) {
|
|
43
|
+
return await operations.setAttributes(runId, attributes);
|
|
44
|
+
},
|
|
45
|
+
async cancel() {
|
|
46
|
+
return await operations.cancel(runId);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function readRunResult(store, runId, fallbackAvailableAt) {
|
|
51
|
+
const run = await getRequiredRun(store, runId);
|
|
52
|
+
if (run.status === "completed") return makeCompletedRunResult(run);
|
|
53
|
+
if (run.status === "failed") return {
|
|
54
|
+
kind: "failed",
|
|
55
|
+
run,
|
|
56
|
+
error: run.error ?? {
|
|
57
|
+
name: "WorkflowError",
|
|
58
|
+
message: `Workflow run failed: ${runId}`
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
if (run.status === "canceled") return makeCanceledRunResult(run);
|
|
62
|
+
return {
|
|
63
|
+
kind: "waiting",
|
|
64
|
+
run,
|
|
65
|
+
availableAt: run.availableAt ?? fallbackAvailableAt
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function makeCompletedRunResult(run) {
|
|
69
|
+
return {
|
|
70
|
+
kind: "completed",
|
|
71
|
+
run,
|
|
72
|
+
output: run.output
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function makeCanceledRunResult(run) {
|
|
76
|
+
return {
|
|
77
|
+
kind: "failed",
|
|
78
|
+
run,
|
|
79
|
+
error: run.error ?? serializeError(WorkflowRunCanceledError.create(run.id))
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { makeCanceledRunResult, makeCompletedRunResult, readRunResult, retentionCleanupOptions, workflowHandle };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RunId } from "../types/run-id.mjs";
|
|
2
|
+
import { ScheduleConfig, ScheduleId, ScheduleRecord, ScheduleStatus, TickSchedulesOptions, TickSchedulesResult } from "../types/schedule.mjs";
|
|
3
|
+
import { WorkflowDefinition } from "../types/definition.mjs";
|
|
4
|
+
import "../types/run.mjs";
|
|
5
|
+
import { WorkflowRunReaderRepository, WorkflowScheduleConditionalWriterRepository, WorkflowScheduleCreationRepository, WorkflowScheduleListerRepository, WorkflowScheduleReaderRepository, WorkflowStoreNamespace } from "../types/store.mjs";
|
|
6
|
+
import { WorkflowExecutionLimits } from "../types/engine-options.mjs";
|
|
7
|
+
import { WorkflowRunCanceler, WorkflowRunStarter, WorkflowScheduleRunObserver } from "../types/engine.mjs";
|
|
8
|
+
//#region src/engine/schedule.d.ts
|
|
9
|
+
type WorkflowScheduleCommandStore = WorkflowStoreNamespace & WorkflowScheduleCreationRepository & WorkflowScheduleReaderRepository & WorkflowScheduleConditionalWriterRepository;
|
|
10
|
+
type WorkflowScheduleTickStore = WorkflowScheduleListerRepository & WorkflowScheduleConditionalWriterRepository & WorkflowRunReaderRepository;
|
|
11
|
+
type WorkflowScheduleTickEngine = WorkflowRunStarter & WorkflowRunCanceler & Partial<WorkflowScheduleRunObserver>;
|
|
12
|
+
declare function resolveScheduleRecord<TInput, TOutput, TRawInput>(namespace: string, definition: WorkflowDefinition<TInput, TOutput, TRawInput>, options: ScheduleConfig<TInput, TRawInput>, createdAt: Temporal.Instant, limits: WorkflowExecutionLimits): ScheduleRecord<TInput>;
|
|
13
|
+
declare function upsertSchedule<TInput, TOutput, TRawInput>(store: WorkflowScheduleCommandStore, definition: WorkflowDefinition<TInput, TOutput, TRawInput>, options: ScheduleConfig<TInput, TRawInput>, timestamp: Temporal.Instant, limits: WorkflowExecutionLimits): Promise<ScheduleRecord<TInput>>;
|
|
14
|
+
declare function updateScheduleStatus(store: WorkflowScheduleReaderRepository & WorkflowScheduleConditionalWriterRepository, scheduleId: ScheduleId, status: ScheduleStatus, now: Temporal.Instant): Promise<ScheduleRecord>;
|
|
15
|
+
declare function workflowScheduleFireTimes(schedule: ScheduleRecord, now: Temporal.Instant): readonly Temporal.Instant[];
|
|
16
|
+
declare function advanceSchedule(store: WorkflowScheduleConditionalWriterRepository, schedule: ScheduleRecord, now: Temporal.Instant, updatedAt: Temporal.Instant, fired?: {
|
|
17
|
+
readonly fireAt: Temporal.Instant;
|
|
18
|
+
readonly runId: RunId;
|
|
19
|
+
}): Promise<ScheduleRecord | undefined>;
|
|
20
|
+
declare function bufferSchedule(store: WorkflowScheduleConditionalWriterRepository, schedule: ScheduleRecord, fireTimes: readonly Temporal.Instant[], now: Temporal.Instant, updatedAt: Temporal.Instant): Promise<ScheduleRecord | undefined>;
|
|
21
|
+
declare function hasActiveScheduledRun(store: WorkflowRunReaderRepository, schedule: ScheduleRecord): Promise<boolean>;
|
|
22
|
+
declare function cancelActiveScheduledRun(store: WorkflowRunReaderRepository, engine: WorkflowRunCanceler, schedule: ScheduleRecord): Promise<void>;
|
|
23
|
+
declare function tickSchedules(store: WorkflowScheduleTickStore, engine: WorkflowScheduleTickEngine, now: () => Temporal.Instant, tickOptions: TickSchedulesOptions | undefined): Promise<TickSchedulesResult>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { advanceSchedule, bufferSchedule, cancelActiveScheduledRun, hasActiveScheduledRun, resolveScheduleRecord, tickSchedules, updateScheduleStatus, upsertSchedule, workflowScheduleFireTimes };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { isActiveWorkflowRunStatus } from "../utility.mjs";
|
|
2
|
+
import { WorkflowScheduleAlreadyExistsError, WorkflowScheduleError } from "../errors/schedule.mjs";
|
|
3
|
+
import "../errors/mod.mjs";
|
|
4
|
+
import { defineWorkflowFromName } from "../definition.mjs";
|
|
5
|
+
import { toOptionalPersistedValue, toPersistedValue } from "./serialization.mjs";
|
|
6
|
+
//#region src/engine/schedule.ts
|
|
7
|
+
const MAX_SCHEDULE_UPSERT_ATTEMPTS = 3;
|
|
8
|
+
function resolveScheduleRecord(namespace, definition, options, createdAt, limits) {
|
|
9
|
+
const nextFireAt = (options.from ?? createdAt).toZonedDateTimeISO("UTC").add(options.every).toInstant();
|
|
10
|
+
const endAt = options.endAt;
|
|
11
|
+
const catchUp = options.catchUp ?? "one";
|
|
12
|
+
const maxCatchUpRuns = options.maxCatchUpRuns;
|
|
13
|
+
const overlap = options.overlap ?? "allow";
|
|
14
|
+
const persistedInput = toOptionalPersistedValue(options.input, "workflow schedule input", limits);
|
|
15
|
+
return {
|
|
16
|
+
id: options.id,
|
|
17
|
+
namespace,
|
|
18
|
+
workflowName: definition.name,
|
|
19
|
+
...definition.version === void 0 ? {} : { workflowVersion: definition.version },
|
|
20
|
+
...persistedInput === void 0 ? {} : { input: persistedInput },
|
|
21
|
+
...options.context === void 0 ? {} : { context: toPersistedValue(options.context, "workflow schedule context", limits) },
|
|
22
|
+
status: endAt !== void 0 && Temporal.Instant.compare(nextFireAt, endAt) > 0 ? "deleted" : "active",
|
|
23
|
+
every: options.every,
|
|
24
|
+
catchUp,
|
|
25
|
+
...maxCatchUpRuns === void 0 ? {} : { maxCatchUpRuns },
|
|
26
|
+
...options.maxLateness === void 0 ? {} : { maxLateness: options.maxLateness },
|
|
27
|
+
overlap,
|
|
28
|
+
createdAt,
|
|
29
|
+
updatedAt: createdAt,
|
|
30
|
+
nextFireAt,
|
|
31
|
+
...endAt === void 0 ? {} : { endAt },
|
|
32
|
+
tickCount: 0
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async function upsertSchedule(store, definition, options, timestamp, limits) {
|
|
36
|
+
const schedule = resolveScheduleRecord(store.namespace, definition, options, timestamp, limits);
|
|
37
|
+
for (let attempt = 0; attempt < MAX_SCHEDULE_UPSERT_ATTEMPTS; attempt += 1) {
|
|
38
|
+
const existing = await store.getSchedule(schedule.id);
|
|
39
|
+
if (existing === void 0) try {
|
|
40
|
+
return await store.createSchedule(schedule);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (!WorkflowScheduleAlreadyExistsError.isAlreadyExists(error, schedule.id)) throw error;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const next = {
|
|
46
|
+
...schedule,
|
|
47
|
+
createdAt: existing.createdAt,
|
|
48
|
+
updatedAt: timestamp,
|
|
49
|
+
tickCount: existing.tickCount,
|
|
50
|
+
...existing.bufferedFireAt === void 0 ? {} : { bufferedFireAt: existing.bufferedFireAt },
|
|
51
|
+
...existing.lastFireAt === void 0 ? {} : { lastFireAt: existing.lastFireAt },
|
|
52
|
+
...existing.lastRunId === void 0 ? {} : { lastRunId: existing.lastRunId }
|
|
53
|
+
};
|
|
54
|
+
const updated = await store.updateScheduleIfCurrent(existing, next);
|
|
55
|
+
if (updated !== void 0) return updated;
|
|
56
|
+
}
|
|
57
|
+
WorkflowScheduleError.upsertConflictExhausted(schedule.id);
|
|
58
|
+
}
|
|
59
|
+
async function updateScheduleStatus(store, scheduleId, status, now) {
|
|
60
|
+
const current = await store.getSchedule(scheduleId);
|
|
61
|
+
if (current === void 0) WorkflowScheduleError.notFound(scheduleId);
|
|
62
|
+
const next = {
|
|
63
|
+
...current,
|
|
64
|
+
status,
|
|
65
|
+
updatedAt: now
|
|
66
|
+
};
|
|
67
|
+
const updated = await store.updateScheduleIfCurrent(current, next);
|
|
68
|
+
if (updated === void 0) WorkflowScheduleError.updateConflictExhausted(scheduleId);
|
|
69
|
+
return updated;
|
|
70
|
+
}
|
|
71
|
+
function workflowScheduleFireTimes(schedule, now) {
|
|
72
|
+
if (schedule.bufferedFireAt !== void 0) return [schedule.bufferedFireAt];
|
|
73
|
+
if (schedule.catchUp !== "all") {
|
|
74
|
+
const fireAt = schedule.catchUp === "skip" && Temporal.Instant.compare(schedule.nextFireAt, now) < 0 ? now : schedule.nextFireAt;
|
|
75
|
+
return schedule.endAt !== void 0 && Temporal.Instant.compare(fireAt, schedule.endAt) > 0 || schedule.maxLateness !== void 0 && now.since(fireAt).total({ unit: "millisecond" }) > schedule.maxLateness.total({ unit: "millisecond" }) ? [] : [fireAt];
|
|
76
|
+
}
|
|
77
|
+
const maxCatchUpRuns = schedule.maxCatchUpRuns ?? 10;
|
|
78
|
+
const fireTimes = [];
|
|
79
|
+
let fireAt = schedule.nextFireAt;
|
|
80
|
+
while (Temporal.Instant.compare(fireAt, now) <= 0) {
|
|
81
|
+
if (schedule.endAt !== void 0 && Temporal.Instant.compare(fireAt, schedule.endAt) > 0) break;
|
|
82
|
+
if (!(schedule.maxLateness !== void 0 && now.since(fireAt).total({ unit: "millisecond" }) > schedule.maxLateness.total({ unit: "millisecond" }))) {
|
|
83
|
+
fireTimes.push(fireAt);
|
|
84
|
+
if (fireTimes.length >= maxCatchUpRuns) break;
|
|
85
|
+
}
|
|
86
|
+
fireAt = fireAt.add(schedule.every);
|
|
87
|
+
}
|
|
88
|
+
return fireTimes;
|
|
89
|
+
}
|
|
90
|
+
async function advanceSchedule(store, schedule, now, updatedAt, fired) {
|
|
91
|
+
const nextFireAt = (fired?.fireAt ?? now).add(schedule.every);
|
|
92
|
+
const next = {
|
|
93
|
+
...schedule,
|
|
94
|
+
nextFireAt,
|
|
95
|
+
status: schedule.endAt !== void 0 && Temporal.Instant.compare(nextFireAt, schedule.endAt) > 0 ? "deleted" : schedule.status,
|
|
96
|
+
updatedAt,
|
|
97
|
+
tickCount: schedule.tickCount + (fired === void 0 ? 0 : 1),
|
|
98
|
+
...fired === void 0 || schedule.bufferedFireAt === void 0 ? {} : { bufferedFireAt: void 0 },
|
|
99
|
+
...fired === void 0 ? {} : {
|
|
100
|
+
lastFireAt: fired.fireAt,
|
|
101
|
+
lastRunId: fired.runId
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
return await store.updateScheduleIfCurrent(schedule, next);
|
|
105
|
+
}
|
|
106
|
+
async function bufferSchedule(store, schedule, fireTimes, now, updatedAt) {
|
|
107
|
+
const bufferAt = schedule.bufferedFireAt ?? fireTimes.at(-1);
|
|
108
|
+
const nextFireAt = (fireTimes.at(-1) ?? now).add(schedule.every);
|
|
109
|
+
const next = {
|
|
110
|
+
...schedule,
|
|
111
|
+
nextFireAt,
|
|
112
|
+
status: schedule.endAt !== void 0 && Temporal.Instant.compare(nextFireAt, schedule.endAt) > 0 ? "deleted" : schedule.status,
|
|
113
|
+
updatedAt,
|
|
114
|
+
...bufferAt === void 0 ? {} : { bufferedFireAt: bufferAt }
|
|
115
|
+
};
|
|
116
|
+
return await store.updateScheduleIfCurrent(schedule, next);
|
|
117
|
+
}
|
|
118
|
+
async function hasActiveScheduledRun(store, schedule) {
|
|
119
|
+
if (schedule.lastRunId === void 0) return false;
|
|
120
|
+
const run = await store.getRun(schedule.lastRunId);
|
|
121
|
+
return run !== void 0 && isActiveWorkflowRunStatus(run.status);
|
|
122
|
+
}
|
|
123
|
+
async function cancelActiveScheduledRun(store, engine, schedule) {
|
|
124
|
+
if (schedule.lastRunId === void 0) return;
|
|
125
|
+
const run = await store.getRun(schedule.lastRunId);
|
|
126
|
+
if (run !== void 0 && isActiveWorkflowRunStatus(run.status)) await engine.cancelRun(schedule.lastRunId);
|
|
127
|
+
}
|
|
128
|
+
async function tickSchedules(store, engine, now, tickOptions) {
|
|
129
|
+
const tickNow = tickOptions?.now === void 0 ? now() : tickOptions.now;
|
|
130
|
+
const limit = tickOptions?.limit;
|
|
131
|
+
const schedules = (await store.listSchedules({ status: "active" })).filter((schedule) => schedule.bufferedFireAt !== void 0 || Temporal.Instant.compare(schedule.nextFireAt, tickNow) <= 0).slice(0, limit);
|
|
132
|
+
const runIds = [];
|
|
133
|
+
const scheduleIds = [];
|
|
134
|
+
for (const schedule of schedules) {
|
|
135
|
+
const hasActiveRun = await hasActiveScheduledRun(store, schedule);
|
|
136
|
+
if (schedule.overlap === "skip" && hasActiveRun) {
|
|
137
|
+
const skipped = await advanceSchedule(store, schedule, tickNow, tickNow);
|
|
138
|
+
if (skipped !== void 0) scheduleIds.push(skipped.id);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (schedule.overlap === "cancel" && hasActiveRun) await cancelActiveScheduledRun(store, engine, schedule);
|
|
142
|
+
let currentSchedule = schedule;
|
|
143
|
+
let advancedSchedule = false;
|
|
144
|
+
const fireTimes = workflowScheduleFireTimes(schedule, tickNow);
|
|
145
|
+
if (schedule.overlap === "buffer" && hasActiveRun) {
|
|
146
|
+
const buffered = await bufferSchedule(store, schedule, fireTimes, tickNow, tickNow);
|
|
147
|
+
if (buffered !== void 0) scheduleIds.push(buffered.id);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (fireTimes.length === 0) {
|
|
151
|
+
const skipped = await advanceSchedule(store, schedule, tickNow, tickNow);
|
|
152
|
+
if (skipped !== void 0) scheduleIds.push(skipped.id);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
for (const fireAt of fireTimes) {
|
|
156
|
+
const run = await engine.startWorkflow(defineWorkflowFromName(schedule.workflowName, schedule.workflowVersion), schedule.input, {
|
|
157
|
+
idempotencyKey: `schedule:${schedule.id}:${fireAt.toString()}`,
|
|
158
|
+
availableAt: fireAt,
|
|
159
|
+
context: scheduleRunContext(schedule, fireAt)
|
|
160
|
+
});
|
|
161
|
+
const advanced = await advanceSchedule(store, currentSchedule, tickNow, tickNow, {
|
|
162
|
+
fireAt,
|
|
163
|
+
runId: run.runId
|
|
164
|
+
});
|
|
165
|
+
if (advanced === void 0) break;
|
|
166
|
+
currentSchedule = advanced;
|
|
167
|
+
advancedSchedule = true;
|
|
168
|
+
runIds.push(run.runId);
|
|
169
|
+
engine.observeScheduleRunCreated?.({
|
|
170
|
+
scheduleId: schedule.id,
|
|
171
|
+
runId: run.runId,
|
|
172
|
+
workflowName: schedule.workflowName,
|
|
173
|
+
...schedule.workflowVersion === void 0 ? {} : { workflowVersion: schedule.workflowVersion },
|
|
174
|
+
fireAt,
|
|
175
|
+
timestamp: tickNow
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
if (advancedSchedule) scheduleIds.push(schedule.id);
|
|
179
|
+
}
|
|
180
|
+
const nextScheduleAt = (await store.listSchedules({
|
|
181
|
+
status: "active",
|
|
182
|
+
limit: 1
|
|
183
|
+
}))[0]?.nextFireAt;
|
|
184
|
+
return {
|
|
185
|
+
ticked: runIds.length,
|
|
186
|
+
runIds,
|
|
187
|
+
scheduleIds,
|
|
188
|
+
...nextScheduleAt === void 0 ? {} : { nextScheduleAt }
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function scheduleRunContext(schedule, fireAt) {
|
|
192
|
+
if (schedule.context === void 0) return {
|
|
193
|
+
scheduleId: schedule.id,
|
|
194
|
+
scheduleFireAt: fireAt.toString()
|
|
195
|
+
};
|
|
196
|
+
if (typeof schedule.context === "object" && schedule.context !== null && !Array.isArray(schedule.context) && (Object.getPrototypeOf(schedule.context) === Object.prototype || Object.getPrototypeOf(schedule.context) === null)) return Object.assign({}, schedule.context, {
|
|
197
|
+
scheduleId: schedule.id,
|
|
198
|
+
scheduleFireAt: fireAt.toString()
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
value: schedule.context,
|
|
202
|
+
scheduleId: schedule.id,
|
|
203
|
+
scheduleFireAt: fireAt.toString()
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
export { advanceSchedule, bufferSchedule, cancelActiveScheduledRun, hasActiveScheduledRun, resolveScheduleRecord, tickSchedules, updateScheduleStatus, upsertSchedule, workflowScheduleFireTimes };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WorkflowErrorRecord } from "../types/error.mjs";
|
|
2
|
+
import { WorkflowEngineSerializationLimits } from "../types/engine-options.mjs";
|
|
3
|
+
import { StorageValue } from "@temelj/storage";
|
|
4
|
+
//#region src/engine/serialization.d.ts
|
|
5
|
+
declare function serializeError(error: unknown): WorkflowErrorRecord;
|
|
6
|
+
declare function toPersistedValue(value: unknown, path: string, limits?: WorkflowEngineSerializationLimits): StorageValue;
|
|
7
|
+
declare function toOptionalPersistedValue(value: unknown, path: string, limits?: WorkflowEngineSerializationLimits): StorageValue | undefined;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { serializeError, toOptionalPersistedValue, toPersistedValue };
|