@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,201 @@
|
|
|
1
|
+
import { makeWorkflowStepAttemptKey } from "../history/attempt-key.mjs";
|
|
2
|
+
import { observeTelemetry } from "../telemetry.mjs";
|
|
3
|
+
import { getWorkflowEventStepAttemptKey } from "../events/descriptors.mjs";
|
|
4
|
+
import "../history/mod.mjs";
|
|
5
|
+
import { createWorkflowStepAttempts } from "../history/step-attempts.mjs";
|
|
6
|
+
import { createPubSub } from "@temelj/event";
|
|
7
|
+
//#region src/engine/observation.ts
|
|
8
|
+
function createObservationEmitter(telemetry) {
|
|
9
|
+
return new ObservationEmitter(telemetry);
|
|
10
|
+
}
|
|
11
|
+
var ObservationEmitter = class {
|
|
12
|
+
#events = createPubSub();
|
|
13
|
+
#telemetry;
|
|
14
|
+
#emit = (event, payload) => {
|
|
15
|
+
this.#events.emit(event, payload);
|
|
16
|
+
observeTelemetry(this.#telemetry, event, payload);
|
|
17
|
+
};
|
|
18
|
+
constructor(telemetry) {
|
|
19
|
+
this.#telemetry = telemetry;
|
|
20
|
+
this.on = this.on.bind(this);
|
|
21
|
+
this.once = this.once.bind(this);
|
|
22
|
+
this.off = this.off.bind(this);
|
|
23
|
+
this.listeners = this.listeners.bind(this);
|
|
24
|
+
this.clearListeners = this.clearListeners.bind(this);
|
|
25
|
+
this.listenerCount = this.listenerCount.bind(this);
|
|
26
|
+
this.emitRunEvent = this.emitRunEvent.bind(this);
|
|
27
|
+
this.emitRunMetadataUpdated = this.emitRunMetadataUpdated.bind(this);
|
|
28
|
+
this.emitDurableEventAppended = this.emitDurableEventAppended.bind(this);
|
|
29
|
+
this.emitMessageSent = this.emitMessageSent.bind(this);
|
|
30
|
+
this.emitHookResumed = this.emitHookResumed.bind(this);
|
|
31
|
+
this.emitWebhookResumed = this.emitWebhookResumed.bind(this);
|
|
32
|
+
this.emitChildWorkflowStarted = this.emitChildWorkflowStarted.bind(this);
|
|
33
|
+
this.emitCleanupCompleted = this.emitCleanupCompleted.bind(this);
|
|
34
|
+
this.emitRetentionApplied = this.emitRetentionApplied.bind(this);
|
|
35
|
+
this.emitWorkerOperation = this.emitWorkerOperation.bind(this);
|
|
36
|
+
this.emitScheduleTicked = this.emitScheduleTicked.bind(this);
|
|
37
|
+
this.emitScheduleRunCreated = this.emitScheduleRunCreated.bind(this);
|
|
38
|
+
}
|
|
39
|
+
on(pattern, handler) {
|
|
40
|
+
return this.#events.on(pattern, handler);
|
|
41
|
+
}
|
|
42
|
+
once(pattern, handler) {
|
|
43
|
+
return this.#events.once(pattern, handler);
|
|
44
|
+
}
|
|
45
|
+
off(pattern, handler) {
|
|
46
|
+
this.#events.off(pattern, handler);
|
|
47
|
+
}
|
|
48
|
+
clearListeners(pattern) {
|
|
49
|
+
this.#events.clear(pattern);
|
|
50
|
+
}
|
|
51
|
+
listenerCount(pattern) {
|
|
52
|
+
return this.#events.listenerCount(pattern);
|
|
53
|
+
}
|
|
54
|
+
listeners(pattern) {
|
|
55
|
+
return pattern === void 0 ? this.#events.listeners() : this.#events.listeners(pattern);
|
|
56
|
+
}
|
|
57
|
+
emitRunEvent(run, previousRun) {
|
|
58
|
+
emitRunEvent(this.#emit, run, previousRun);
|
|
59
|
+
}
|
|
60
|
+
emitRunMetadataUpdated(run, previousRun) {
|
|
61
|
+
this.#emit("workflow:run-metadata-updated", makeRunObservationEvent(run, previousRun));
|
|
62
|
+
}
|
|
63
|
+
emitDurableEventAppended(runId, event, appendedEvents) {
|
|
64
|
+
this.#emit("workflow:durable-event-appended", {
|
|
65
|
+
runId,
|
|
66
|
+
event,
|
|
67
|
+
events: appendedEvents
|
|
68
|
+
});
|
|
69
|
+
emitStepAttemptUpdated(this.#emit, runId, event, appendedEvents);
|
|
70
|
+
emitStreamUpdated(this.#emit, runId, event);
|
|
71
|
+
}
|
|
72
|
+
emitMessageSent(runId, event) {
|
|
73
|
+
this.#emit("workflow:message-sent", {
|
|
74
|
+
runId,
|
|
75
|
+
messageId: event.messageId,
|
|
76
|
+
payload: event.payload,
|
|
77
|
+
timestamp: event.timestamp,
|
|
78
|
+
...event.telemetryContext === void 0 ? {} : { traceContext: event.telemetryContext }
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
emitHookResumed(runId, messageId, payload, traceContext) {
|
|
82
|
+
this.#emit("workflow:hook-resumed", {
|
|
83
|
+
runId,
|
|
84
|
+
messageId,
|
|
85
|
+
...payload === void 0 ? {} : { payload },
|
|
86
|
+
...traceContext === void 0 ? {} : { traceContext }
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
emitWebhookResumed(runId, messageId, payload, traceContext) {
|
|
90
|
+
this.#emit("workflow:webhook-resumed", {
|
|
91
|
+
runId,
|
|
92
|
+
messageId,
|
|
93
|
+
...payload === void 0 ? {} : { payload },
|
|
94
|
+
...traceContext === void 0 ? {} : { traceContext }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
emitChildWorkflowStarted(event) {
|
|
98
|
+
this.#emit("workflow:child-workflow-started", event);
|
|
99
|
+
}
|
|
100
|
+
emitCleanupCompleted(result) {
|
|
101
|
+
this.#emit("workflow:cleanup-completed", { result });
|
|
102
|
+
}
|
|
103
|
+
emitRetentionApplied(result) {
|
|
104
|
+
this.#emit("workflow:retention-applied", { result });
|
|
105
|
+
}
|
|
106
|
+
emitWorkerOperation(event) {
|
|
107
|
+
this.#emit("workflow:worker-operation", event);
|
|
108
|
+
}
|
|
109
|
+
emitScheduleTicked(event) {
|
|
110
|
+
this.#emit("workflow:schedule-ticked", event);
|
|
111
|
+
}
|
|
112
|
+
emitScheduleRunCreated(event) {
|
|
113
|
+
this.#emit("workflow:schedule-run-created", event);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
function emitStepAttemptUpdated(emit, runId, event, events) {
|
|
117
|
+
let key;
|
|
118
|
+
try {
|
|
119
|
+
key = getWorkflowEventStepAttemptKey(event);
|
|
120
|
+
} catch {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (key === void 0) return;
|
|
124
|
+
const attempt = createWorkflowStepAttempts(runId, events).find((current) => makeWorkflowStepAttemptKey(current.stepId, current.attempt) === key);
|
|
125
|
+
if (attempt === void 0) return;
|
|
126
|
+
emit("workflow:step-attempt-updated", {
|
|
127
|
+
runId,
|
|
128
|
+
attempt
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function emitStreamUpdated(emit, runId, event) {
|
|
132
|
+
if (event.kind !== "stream_started" && event.kind !== "stream_chunk" && event.kind !== "stream_closed" && event.kind !== "stream_failed") return;
|
|
133
|
+
emit("workflow:stream-updated", {
|
|
134
|
+
runId,
|
|
135
|
+
streamId: event.streamId,
|
|
136
|
+
streamName: event.stepName,
|
|
137
|
+
eventKind: event.kind,
|
|
138
|
+
timestamp: event.timestamp,
|
|
139
|
+
stepId: event.stepId,
|
|
140
|
+
stepName: event.stepName,
|
|
141
|
+
...event.kind === "stream_chunk" ? { index: event.index } : {},
|
|
142
|
+
...event.kind === "stream_failed" ? { error: event.error } : {}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function emitRunEvent(emit, run, previousRun) {
|
|
146
|
+
const payload = makeRunObservationEvent(run, previousRun);
|
|
147
|
+
switch (run.lastTransitionReason) {
|
|
148
|
+
case "created":
|
|
149
|
+
emit("workflow:run-created", payload);
|
|
150
|
+
break;
|
|
151
|
+
case "claimed":
|
|
152
|
+
case "reclaimed":
|
|
153
|
+
emit("workflow:run-claimed", payload);
|
|
154
|
+
break;
|
|
155
|
+
case "started":
|
|
156
|
+
emit("workflow:run-started", payload);
|
|
157
|
+
break;
|
|
158
|
+
case "waiting":
|
|
159
|
+
case "missing_implementation":
|
|
160
|
+
emit("workflow:run-waiting", payload);
|
|
161
|
+
break;
|
|
162
|
+
case "rescheduled":
|
|
163
|
+
emit("workflow:run-rescheduled", payload);
|
|
164
|
+
break;
|
|
165
|
+
case "lease_released":
|
|
166
|
+
emit("workflow:run-lease-released", payload);
|
|
167
|
+
break;
|
|
168
|
+
case "manual_retry":
|
|
169
|
+
emit("workflow:run-manual-retry", payload);
|
|
170
|
+
break;
|
|
171
|
+
case "permanent_failure":
|
|
172
|
+
emit("workflow:run-permanently-failed", payload);
|
|
173
|
+
break;
|
|
174
|
+
case "retry":
|
|
175
|
+
emit("workflow:run-retrying", payload);
|
|
176
|
+
break;
|
|
177
|
+
case "completed":
|
|
178
|
+
emit("workflow:run-completed", payload);
|
|
179
|
+
break;
|
|
180
|
+
case "failed":
|
|
181
|
+
case "deadline":
|
|
182
|
+
emit("workflow:run-failed", payload);
|
|
183
|
+
break;
|
|
184
|
+
case "canceled":
|
|
185
|
+
emit("workflow:run-canceled", payload);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function makeRunObservationEvent(run, previousRun) {
|
|
190
|
+
return {
|
|
191
|
+
run,
|
|
192
|
+
previousRun,
|
|
193
|
+
status: run.status,
|
|
194
|
+
reason: run.lastTransitionReason,
|
|
195
|
+
timestamp: run.lastTransitionAt,
|
|
196
|
+
workflowName: run.workflowName,
|
|
197
|
+
...run.workflowVersion === void 0 ? {} : { workflowVersion: run.workflowVersion }
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
//#endregion
|
|
201
|
+
export { ObservationEmitter, createObservationEmitter };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ScheduleRecord } from "../types/schedule.mjs";
|
|
2
|
+
import { LockRecord } from "../types/lock.mjs";
|
|
3
|
+
import { WorkflowRecoverySummary } from "../types/summary.mjs";
|
|
4
|
+
import { WorkflowStepAttemptRecord } from "../types/step-attempts.mjs";
|
|
5
|
+
import { WorkflowRunRecord } from "../types/run.mjs";
|
|
6
|
+
import { WorkflowRecoveryWaitInputs } from "./summary/recovery-waits.mjs";
|
|
7
|
+
//#region src/engine/recovery.d.ts
|
|
8
|
+
interface WorkflowRecoverySummaryInputs extends WorkflowRecoveryWaitInputs {
|
|
9
|
+
readonly lockWaitAttempts?: readonly WorkflowStepAttemptRecord[];
|
|
10
|
+
readonly locks?: readonly LockRecord[];
|
|
11
|
+
readonly schedules?: readonly ScheduleRecord[];
|
|
12
|
+
}
|
|
13
|
+
interface WorkflowRecoverySummaryOptions {
|
|
14
|
+
readonly runs: readonly WorkflowRunRecord[];
|
|
15
|
+
readonly now: Temporal.Instant;
|
|
16
|
+
readonly inputs?: WorkflowRecoverySummaryInputs;
|
|
17
|
+
}
|
|
18
|
+
interface WorkflowRecoveryDeadline {
|
|
19
|
+
readonly timestamp: Temporal.Instant;
|
|
20
|
+
}
|
|
21
|
+
declare function summarizeWorkflowRecovery(options: WorkflowRecoverySummaryOptions): WorkflowRecoverySummary;
|
|
22
|
+
declare function mergeWorkflowRecoveryRunIds(runIdGroups: readonly (readonly string[])[]): readonly string[];
|
|
23
|
+
declare function workflowRecoveryDeadline(ownerId: string | undefined, timestamp: Temporal.Instant | undefined): WorkflowRecoveryDeadline | undefined;
|
|
24
|
+
declare function earliestWorkflowRecoveryDeadline(candidates: readonly (WorkflowRecoveryDeadline | undefined)[]): WorkflowRecoveryDeadline | undefined;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { WorkflowRecoveryDeadline, WorkflowRecoverySummaryInputs, WorkflowRecoverySummaryOptions, earliestWorkflowRecoveryDeadline, mergeWorkflowRecoveryRunIds, summarizeWorkflowRecovery, workflowRecoveryDeadline };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createWorkflowRecoveryLockSummaryReducer } from "./summary/recovery-locks.mjs";
|
|
2
|
+
import { createWorkflowRecoveryRunSummaryReducer } from "./summary/recovery-runs.mjs";
|
|
3
|
+
import { createWorkflowRecoveryScheduleSummaryReducer } from "./summary/recovery-schedules.mjs";
|
|
4
|
+
import { createWorkflowRecoveryWaitSummaryReducer } from "./summary/recovery-waits.mjs";
|
|
5
|
+
//#region src/engine/recovery.ts
|
|
6
|
+
function recoveryWaitInputs(inputs) {
|
|
7
|
+
return {
|
|
8
|
+
sleepAttempts: inputs.sleepAttempts,
|
|
9
|
+
messageWaitAttempts: inputs.messageWaitAttempts,
|
|
10
|
+
childWorkflowAttempts: inputs.childWorkflowAttempts,
|
|
11
|
+
childRuns: inputs.childRuns,
|
|
12
|
+
eventsByRunId: inputs.eventsByRunId
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function recoveryResourceInputs(inputs) {
|
|
16
|
+
return {
|
|
17
|
+
lockWaitAttempts: inputs.lockWaitAttempts,
|
|
18
|
+
locks: inputs.locks,
|
|
19
|
+
schedules: inputs.schedules
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function summarizeWorkflowRecovery(options) {
|
|
23
|
+
const { runs, now, inputs = {} } = options;
|
|
24
|
+
const waitInputs = recoveryWaitInputs(inputs);
|
|
25
|
+
const resources = recoveryResourceInputs(inputs);
|
|
26
|
+
const runReducer = createWorkflowRecoveryRunSummaryReducer(now);
|
|
27
|
+
for (const run of runs) runReducer.addRun(run);
|
|
28
|
+
const runSummary = runReducer.finish();
|
|
29
|
+
const waitReducer = createWorkflowRecoveryWaitSummaryReducer(waitInputs, now);
|
|
30
|
+
waitReducer.addSleepAttempts(waitInputs.sleepAttempts ?? []);
|
|
31
|
+
waitReducer.addMessageWaitAttempts(waitInputs.messageWaitAttempts ?? []);
|
|
32
|
+
waitReducer.addChildWorkflowAttempts(waitInputs.childWorkflowAttempts ?? []);
|
|
33
|
+
const wait = waitReducer.finish();
|
|
34
|
+
const lockReducer = createWorkflowRecoveryLockSummaryReducer(runs, now);
|
|
35
|
+
for (const lockRecord of resources.locks ?? []) lockReducer.addLock(lockRecord);
|
|
36
|
+
for (const attempt of resources.lockWaitAttempts ?? []) lockReducer.addLockWaitAttempt(attempt);
|
|
37
|
+
const lock = lockReducer.finish();
|
|
38
|
+
const scheduleReducer = createWorkflowRecoveryScheduleSummaryReducer(now);
|
|
39
|
+
for (const scheduleRecord of resources.schedules ?? []) scheduleReducer.addSchedule(scheduleRecord);
|
|
40
|
+
const schedule = scheduleReducer.finish();
|
|
41
|
+
const recoverableRunIds = mergeWorkflowRecoveryRunIds([
|
|
42
|
+
runSummary.recoverableRunIds,
|
|
43
|
+
wait.sleep.dueRunIds,
|
|
44
|
+
wait.message.readyRunIds,
|
|
45
|
+
wait.message.timedOutRunIds,
|
|
46
|
+
wait.childWorkflow.terminalRunIds,
|
|
47
|
+
wait.childWorkflow.missingRunIds,
|
|
48
|
+
wait.childWorkflow.timedOutRunIds
|
|
49
|
+
]);
|
|
50
|
+
const summary = {
|
|
51
|
+
total: runSummary.total,
|
|
52
|
+
recoverableRunIds,
|
|
53
|
+
due: runSummary.due,
|
|
54
|
+
lease: runSummary.lease,
|
|
55
|
+
retry: runSummary.retry,
|
|
56
|
+
missingImplementation: runSummary.missingImplementation,
|
|
57
|
+
failed: runSummary.failed,
|
|
58
|
+
schedule,
|
|
59
|
+
lock,
|
|
60
|
+
wait
|
|
61
|
+
};
|
|
62
|
+
const nextRecovery = earliestWorkflowRecoveryDeadline([
|
|
63
|
+
runSummary.nextAvailable,
|
|
64
|
+
runSummary.nextLeaseExpires,
|
|
65
|
+
runSummary.nextRetry,
|
|
66
|
+
workflowRecoveryDeadline(schedule.nextFireScheduleId, schedule.nextFireAt),
|
|
67
|
+
workflowRecoveryDeadline(lock.nextExpiringKey, lock.nextExpiresAt),
|
|
68
|
+
workflowRecoveryDeadline(lock.nextWaitDeadlineRunId, lock.nextWaitDeadlineAt),
|
|
69
|
+
workflowRecoveryDeadline(wait.sleep.nextWakeRunId, wait.sleep.nextWakeAt),
|
|
70
|
+
workflowRecoveryDeadline(wait.message.nextTimeoutRunId, wait.message.nextTimeoutAt),
|
|
71
|
+
workflowRecoveryDeadline(wait.childWorkflow.nextTimeoutRunId, wait.childWorkflow.nextTimeoutAt)
|
|
72
|
+
]);
|
|
73
|
+
return {
|
|
74
|
+
...summary,
|
|
75
|
+
...nextRecovery === void 0 ? {} : { nextRecoveryAt: nextRecovery.timestamp }
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function mergeWorkflowRecoveryRunIds(runIdGroups) {
|
|
79
|
+
return [...new Set(runIdGroups.flat())].sort();
|
|
80
|
+
}
|
|
81
|
+
function workflowRecoveryDeadline(ownerId, timestamp) {
|
|
82
|
+
return ownerId === void 0 || timestamp === void 0 ? void 0 : { timestamp };
|
|
83
|
+
}
|
|
84
|
+
function earliestWorkflowRecoveryDeadline(candidates) {
|
|
85
|
+
return candidates.reduce((current, candidate) => {
|
|
86
|
+
if (candidate === void 0) return current;
|
|
87
|
+
if (current === void 0) return candidate;
|
|
88
|
+
return Temporal.Instant.compare(candidate.timestamp, current.timestamp) < 0 ? candidate : current;
|
|
89
|
+
}, void 0);
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { earliestWorkflowRecoveryDeadline, mergeWorkflowRecoveryRunIds, summarizeWorkflowRecovery, workflowRecoveryDeadline };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { MessageId } from "../types/message-id.mjs";
|
|
2
|
+
import { RunId } from "../types/run-id.mjs";
|
|
3
|
+
import { WorkflowStepRunConfig } from "../types/step.mjs";
|
|
4
|
+
import { WorkflowAttributePatch, WorkflowStepIdentity } from "../types/run.mjs";
|
|
5
|
+
import { EventRecord } from "../types/events.mjs";
|
|
6
|
+
import "../history/mod.mjs";
|
|
7
|
+
import { WorkflowExecutionEnvironment } from "../types/engine.mjs";
|
|
8
|
+
import { StorageValue } from "@temelj/storage";
|
|
9
|
+
//#region src/engine/replay.d.ts
|
|
10
|
+
declare function isRunStepTerminalForStartedAttempt(terminal: Extract<EventRecord, {
|
|
11
|
+
readonly kind: "step_completed" | "step_failed";
|
|
12
|
+
}>, started: Extract<EventRecord, {
|
|
13
|
+
readonly kind: "step_started";
|
|
14
|
+
}>): boolean;
|
|
15
|
+
declare function requireRecordedDurableStepStarted(identity: WorkflowStepIdentity, started: boolean): void;
|
|
16
|
+
declare function requireRecordedDurableTerminalStarted(identity: WorkflowStepIdentity, hasStartedEventBeforeTerminal: boolean): void;
|
|
17
|
+
declare function requireRunStepReplayTimeoutMatches(identity: WorkflowStepIdentity, started: Extract<EventRecord, {
|
|
18
|
+
readonly kind: "step_started";
|
|
19
|
+
}> | undefined, config: WorkflowStepRunConfig): void;
|
|
20
|
+
declare function requireMetadataReplayMatches(identity: WorkflowStepIdentity, recorded: Extract<EventRecord, {
|
|
21
|
+
readonly kind: "metadata_set";
|
|
22
|
+
}>, metadata: StorageValue): void;
|
|
23
|
+
declare function requireAttributesReplayMatches(identity: WorkflowStepIdentity, recorded: Extract<EventRecord, {
|
|
24
|
+
readonly kind: "attributes_set";
|
|
25
|
+
}>, attributes: WorkflowAttributePatch): void;
|
|
26
|
+
declare function requireMessageSendReplayMatches(identity: WorkflowStepIdentity, started: Extract<EventRecord, {
|
|
27
|
+
readonly kind: "message_send_started";
|
|
28
|
+
}> | undefined, terminal: Extract<EventRecord, {
|
|
29
|
+
readonly kind: "message_send_started" | "message_send_completed" | "message_send_failed";
|
|
30
|
+
}>, next: {
|
|
31
|
+
readonly targetRunId: RunId;
|
|
32
|
+
readonly messageId: MessageId;
|
|
33
|
+
readonly payload?: StorageValue;
|
|
34
|
+
readonly idempotencyKey?: string;
|
|
35
|
+
}): void;
|
|
36
|
+
declare function sleepUntil(environment: WorkflowExecutionEnvironment, name: string, initialUntil: Temporal.Instant, options: {
|
|
37
|
+
readonly duration?: Temporal.Duration;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
declare function recordedStepCompletionTimestamp(identity: WorkflowStepIdentity, value: Temporal.Instant): Temporal.Instant;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { isRunStepTerminalForStartedAttempt, recordedStepCompletionTimestamp, requireAttributesReplayMatches, requireMessageSendReplayMatches, requireMetadataReplayMatches, requireRecordedDurableStepStarted, requireRecordedDurableTerminalStarted, requireRunStepReplayTimeoutMatches, sleepUntil };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { WorkflowReplayDivergenceError } from "../errors/failures.mjs";
|
|
2
|
+
import { workflowAttributePatchFromEvent } from "../attributes.mjs";
|
|
3
|
+
import "../errors/mod.mjs";
|
|
4
|
+
import { WorkflowSuspended } from "./state.mjs";
|
|
5
|
+
import { resolveWorkflowCommandIdentity } from "./command-identity.mjs";
|
|
6
|
+
import { appendDurableStepStartedEvent, appendDurableStepTerminalEvent } from "./durable-command.mjs";
|
|
7
|
+
import { deepEquals } from "@temelj/value";
|
|
8
|
+
//#region src/engine/replay.ts
|
|
9
|
+
function isRunStepTerminalForStartedAttempt(terminal, started) {
|
|
10
|
+
return terminal.attempt === started.attempt;
|
|
11
|
+
}
|
|
12
|
+
function requireRecordedDurableStepStarted(identity, started) {
|
|
13
|
+
if (started) return;
|
|
14
|
+
WorkflowReplayDivergenceError.diverged(`recorded ${identity.kind} step ${identity.id} has a terminal event without a started event`, {
|
|
15
|
+
expectedStepId: identity.id,
|
|
16
|
+
actualStepId: identity.id
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function requireRecordedDurableTerminalStarted(identity, hasStartedEventBeforeTerminal) {
|
|
20
|
+
requireRecordedDurableStepStarted(identity, hasStartedEventBeforeTerminal);
|
|
21
|
+
}
|
|
22
|
+
function requireRunStepReplayTimeoutMatches(identity, started, config) {
|
|
23
|
+
if (started === void 0 || started.timeoutAt === void 0 === (config.timeout === void 0)) return;
|
|
24
|
+
const recordedTimeout = started.timeoutAt === void 0 ? "no timeout" : started.timeoutAt.toString();
|
|
25
|
+
const replayTimeout = config.timeout === void 0 ? "no timeout" : "a timeout";
|
|
26
|
+
WorkflowReplayDivergenceError.diverged(`recorded run step ${identity.id} had ${recordedTimeout}, but replay used ${replayTimeout}`, {
|
|
27
|
+
expectedStepId: identity.id,
|
|
28
|
+
actualStepId: identity.id
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function requireMetadataReplayMatches(identity, recorded, metadata) {
|
|
32
|
+
if (deepEquals(recorded.metadata, metadata)) return;
|
|
33
|
+
WorkflowReplayDivergenceError.diverged(`recorded metadata step ${identity.id} used different metadata`, {
|
|
34
|
+
expectedStepId: identity.id,
|
|
35
|
+
actualStepId: recorded.stepId
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function requireAttributesReplayMatches(identity, recorded, attributes) {
|
|
39
|
+
if (JSON.stringify(workflowAttributePatchFromEvent(recorded)) === JSON.stringify(attributes)) return;
|
|
40
|
+
WorkflowReplayDivergenceError.diverged(`recorded attributes step ${identity.id} used different attributes`, {
|
|
41
|
+
expectedStepId: identity.id,
|
|
42
|
+
actualStepId: recorded.stepId
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function requireMessageSendReplayMatches(identity, started, terminal, next) {
|
|
46
|
+
const recordedTargetRunId = started?.targetRunId ?? terminal.targetRunId;
|
|
47
|
+
const recordedMessage = started?.messageId ?? terminal.messageId;
|
|
48
|
+
const recordedPayload = started?.payload;
|
|
49
|
+
const recordedIdempotencyKey = started?.idempotencyKey;
|
|
50
|
+
if (recordedTargetRunId === next.targetRunId && recordedMessage === next.messageId && deepEquals(recordedPayload, next.payload) && recordedIdempotencyKey === next.idempotencyKey) return;
|
|
51
|
+
const message = recordedTargetRunId === next.targetRunId && recordedMessage === next.messageId ? `recorded message-send step ${identity.id} targeted ${recordedTargetRunId} messageId ${recordedMessage} with different payload or idempotency key` : `recorded message-send step ${identity.id} targeted ${recordedTargetRunId} messageId ${recordedMessage}, but replay targeted ${next.targetRunId} messageId ${next.messageId}`;
|
|
52
|
+
WorkflowReplayDivergenceError.diverged(message, {
|
|
53
|
+
expectedStepId: identity.id,
|
|
54
|
+
actualStepId: identity.id
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function sleepUntil(environment, name, initialUntil, options) {
|
|
58
|
+
const { history, now } = environment;
|
|
59
|
+
const identity = resolveWorkflowCommandIdentity(history, "sleep", name);
|
|
60
|
+
const started = history.startedSleep(identity.id);
|
|
61
|
+
const completed = history.completedSleep(identity.id);
|
|
62
|
+
if (completed !== void 0) {
|
|
63
|
+
requireRecordedDurableStepStarted(identity, history.hasStartedEventBeforeTerminalEvent(completed));
|
|
64
|
+
requireSleepReplayMatches(identity, started, initialUntil, options);
|
|
65
|
+
if (!(completed.timestamp instanceof Temporal.Instant)) WorkflowReplayDivergenceError.diverged(`recorded sleep step ${identity.id} has invalid completion timestamp: ` + String(completed.timestamp), {
|
|
66
|
+
expectedStepId: identity.id,
|
|
67
|
+
actualStepId: identity.id
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const until = started === void 0 ? initialUntil : recordedSleepUntil(identity, started.until);
|
|
72
|
+
requireSleepReplayMatches(identity, started, initialUntil, options);
|
|
73
|
+
if (started === void 0) await appendDurableStepStartedEvent(environment, {
|
|
74
|
+
kind: "sleep_started",
|
|
75
|
+
timestamp: now(),
|
|
76
|
+
stepId: identity.id,
|
|
77
|
+
stepName: identity.name,
|
|
78
|
+
count: identity.count,
|
|
79
|
+
until,
|
|
80
|
+
...options.duration === void 0 ? {} : { duration: options.duration }
|
|
81
|
+
});
|
|
82
|
+
if (Temporal.Instant.compare(until, now()) > 0) WorkflowSuspended.until(until);
|
|
83
|
+
await appendDurableStepTerminalEvent(environment, {
|
|
84
|
+
kind: "sleep_completed",
|
|
85
|
+
timestamp: now(),
|
|
86
|
+
stepId: identity.id,
|
|
87
|
+
stepName: identity.name
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function recordedStepCompletionTimestamp(identity, value) {
|
|
91
|
+
if (value instanceof Temporal.Instant) return value;
|
|
92
|
+
WorkflowReplayDivergenceError.diverged(`recorded run step ${identity.id} has invalid completion timestamp: ${String(value)}`, {
|
|
93
|
+
expectedStepId: identity.id,
|
|
94
|
+
actualStepId: identity.id
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function recordedSleepUntil(identity, value) {
|
|
98
|
+
if (value instanceof Temporal.Instant) return value;
|
|
99
|
+
WorkflowReplayDivergenceError.diverged(`recorded sleep step ${identity.id} has invalid wake timestamp: ${String(value)}`, {
|
|
100
|
+
expectedStepId: identity.id,
|
|
101
|
+
actualStepId: identity.id
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function requireSleepReplayMatches(identity, started, until, options) {
|
|
105
|
+
if (started === void 0) return;
|
|
106
|
+
if (started.duration !== void 0 || options.duration !== void 0) {
|
|
107
|
+
if (started.duration === void 0 || options.duration === void 0) {
|
|
108
|
+
if (started.duration === options.duration) return;
|
|
109
|
+
} else if (started.duration.toString() === options.duration.toString()) return;
|
|
110
|
+
WorkflowReplayDivergenceError.diverged(`recorded sleep step ${identity.id} waited for ${String(started.duration)}ms, but replay waited for ${String(options.duration)}ms`, {
|
|
111
|
+
expectedStepId: identity.id,
|
|
112
|
+
actualStepId: identity.id
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (Temporal.Instant.compare(started.until, until) === 0) return;
|
|
116
|
+
WorkflowReplayDivergenceError.diverged(`recorded sleep step ${identity.id} waited until ${started.until.toString()}, but replay waited until ${until.toString()}`, {
|
|
117
|
+
expectedStepId: identity.id,
|
|
118
|
+
actualStepId: identity.id
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { isRunStepTerminalForStartedAttempt, recordedStepCompletionTimestamp, requireAttributesReplayMatches, requireMessageSendReplayMatches, requireMetadataReplayMatches, requireRecordedDurableStepStarted, requireRecordedDurableTerminalStarted, requireRunStepReplayTimeoutMatches, sleepUntil };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RunId } from "../types/run-id.mjs";
|
|
2
|
+
import { WorkflowMissingImplementationRetryConfig, WorkflowMissingImplementationRetryDefaults, WorkflowResolvedMissingImplementationRetryConfig, WorkflowResolvedRetryConfig, WorkflowResolvedRetryDefaults, WorkflowResolvedStepRetryConfig, WorkflowRetryConfig } from "../types/retry.mjs";
|
|
3
|
+
import { WorkflowStepRunWorkflowOptions } from "../types/step.mjs";
|
|
4
|
+
import "../types/run.mjs";
|
|
5
|
+
import { EventRecord } from "../types/events.mjs";
|
|
6
|
+
import { WorkflowHistory } from "../history/mod.mjs";
|
|
7
|
+
//#region src/engine/retry.d.ts
|
|
8
|
+
interface WorkflowEngineRetryLimits {
|
|
9
|
+
readonly maximumEventHistoryEvents?: number;
|
|
10
|
+
}
|
|
11
|
+
/** Resolves retry options and merges them with defaults used by workflow or step execution. */
|
|
12
|
+
declare function resolveWorkflowRetryConfig(config: WorkflowRetryConfig | undefined, defaults: WorkflowResolvedRetryDefaults, label: string): WorkflowResolvedRetryConfig;
|
|
13
|
+
/** Resolves missing-implementation retry options and merges them with worker defaults. */
|
|
14
|
+
declare function resolveMissingImplementationRetryConfig(config: WorkflowMissingImplementationRetryConfig | undefined, defaults: WorkflowMissingImplementationRetryDefaults, label: string): WorkflowResolvedMissingImplementationRetryConfig;
|
|
15
|
+
declare function resolveChildWorkflowRetryConfig(options: WorkflowStepRunWorkflowOptions | undefined): WorkflowResolvedStepRetryConfig;
|
|
16
|
+
declare function shouldRetryWorkflowAttempt(retry: WorkflowResolvedRetryConfig, failedAttempt: number): boolean;
|
|
17
|
+
declare function nextWorkflowRetryAttempt(failedAttempt: number): number;
|
|
18
|
+
declare function enforceStepAttemptBudget(runId: RunId, history: WorkflowHistory, maximumStepAttemptsPerRun: number): void;
|
|
19
|
+
declare function enforceWorkflowEventHistoryNextLimit(events: readonly EventRecord[], limits: WorkflowEngineRetryLimits): void;
|
|
20
|
+
declare function nextRetryAt(failedAt: Temporal.Instant, retry: WorkflowResolvedRetryConfig, failedAttempt: number, label: string): Temporal.Instant | undefined;
|
|
21
|
+
declare function retryClassificationRetryAt(failedAt: Temporal.Instant, error: unknown, label: string): Temporal.Instant | undefined;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { enforceStepAttemptBudget, enforceWorkflowEventHistoryNextLimit, nextRetryAt, nextWorkflowRetryAttempt, resolveChildWorkflowRetryConfig, resolveMissingImplementationRetryConfig, resolveWorkflowRetryConfig, retryClassificationRetryAt, shouldRetryWorkflowAttempt };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { WorkflowOptionsError } from "../errors/base.mjs";
|
|
2
|
+
import { WorkflowDurationError, WorkflowRetryableError, WorkflowSerializationError } from "../errors/failures.mjs";
|
|
3
|
+
import { durationAmount, isPositiveSafeInteger, nextPositiveSafeInteger, resolveSafeRetryDelay } from "../utility.mjs";
|
|
4
|
+
import { WorkflowStepAttemptLimitError } from "../errors/step.mjs";
|
|
5
|
+
import "../errors/mod.mjs";
|
|
6
|
+
//#region src/engine/retry.ts
|
|
7
|
+
const DEFAULT_STEP_RETRY_CONFIG = {
|
|
8
|
+
maximumAttempts: 10,
|
|
9
|
+
backoffCoefficient: 2
|
|
10
|
+
};
|
|
11
|
+
/** Resolves retry options and merges them with defaults used by workflow or step execution. */
|
|
12
|
+
function resolveWorkflowRetryConfig(config, defaults, label) {
|
|
13
|
+
const input = config ?? {};
|
|
14
|
+
if (input.initialInterval !== void 0 && input.maximumInterval !== void 0 && Temporal.Duration.compare(input.maximumInterval, input.initialInterval) < 0) WorkflowOptionsError.retryMaximumIntervalTooSmall(label);
|
|
15
|
+
return {
|
|
16
|
+
maximumAttempts: input.maximumAttempts ?? defaults.maximumAttempts,
|
|
17
|
+
...input.initialInterval === void 0 ? {} : { initialInterval: input.initialInterval },
|
|
18
|
+
backoffCoefficient: input.backoffCoefficient ?? defaults.backoffCoefficient,
|
|
19
|
+
...input.maximumInterval === void 0 ? {} : { maximumInterval: input.maximumInterval }
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Resolves missing-implementation retry options and merges them with worker defaults. */
|
|
23
|
+
function resolveMissingImplementationRetryConfig(config, defaults, label) {
|
|
24
|
+
const input = config === void 0 ? {} : config;
|
|
25
|
+
const initialInterval = input.initialInterval ?? defaults.initialInterval;
|
|
26
|
+
const maximumInterval = input.maximumInterval;
|
|
27
|
+
if (maximumInterval !== void 0 && Temporal.Duration.compare(maximumInterval, initialInterval) < 0) WorkflowOptionsError.retryMaximumIntervalTooSmall(label);
|
|
28
|
+
return {
|
|
29
|
+
initialInterval,
|
|
30
|
+
backoffCoefficient: input.backoffCoefficient ?? defaults.backoffCoefficient,
|
|
31
|
+
maximumAttempts: input.maximumAttempts ?? defaults.maximumAttempts,
|
|
32
|
+
...maximumInterval === void 0 ? {} : { maximumInterval }
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function resolveChildWorkflowRetryConfig(options) {
|
|
36
|
+
if (options?.retry === void 0) return {
|
|
37
|
+
maximumAttempts: 1,
|
|
38
|
+
backoffCoefficient: DEFAULT_STEP_RETRY_CONFIG.backoffCoefficient
|
|
39
|
+
};
|
|
40
|
+
return resolveWorkflowRetryConfig(options.retry, DEFAULT_STEP_RETRY_CONFIG, "Workflow step retry");
|
|
41
|
+
}
|
|
42
|
+
function shouldRetryWorkflowAttempt(retry, failedAttempt) {
|
|
43
|
+
return retry.maximumAttempts === 0 || failedAttempt < retry.maximumAttempts;
|
|
44
|
+
}
|
|
45
|
+
function nextWorkflowRetryAttempt(failedAttempt) {
|
|
46
|
+
const nextAttempt = nextPositiveSafeInteger(failedAttempt);
|
|
47
|
+
if (nextAttempt === void 0) WorkflowOptionsError.positiveSafeInteger("Workflow retry next attempt");
|
|
48
|
+
return nextAttempt;
|
|
49
|
+
}
|
|
50
|
+
function enforceStepAttemptBudget(runId, history, maximumStepAttemptsPerRun) {
|
|
51
|
+
if (history.totalStartedStepCount() >= maximumStepAttemptsPerRun) WorkflowStepAttemptLimitError.exceeded(runId, maximumStepAttemptsPerRun);
|
|
52
|
+
}
|
|
53
|
+
function enforceWorkflowEventHistoryNextLimit(events, limits) {
|
|
54
|
+
if (limits.maximumEventHistoryEvents !== void 0 && events.length >= limits.maximumEventHistoryEvents) WorkflowSerializationError.notSerializable("workflow event history", `event count would exceed maximumEventHistoryEvents ${limits.maximumEventHistoryEvents}`);
|
|
55
|
+
}
|
|
56
|
+
function nextRetryAt(failedAt, retry, failedAttempt, label) {
|
|
57
|
+
if (retry.initialInterval === void 0) return;
|
|
58
|
+
if (!isPositiveSafeInteger(failedAttempt)) WorkflowOptionsError.positiveSafeInteger(`${label} attempt`);
|
|
59
|
+
const exponentialDelay = durationAmount(retry.initialInterval, label) * retry.backoffCoefficient ** (failedAttempt - 1);
|
|
60
|
+
const cappedDelay = retry.maximumInterval === void 0 ? exponentialDelay : Math.min(exponentialDelay, durationAmount(retry.maximumInterval, label));
|
|
61
|
+
return failedAt.add(Temporal.Duration.from({ milliseconds: resolveSafeRetryDelay(cappedDelay, label) }));
|
|
62
|
+
}
|
|
63
|
+
function retryClassificationRetryAt(failedAt, error, label) {
|
|
64
|
+
if (!(error instanceof WorkflowRetryableError)) return;
|
|
65
|
+
if (error.retryAt !== void 0) {
|
|
66
|
+
if (!(error.retryAt instanceof Temporal.Instant)) WorkflowDurationError.retryAtInstant(label);
|
|
67
|
+
return error.retryAt;
|
|
68
|
+
}
|
|
69
|
+
if (error.retryDelay !== void 0) {
|
|
70
|
+
const retryDelay = durationAmount(error.retryDelay, label);
|
|
71
|
+
return failedAt.add(Temporal.Duration.from({ milliseconds: resolveSafeRetryDelay(retryDelay, label) }));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { enforceStepAttemptBudget, enforceWorkflowEventHistoryNextLimit, nextRetryAt, nextWorkflowRetryAttempt, resolveChildWorkflowRetryConfig, resolveMissingImplementationRetryConfig, resolveWorkflowRetryConfig, retryClassificationRetryAt, shouldRetryWorkflowAttempt };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WorkflowStepRunDataApi } from "../types/step.mjs";
|
|
2
|
+
import { WorkflowAttributePatch } from "../types/run.mjs";
|
|
3
|
+
import { WorkflowExecutionEnvironment } from "../types/engine.mjs";
|
|
4
|
+
//#region src/engine/run-data.d.ts
|
|
5
|
+
declare function createWorkflowRunDataApi(environment: WorkflowExecutionEnvironment): WorkflowStepRunDataApi;
|
|
6
|
+
declare function setWorkflowRunMetadata(environment: WorkflowExecutionEnvironment, commandId: string, metadata: unknown): Promise<void>;
|
|
7
|
+
declare function setWorkflowRunAttributes(environment: WorkflowExecutionEnvironment, commandId: string, attributes: WorkflowAttributePatch): Promise<void>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { createWorkflowRunDataApi, setWorkflowRunAttributes, setWorkflowRunMetadata };
|