@temelj/workflow 0.0.0-alpha.2 → 0.0.0-alpha.4
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/README.md +394 -2
- package/dist/attributes.d.mts +11 -9
- package/dist/attributes.mjs +23 -5
- package/dist/bundle.d.mts +5 -23
- package/dist/bundle.mjs +2 -18
- package/dist/client/create.d.mts +26 -23
- package/dist/client/create.mjs +26 -32
- package/dist/client/facades.d.mts +12 -18
- package/dist/client/facades.mjs +102 -93
- package/dist/client/mod.mjs +1 -2
- package/dist/client/run-handle.d.mts +17 -54
- package/dist/client/run-handle.mjs +35 -105
- package/dist/client/worker-options.d.mts +8 -8
- package/dist/client/worker-options.mjs +11 -11
- package/dist/cloudflare/cloudflare.d.mts +4 -5
- package/dist/cloudflare/codec.d.mts +28 -13
- package/dist/cloudflare/codec.mjs +40 -17
- package/dist/cloudflare/entrypoint.d.mts +3 -4
- package/dist/cloudflare/entrypoint.mjs +4 -3
- package/dist/cloudflare/execution.d.mts +3 -4
- package/dist/cloudflare/execution.mjs +20 -13
- package/dist/cloudflare/host.d.mts +6 -7
- package/dist/cloudflare/host.mjs +7 -6
- package/dist/cloudflare/mod.d.mts +4 -4
- package/dist/cloudflare/mod.mjs +2 -2
- package/dist/cloudflare/name.d.mts +3 -4
- package/dist/cloudflare/name.mjs +3 -3
- package/dist/cloudflare/registry.d.mts +3 -23
- package/dist/cloudflare/registry.mjs +2 -20
- package/dist/cloudflare/runtime.d.mts +11 -18
- package/dist/cloudflare/runtime.mjs +52 -73
- package/dist/cloudflare/step.d.mts +6 -6
- package/dist/cloudflare/step.mjs +69 -57
- package/dist/cloudflare/types.d.mts +17 -36
- package/dist/collection.d.mts +8 -11
- package/dist/collection.mjs +10 -14
- package/dist/compiled-function.d.mts +14 -19
- package/dist/compiled-function.mjs +12 -24
- package/dist/compiled.d.mts +4 -0
- package/dist/compiled.mjs +4 -0
- package/dist/compiler/ast.d.mts +26 -0
- package/dist/{vite → compiler}/ast.mjs +24 -16
- package/dist/{vite → compiler}/error.d.mts +4 -6
- package/dist/{vite → compiler}/error.mjs +14 -16
- package/dist/compiler/manifest.d.mts +6 -0
- package/dist/{vite → compiler}/manifest.mjs +9 -7
- package/dist/compiler/plugin.d.mts +7 -0
- package/dist/{vite → compiler}/plugin.mjs +45 -46
- package/dist/compiler/safety.d.mts +12 -0
- package/dist/{vite → compiler}/safety.mjs +5 -11
- package/dist/{vite → compiler}/source-edit.d.mts +3 -4
- package/dist/{vite → compiler}/source-edit.mjs +1 -1
- package/dist/{vite → compiler}/source-map.d.mts +4 -3
- package/dist/{vite → compiler}/source-map.mjs +3 -3
- package/dist/compiler/source.d.mts +7 -0
- package/dist/{vite → compiler}/source.mjs +1 -1
- package/dist/compiler/transform.d.mts +12 -0
- package/dist/{vite → compiler}/transform.mjs +37 -38
- package/dist/definition.d.mts +17 -25
- package/dist/definition.mjs +19 -35
- package/dist/engine/child-workflow.d.mts +5 -9
- package/dist/engine/child-workflow.mjs +46 -67
- package/dist/engine/command-identity.d.mts +5 -6
- package/dist/engine/command-identity.mjs +9 -5
- package/dist/engine/context.d.mts +17 -0
- package/dist/engine/create.d.mts +36 -94
- package/dist/engine/create.mjs +55 -260
- package/dist/engine/deterministic.d.mts +6 -11
- package/dist/engine/deterministic.mjs +47 -68
- package/dist/engine/durable-command.d.mts +5 -5
- package/dist/engine/durable-command.mjs +2 -2
- package/dist/engine/execution-service.d.mts +20 -24
- package/dist/engine/execution-service.mjs +54 -52
- package/dist/engine/hooks.d.mts +17 -39
- package/dist/engine/hooks.mjs +73 -94
- package/dist/engine/inspection.d.mts +23 -15
- package/dist/engine/inspection.mjs +55 -29
- package/dist/engine/lifecycle.d.mts +6 -12
- package/dist/engine/lifecycle.mjs +5 -5
- package/dist/engine/lock-replay.d.mts +8 -15
- package/dist/engine/lock-replay.mjs +12 -25
- package/dist/engine/lock.d.mts +10 -15
- package/dist/engine/lock.mjs +65 -51
- package/dist/engine/message.d.mts +14 -34
- package/dist/engine/message.mjs +94 -127
- package/dist/engine/observation.d.mts +9 -11
- package/dist/engine/observation.mjs +18 -27
- package/dist/engine/replay.d.mts +18 -19
- package/dist/engine/replay.mjs +32 -56
- package/dist/engine/resume.d.mts +16 -0
- package/dist/engine/resume.mjs +24 -0
- package/dist/engine/retry.d.mts +15 -19
- package/dist/engine/retry.mjs +17 -17
- package/dist/engine/run-data.d.mts +4 -8
- package/dist/engine/run-data.mjs +24 -22
- package/dist/engine/run-service.d.mts +24 -33
- package/dist/engine/run-service.mjs +125 -93
- package/dist/engine/run-utils.d.mts +11 -13
- package/dist/engine/run-utils.mjs +23 -46
- package/dist/engine/schedule.d.mts +8 -22
- package/dist/engine/schedule.mjs +37 -34
- package/dist/engine/serialization.d.mts +9 -6
- package/dist/engine/serialization.mjs +30 -21
- package/dist/engine/signals.d.mts +23 -0
- package/dist/engine/signals.mjs +41 -0
- package/dist/engine/start.d.mts +18 -0
- package/dist/engine/start.mjs +88 -0
- package/dist/engine/state.d.mts +37 -67
- package/dist/engine/state.mjs +127 -282
- package/dist/engine/step-api.d.mts +5 -8
- package/dist/engine/step-api.mjs +16 -16
- package/dist/engine/stream-reader.d.mts +12 -0
- package/dist/engine/stream-reader.mjs +154 -0
- package/dist/engine/stream.d.mts +9 -54
- package/dist/engine/stream.mjs +54 -196
- package/dist/engine/summary/recovery.d.mts +35 -0
- package/dist/engine/summary/recovery.mjs +363 -0
- package/dist/engine/summary/runs.d.mts +43 -0
- package/dist/engine/summary/runs.mjs +294 -0
- package/dist/engine/summary/step-attempts.d.mts +5 -10
- package/dist/engine/summary/step-attempts.mjs +157 -36
- package/dist/engine/summary/tally.d.mts +44 -0
- package/dist/engine/summary/tally.mjs +142 -0
- package/dist/engine/task.d.mts +4 -5
- package/dist/engine/task.mjs +40 -48
- package/dist/errors/base.d.mts +17 -77
- package/dist/errors/base.mjs +26 -327
- package/dist/errors/capability.d.mts +3 -6
- package/dist/errors/capability.mjs +4 -8
- package/dist/errors/codes.d.mts +116 -0
- package/dist/{types/error-code.mjs → errors/codes.mjs} +2 -17
- package/dist/errors/definition.d.mts +3 -17
- package/dist/errors/definition.mjs +5 -42
- package/dist/errors/failures.d.mts +17 -51
- package/dist/errors/failures.mjs +35 -102
- package/dist/errors/hook.d.mts +5 -9
- package/dist/errors/hook.mjs +4 -16
- package/dist/errors/implementation.d.mts +3 -6
- package/dist/errors/implementation.mjs +7 -12
- package/dist/errors/lock.d.mts +7 -20
- package/dist/errors/lock.mjs +8 -44
- package/dist/errors/message.d.mts +14 -59
- package/dist/errors/message.mjs +13 -39
- package/dist/errors/mod.d.mts +4 -5
- package/dist/errors/mod.mjs +5 -7
- package/dist/errors/records.d.mts +10 -4
- package/dist/errors/records.mjs +256 -256
- package/dist/errors/run.d.mts +27 -68
- package/dist/errors/run.mjs +31 -85
- package/dist/errors/schedule.d.mts +7 -18
- package/dist/errors/schedule.mjs +7 -39
- package/dist/errors/step.d.mts +12 -45
- package/dist/errors/step.mjs +13 -34
- package/dist/errors/stream.d.mts +8 -16
- package/dist/errors/stream.mjs +7 -41
- package/dist/esbuild.d.mts +6 -4
- package/dist/esbuild.mjs +2 -1
- package/dist/events/descriptors.d.mts +12 -241
- package/dist/events/descriptors.mjs +12 -5
- package/dist/history/projection.d.mts +4 -6
- package/dist/history/projection.mjs +22 -26
- package/dist/history/replay-projection.d.mts +44 -48
- package/dist/history/replay-projection.mjs +41 -50
- package/dist/history/{mod.d.mts → replay.d.mts} +16 -21
- package/dist/history/{mod.mjs → replay.mjs} +21 -25
- package/dist/history/sequencer.d.mts +10 -11
- package/dist/history/sequencer.mjs +11 -7
- package/dist/history/step-attempts.d.mts +4 -7
- package/dist/history/step-attempts.mjs +8 -9
- package/dist/history/timeline.d.mts +4 -13
- package/dist/history/timeline.mjs +46 -265
- package/dist/history/validator.d.mts +5 -7
- package/dist/history/validator.mjs +9 -24
- package/dist/hook-token.d.mts +7 -0
- package/dist/hook-token.mjs +32 -0
- package/dist/ids.d.mts +8 -0
- package/dist/ids.mjs +21 -0
- package/dist/message-options.d.mts +11 -5
- package/dist/message-options.mjs +9 -7
- package/dist/mod.d.mts +32 -36
- package/dist/mod.mjs +9 -13
- package/dist/otel/metrics.d.mts +31 -0
- package/dist/otel/metrics.mjs +60 -0
- package/dist/otel/mod.d.mts +3 -0
- package/dist/otel/mod.mjs +3 -0
- package/dist/otel/spans.d.mts +24 -0
- package/dist/otel/spans.mjs +218 -0
- package/dist/otel/support.d.mts +15 -8
- package/dist/otel/support.mjs +18 -40
- package/dist/{otel.d.mts → otel/telemetry.d.mts} +5 -6
- package/dist/otel/telemetry.mjs +305 -0
- package/dist/pagination.d.mts +6 -12
- package/dist/pagination.mjs +10 -14
- package/dist/registry.d.mts +8 -5
- package/dist/registry.mjs +19 -10
- package/dist/rolldown.d.mts +6 -4
- package/dist/rolldown.mjs +2 -1
- package/dist/rollup.d.mts +6 -4
- package/dist/rollup.mjs +2 -1
- package/dist/rspack.d.mts +6 -4
- package/dist/rspack.mjs +2 -1
- package/dist/run-status.d.mts +29 -0
- package/dist/run-status.mjs +42 -0
- package/dist/schema/common.d.mts +22 -0
- package/dist/schema/common.mjs +54 -0
- package/dist/schema/error.d.mts +17 -0
- package/dist/schema/error.mjs +39 -0
- package/dist/schema/events.d.mts +446 -0
- package/dist/schema/events.mjs +235 -0
- package/dist/schema/pagination.d.mts +5 -0
- package/dist/schema/pagination.mjs +11 -0
- package/dist/schema/persisted-value.d.mts +8 -0
- package/dist/schema/persisted-value.mjs +94 -0
- package/dist/schema/run.d.mts +51 -0
- package/dist/schema/run.mjs +88 -0
- package/dist/schema/store.d.mts +94 -0
- package/dist/schema/store.mjs +116 -0
- package/dist/step-definition.d.mts +4 -9
- package/dist/step-definition.mjs +2 -2
- package/dist/store/capabilities.d.mts +8 -9
- package/dist/store/capabilities.mjs +7 -7
- package/dist/store/cleanup.d.mts +9 -14
- package/dist/store/cleanup.mjs +86 -85
- package/dist/store/create.d.mts +28 -29
- package/dist/store/create.mjs +10 -11
- package/dist/store/events.d.mts +48 -0
- package/dist/store/events.mjs +263 -0
- package/dist/store/indexes.d.mts +25 -0
- package/dist/store/indexes.mjs +282 -0
- package/dist/store/instrumentation.d.mts +2 -3
- package/dist/store/instrumentation.mjs +30 -30
- package/dist/store/lock.d.mts +4 -5
- package/dist/store/lock.mjs +5 -7
- package/dist/store/materialization.d.mts +10 -17
- package/dist/store/materialization.mjs +39 -33
- package/dist/store/mod.d.mts +3 -3
- package/dist/store/mod.mjs +2 -2
- package/dist/store/query.d.mts +13 -17
- package/dist/store/query.mjs +13 -13
- package/dist/store/run.d.mts +25 -34
- package/dist/store/run.mjs +67 -108
- package/dist/store/schedule.d.mts +6 -8
- package/dist/store/schedule.mjs +11 -11
- package/dist/store/step-attempt.d.mts +9 -12
- package/dist/store/step-attempt.mjs +9 -9
- package/dist/store/storage-value.d.mts +3 -3
- package/dist/store/storage-value.mjs +17 -1
- package/dist/store/validation.d.mts +17 -20
- package/dist/store/validation.mjs +30 -33
- package/dist/store-keys.d.mts +35 -47
- package/dist/store-keys.mjs +9 -17
- package/dist/telemetry.d.mts +16 -16
- package/dist/telemetry.mjs +3 -3
- package/dist/temporal.d.mts +11 -16
- package/dist/temporal.mjs +8 -9
- package/dist/timer.d.mts +12 -10
- package/dist/timer.mjs +11 -3
- package/dist/types/cleanup.d.mts +13 -50
- package/dist/types/cleanup.mjs +1 -22
- package/dist/types/client.d.mts +101 -162
- package/dist/types/{vite.d.mts → compiler.d.mts} +17 -24
- package/dist/types/compiler.mjs +1 -0
- package/dist/types/definition.d.mts +22 -34
- package/dist/types/engine-options.d.mts +10 -17
- package/dist/types/engine.d.mts +15 -274
- package/dist/types/error.d.mts +15 -217
- package/dist/types/error.mjs +1 -48
- package/dist/types/events.d.mts +59 -2730
- package/dist/types/events.mjs +1 -283
- package/dist/types/hook.d.mts +27 -85
- package/dist/types/hook.mjs +1 -66
- package/dist/types/ids.d.mts +9 -0
- package/dist/types/ids.mjs +1 -0
- package/dist/types/lock.d.mts +8 -26
- package/dist/types/lock.mjs +1 -18
- package/dist/types/message.d.mts +29 -43
- package/dist/types/observation.d.mts +43 -58
- package/dist/types/pagination.d.mts +6 -22
- package/dist/types/pagination.mjs +1 -13
- package/dist/types/result.d.mts +11 -43
- package/dist/types/retry.d.mts +7 -14
- package/dist/types/run-list.d.mts +9 -11
- package/dist/types/run-options.d.mts +25 -32
- package/dist/types/run.d.mts +35 -315
- package/dist/types/run.mjs +1 -207
- package/dist/types/runtime.d.mts +33 -145
- package/dist/types/runtime.mjs +1 -21
- package/dist/types/schedule.d.mts +13 -72
- package/dist/types/schedule.mjs +1 -48
- package/dist/types/step-attempts.d.mts +65 -261
- package/dist/types/step-attempts.mjs +1 -43
- package/dist/types/step.d.mts +66 -77
- package/dist/types/step.mjs +1 -5
- package/dist/types/store.d.mts +50 -182
- package/dist/types/stream.d.mts +19 -40
- package/dist/types/summary.d.mts +174 -278
- package/dist/types/telemetry.d.mts +23 -28
- package/dist/types/telemetry.mjs +1 -9
- package/dist/types/timeline.d.mts +46 -233
- package/dist/types/worker.d.mts +22 -29
- package/dist/values.d.mts +15 -0
- package/dist/values.mjs +57 -0
- package/dist/vite.d.mts +5 -6
- package/dist/vite.mjs +3 -4
- package/dist/webpack.d.mts +6 -4
- package/dist/webpack.mjs +2 -1
- package/dist/worker/error.d.mts +2 -9
- package/dist/worker/error.mjs +20 -32
- package/dist/worker/missing-implementation.d.mts +19 -0
- package/dist/worker/missing-implementation.mjs +62 -0
- package/dist/worker/worker.d.mts +18 -0
- package/dist/{worker.mjs → worker/worker.mjs} +64 -118
- package/package.json +28 -47
- package/dist/engine/execution-api.d.mts +0 -29
- package/dist/engine/execution-api.mjs +0 -33
- package/dist/engine/inspection-api.d.mts +0 -34
- package/dist/engine/inspection-api.mjs +0 -78
- package/dist/engine/mod.d.mts +0 -4
- package/dist/engine/mod.mjs +0 -2
- package/dist/engine/recovery.d.mts +0 -26
- package/dist/engine/recovery.mjs +0 -92
- package/dist/engine/retry-policy.d.mts +0 -4
- package/dist/engine/retry-policy.mjs +0 -4
- package/dist/engine/start-api.d.mts +0 -30
- package/dist/engine/start-api.mjs +0 -99
- package/dist/engine/summary/active-events.d.mts +0 -34
- package/dist/engine/summary/active-events.mjs +0 -69
- package/dist/engine/summary/child-workflow-runs.d.mts +0 -24
- package/dist/engine/summary/child-workflow-runs.mjs +0 -138
- package/dist/engine/summary/child-workflow-waits.d.mts +0 -21
- package/dist/engine/summary/child-workflow-waits.mjs +0 -67
- package/dist/engine/summary/recovery-child-workflow-waits.d.mts +0 -11
- package/dist/engine/summary/recovery-child-workflow-waits.mjs +0 -89
- package/dist/engine/summary/recovery-due-runs.d.mts +0 -16
- package/dist/engine/summary/recovery-due-runs.mjs +0 -52
- package/dist/engine/summary/recovery-failed-runs.d.mts +0 -14
- package/dist/engine/summary/recovery-failed-runs.mjs +0 -33
- package/dist/engine/summary/recovery-lease-runs.d.mts +0 -16
- package/dist/engine/summary/recovery-lease-runs.mjs +0 -69
- package/dist/engine/summary/recovery-locks.d.mts +0 -18
- package/dist/engine/summary/recovery-locks.mjs +0 -100
- package/dist/engine/summary/recovery-message-waits.d.mts +0 -11
- package/dist/engine/summary/recovery-message-waits.mjs +0 -74
- package/dist/engine/summary/recovery-retry-runs.d.mts +0 -17
- package/dist/engine/summary/recovery-retry-runs.mjs +0 -65
- package/dist/engine/summary/recovery-run-timestamps.d.mts +0 -13
- package/dist/engine/summary/recovery-run-timestamps.mjs +0 -18
- package/dist/engine/summary/recovery-runs.d.mts +0 -23
- package/dist/engine/summary/recovery-runs.mjs +0 -54
- package/dist/engine/summary/recovery-schedules.d.mts +0 -10
- package/dist/engine/summary/recovery-schedules.mjs +0 -46
- package/dist/engine/summary/recovery-sleep-waits.d.mts +0 -10
- package/dist/engine/summary/recovery-sleep-waits.mjs +0 -53
- package/dist/engine/summary/recovery-waits.d.mts +0 -21
- package/dist/engine/summary/recovery-waits.mjs +0 -29
- package/dist/engine/summary/run-availability.d.mts +0 -13
- package/dist/engine/summary/run-availability.mjs +0 -37
- package/dist/engine/summary/run-cleanup.d.mts +0 -14
- package/dist/engine/summary/run-cleanup.mjs +0 -44
- package/dist/engine/summary/run-failure.d.mts +0 -14
- package/dist/engine/summary/run-failure.mjs +0 -62
- package/dist/engine/summary/run-hooks.d.mts +0 -14
- package/dist/engine/summary/run-hooks.mjs +0 -63
- package/dist/engine/summary/run-lease.d.mts +0 -11
- package/dist/engine/summary/run-lease.mjs +0 -64
- package/dist/engine/summary/run-message-waits.d.mts +0 -15
- package/dist/engine/summary/run-message-waits.mjs +0 -62
- package/dist/engine/summary/run-metrics.d.mts +0 -31
- package/dist/engine/summary/run-metrics.mjs +0 -93
- package/dist/engine/summary/run-retry.d.mts +0 -9
- package/dist/engine/summary/run-retry.mjs +0 -69
- package/dist/engine/summary/run-sleeps.d.mts +0 -15
- package/dist/engine/summary/run-sleeps.mjs +0 -61
- package/dist/engine/summary/run-state.d.mts +0 -26
- package/dist/engine/summary/run-state.mjs +0 -48
- package/dist/engine/summary/run-status.d.mts +0 -16
- package/dist/engine/summary/run-status.mjs +0 -35
- package/dist/engine/summary/run-streams.d.mts +0 -14
- package/dist/engine/summary/run-streams.mjs +0 -46
- package/dist/engine/summary/run-transition.d.mts +0 -9
- package/dist/engine/summary/run-transition.mjs +0 -39
- package/dist/engine/summary/run-workflow.d.mts +0 -9
- package/dist/engine/summary/run-workflow.mjs +0 -47
- package/dist/engine/summary/step-attempt-active-child-workflows.d.mts +0 -13
- package/dist/engine/summary/step-attempt-active-child-workflows.mjs +0 -55
- package/dist/engine/summary/step-attempt-active-fields.d.mts +0 -23
- package/dist/engine/summary/step-attempt-active-fields.mjs +0 -14
- package/dist/engine/summary/step-attempt-active-message-waits.d.mts +0 -12
- package/dist/engine/summary/step-attempt-active-message-waits.mjs +0 -47
- package/dist/engine/summary/step-attempt-active-sleeps.d.mts +0 -19
- package/dist/engine/summary/step-attempt-active-sleeps.mjs +0 -44
- package/dist/engine/summary/step-attempt-buckets.d.mts +0 -22
- package/dist/engine/summary/step-attempt-buckets.mjs +0 -152
- package/dist/engine/summary/step-attempt-failure.d.mts +0 -12
- package/dist/engine/summary/step-attempt-failure.mjs +0 -61
- package/dist/engine/summary/step-attempt-lifecycle.d.mts +0 -13
- package/dist/engine/summary/step-attempt-lifecycle.mjs +0 -19
- package/dist/engine/summary.d.mts +0 -32
- package/dist/engine/summary.mjs +0 -37
- package/dist/errors/details.d.mts +0 -13
- package/dist/errors/details.mjs +0 -66
- package/dist/errors/record-view.d.mts +0 -11
- package/dist/errors/record-view.mjs +0 -24
- package/dist/errors/runtime.d.mts +0 -12
- package/dist/errors/runtime.mjs +0 -24
- package/dist/events/mod.d.mts +0 -3
- package/dist/events/mod.mjs +0 -2
- package/dist/history/attempt-key.d.mts +0 -6
- package/dist/history/attempt-key.mjs +0 -7
- package/dist/inspection/mod.d.mts +0 -5
- package/dist/inspection/mod.mjs +0 -3
- package/dist/otel.mjs +0 -590
- package/dist/runtime.d.mts +0 -35
- package/dist/runtime.mjs +0 -198
- package/dist/store/append-projection.d.mts +0 -15
- package/dist/store/append-projection.mjs +0 -26
- package/dist/store/compaction.d.mts +0 -5
- package/dist/store/compaction.mjs +0 -8
- package/dist/store/event-append-project.d.mts +0 -15
- package/dist/store/event-append-project.mjs +0 -77
- package/dist/store/event-append.d.mts +0 -37
- package/dist/store/event-append.mjs +0 -80
- package/dist/store/event-history.d.mts +0 -22
- package/dist/store/event-history.mjs +0 -75
- package/dist/store/event.d.mts +0 -10
- package/dist/store/event.mjs +0 -28
- package/dist/store/idempotency.d.mts +0 -10
- package/dist/store/idempotency.mjs +0 -167
- package/dist/store/message-index.d.mts +0 -21
- package/dist/store/message-index.mjs +0 -122
- package/dist/store/revision.d.mts +0 -4
- package/dist/store/revision.mjs +0 -7
- package/dist/store/schema.d.mts +0 -14
- package/dist/store/schema.mjs +0 -17
- package/dist/types/common.d.mts +0 -20
- package/dist/types/common.mjs +0 -16
- package/dist/types/error-code.d.mts +0 -256
- package/dist/types/message-id.d.mts +0 -7
- package/dist/types/message-id.mjs +0 -5
- package/dist/types/run-id.d.mts +0 -7
- package/dist/types/run-id.mjs +0 -5
- package/dist/types/step-id.d.mts +0 -7
- package/dist/types/step-id.mjs +0 -5
- package/dist/types/stream-id.d.mts +0 -7
- package/dist/types/stream-id.mjs +0 -5
- package/dist/types/worker-id.d.mts +0 -7
- package/dist/types/worker-id.mjs +0 -5
- package/dist/utility.d.mts +0 -49
- package/dist/utility.mjs +0 -122
- package/dist/vite/ast.d.mts +0 -23
- package/dist/vite/generated-name.d.mts +0 -7
- package/dist/vite/generated-name.mjs +0 -9
- package/dist/vite/manifest.d.mts +0 -7
- package/dist/vite/plugin.d.mts +0 -7
- package/dist/vite/safety.d.mts +0 -12
- package/dist/vite/source.d.mts +0 -7
- package/dist/vite/transform.d.mts +0 -7
- package/dist/webhook.d.mts +0 -16
- package/dist/webhook.mjs +0 -17
- package/dist/worker.d.mts +0 -19
- /package/dist/{types/vite.mjs → engine/context.mjs} +0 -0
package/dist/store/create.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { getWorkflowStoreCapabilities } from "./capabilities.mjs";
|
|
2
1
|
import { makeEventsKey } from "../store-keys.mjs";
|
|
2
|
+
import { getWorkflowStoreCapabilities } from "./capabilities.mjs";
|
|
3
3
|
import { claimWorkflowRun, countWorkflowRuns, extendWorkflowRunLease, getWorkflowRun, listWorkflowRuns, listWorkflowRunsPage, releaseWorkflowRunLease, updateRunIfCurrent, updateWorkflowRun } from "./run.mjs";
|
|
4
|
-
import { hasMessageIdempotencyKey, repairMessageIdempotencyIndexes } from "./
|
|
4
|
+
import { createRunWithIdempotency, getRunByIdempotencyKey, hasMessageIdempotencyKey, repairMessageIdempotencyIndexes } from "./indexes.mjs";
|
|
5
|
+
import { appendWorkflowEvent, appendWorkflowEventIfRunCurrent, getWorkflowEvents } from "./events.mjs";
|
|
5
6
|
import { cleanupRuns, listCleanupMarkers } from "./cleanup.mjs";
|
|
6
|
-
import { appendWorkflowEvent, appendWorkflowEventIfRunCurrent, getWorkflowEvents } from "./event.mjs";
|
|
7
|
-
import { createRunWithIdempotency, getRunByIdempotencyKey } from "./idempotency.mjs";
|
|
8
7
|
import { getReadableLock, listReadableLocks, updateLockIfCurrent } from "./lock.mjs";
|
|
9
8
|
import { createSchedule, getReadableSchedule, listSchedules, listSchedulesPage, updateScheduleIfCurrent } from "./schedule.mjs";
|
|
10
9
|
import { countWorkflowStepAttempts, listWorkflowStepAttempts, listWorkflowStepAttemptsPage, repairWorkflowStepAttempts } from "./step-attempt.mjs";
|
|
@@ -75,15 +74,15 @@ var WorkflowStore = class {
|
|
|
75
74
|
if (settled) return;
|
|
76
75
|
settled = true;
|
|
77
76
|
options.signal?.removeEventListener("abort", finish);
|
|
78
|
-
|
|
77
|
+
disposeStoreWatcher(unwatch);
|
|
79
78
|
resolve();
|
|
80
79
|
};
|
|
81
80
|
options.signal?.addEventListener("abort", finish, { once: true });
|
|
82
81
|
this.storage.watch((event) => {
|
|
83
|
-
if (
|
|
82
|
+
if (isStorageChangeForKey(event, key)) finish();
|
|
84
83
|
}).then((unsubscribe) => {
|
|
85
84
|
unwatch = unsubscribe;
|
|
86
|
-
if (settled)
|
|
85
|
+
if (settled) disposeStoreWatcher(unwatch);
|
|
87
86
|
}).catch(() => {
|
|
88
87
|
finish();
|
|
89
88
|
});
|
|
@@ -138,15 +137,15 @@ var WorkflowStore = class {
|
|
|
138
137
|
return updateLockIfCurrent(this.storage, this.namespace, current, next);
|
|
139
138
|
}
|
|
140
139
|
};
|
|
141
|
-
function
|
|
140
|
+
function disposeStoreWatcher(unwatch) {
|
|
142
141
|
if (unwatch === void 0) return;
|
|
143
|
-
|
|
142
|
+
ignoreStoreWatcherDisposal(unwatch());
|
|
144
143
|
}
|
|
145
|
-
function
|
|
144
|
+
function ignoreStoreWatcherDisposal(result) {
|
|
146
145
|
if (result === void 0) return;
|
|
147
146
|
result.catch(() => {});
|
|
148
147
|
}
|
|
149
|
-
function
|
|
148
|
+
function isStorageChangeForKey(event, key) {
|
|
150
149
|
switch (event.type) {
|
|
151
150
|
case "set":
|
|
152
151
|
case "delete": return event.key === key;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { RunId } from "../types/ids.mjs";
|
|
2
|
+
import { RunRecord } from "../types/run.mjs";
|
|
3
|
+
import { EventRecord } from "../types/events.mjs";
|
|
4
|
+
import { WorkflowStorage } from "../types/store.mjs";
|
|
5
|
+
import { StorageCompareAndSetManyItem, StorageValue } from "@temelj/storage";
|
|
6
|
+
//#region src/store/events.d.ts
|
|
7
|
+
export declare function appendWorkflowEvent(storage: WorkflowStorage, namespace: string, runId: RunId, event: EventRecord): Promise<readonly EventRecord[]>;
|
|
8
|
+
export declare function appendWorkflowEventIfRunCurrent(storage: WorkflowStorage, namespace: string, current: RunRecord, event: EventRecord): Promise<readonly EventRecord[] | undefined>;
|
|
9
|
+
export declare function getWorkflowEvents(storage: WorkflowStorage, namespace: string, runId: RunId): Promise<readonly EventRecord[]>;
|
|
10
|
+
export type EventAppendSuccessOutcome = {
|
|
11
|
+
readonly status: "appended";
|
|
12
|
+
readonly events: readonly EventRecord[];
|
|
13
|
+
readonly previousEventHistory?: StorageValue;
|
|
14
|
+
} | {
|
|
15
|
+
readonly status: "duplicate";
|
|
16
|
+
readonly events: readonly EventRecord[];
|
|
17
|
+
};
|
|
18
|
+
type EventAppendOutcome = EventAppendSuccessOutcome | {
|
|
19
|
+
readonly status: "staleRun";
|
|
20
|
+
};
|
|
21
|
+
interface EventAppendAtomicProjectionPlan {
|
|
22
|
+
readonly item?: StorageCompareAndSetManyItem<StorageValue>;
|
|
23
|
+
}
|
|
24
|
+
type EventAppendAtomicProjectionPlanner = (attempt: number) => Promise<EventAppendAtomicProjectionPlan | undefined>;
|
|
25
|
+
interface EventAppendProjectionOutcome {
|
|
26
|
+
readonly outcome: EventAppendOutcome;
|
|
27
|
+
readonly projectionPipeline?: AppendProjectionPipeline;
|
|
28
|
+
}
|
|
29
|
+
export declare function appendEventWithProjections(storage: WorkflowStorage, namespace: string, runId: RunId, event: EventRecord, projectionPipeline?: AppendProjectionPipeline): Promise<EventAppendSuccessOutcome>;
|
|
30
|
+
export declare function appendEventWithProjectionPipelineIfRunCurrent(storage: WorkflowStorage, namespace: string, currentRun: RunRecord, event: EventRecord): Promise<EventAppendProjectionOutcome>;
|
|
31
|
+
interface AppendProjectionPipeline {
|
|
32
|
+
readonly materializesAtomically: boolean;
|
|
33
|
+
readonly planAtomicProjections?: EventAppendAtomicProjectionPlanner;
|
|
34
|
+
finalize(outcome: EventAppendSuccessOutcome): Promise<readonly EventRecord[]>;
|
|
35
|
+
finalizePostCommit(outcome: EventAppendSuccessOutcome): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export declare function getStoredEventHistory(storage: WorkflowStorage, key: string): Promise<{
|
|
38
|
+
readonly raw: StorageValue | undefined;
|
|
39
|
+
readonly events: readonly EventRecord[];
|
|
40
|
+
}>;
|
|
41
|
+
export declare function getStoredCleanupEventHistory(storage: WorkflowStorage, key: string): Promise<{
|
|
42
|
+
readonly raw: StorageValue | undefined;
|
|
43
|
+
readonly events: readonly EventRecord[];
|
|
44
|
+
}>;
|
|
45
|
+
export declare function isSameEventIdentity(left: EventRecord, right: EventRecord): boolean;
|
|
46
|
+
export declare function rollbackAppendedEventIfCurrent(storage: WorkflowStorage, namespace: string, runId: RunId, expectedEvents: readonly EventRecord[], previousEventHistory?: StorageValue): Promise<boolean>;
|
|
47
|
+
//#endregion
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { WorkflowErrorCode } from "../errors/codes.mjs";
|
|
2
|
+
import { WorkflowStateError } from "../errors/base.mjs";
|
|
3
|
+
import "../errors/mod.mjs";
|
|
4
|
+
import { makeEventsKey, makeRunKey } from "../store-keys.mjs";
|
|
5
|
+
import { eventFieldsMatch, getEventDescriptor, getEventField, isCleanupEventRecord } from "../events/descriptors.mjs";
|
|
6
|
+
import { supportsAtomicBatchWrite, supportsConditionalWrite } from "./capabilities.mjs";
|
|
7
|
+
import { toStorageValue } from "./storage-value.mjs";
|
|
8
|
+
import { isReadableEventRecord, requireReadableStoreRun } from "./validation.mjs";
|
|
9
|
+
import { isRunStaleForAppend, isStoredRunRevisionCurrent, requireReadableStoredRun, rollbackAppendedEventIfRunStale } from "./run.mjs";
|
|
10
|
+
import { duplicateMessageAppendOutcome, projectMessageIdempotencyIndexForAppendOutcome } from "./indexes.mjs";
|
|
11
|
+
import { createStepAttemptMaterializationStoragePlan, materializeStepAttemptForAppendOutcome } from "./materialization.mjs";
|
|
12
|
+
import { deepEquals, isString } from "@temelj/value";
|
|
13
|
+
//#region src/store/events.ts
|
|
14
|
+
async function finalizeAppendOutcome(outcome, projectionPipeline) {
|
|
15
|
+
if (outcome.status === "staleRun") return;
|
|
16
|
+
if (projectionPipeline === void 0) throw new WorkflowStateError("Cannot finalize workflow event append without an append projection pipeline.", { code: WorkflowErrorCode.STATE_APPEND_PROJECTION_PIPELINE_MISSING });
|
|
17
|
+
return await projectionPipeline.finalize(outcome);
|
|
18
|
+
}
|
|
19
|
+
async function appendWorkflowEvent(storage, namespace, runId, event) {
|
|
20
|
+
await requireReadableStoredRun(storage, namespace, runId);
|
|
21
|
+
const projectionPipeline = await createAppendProjectionPipeline(storage, namespace, runId, event);
|
|
22
|
+
return await finalizeAppendOutcome(await appendEventWithProjections(storage, namespace, runId, event, projectionPipeline), projectionPipeline);
|
|
23
|
+
}
|
|
24
|
+
async function appendWorkflowEventIfRunCurrent(storage, namespace, current, event) {
|
|
25
|
+
requireReadableStoreRun(current, namespace);
|
|
26
|
+
const appendOutcome = await appendEventWithProjectionPipelineIfRunCurrent(storage, namespace, current, event);
|
|
27
|
+
return await finalizeAppendOutcome(appendOutcome.outcome, appendOutcome.projectionPipeline);
|
|
28
|
+
}
|
|
29
|
+
async function getWorkflowEvents(storage, namespace, runId) {
|
|
30
|
+
return (await getStoredEventHistory(storage, makeEventsKey(namespace, runId))).events;
|
|
31
|
+
}
|
|
32
|
+
const MAX_APPEND_EVENT_ATTEMPTS = 16;
|
|
33
|
+
function makeAppendedEventOutcome(events, previousEventHistory) {
|
|
34
|
+
return {
|
|
35
|
+
status: "appended",
|
|
36
|
+
events,
|
|
37
|
+
previousEventHistory
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function makeStaleRunAppendOutcome() {
|
|
41
|
+
return { status: "staleRun" };
|
|
42
|
+
}
|
|
43
|
+
async function appendEventWithAtomicProjectionPlan(storage, namespace, runId, event, planProjection, detectDuplicate) {
|
|
44
|
+
if (!supportsAtomicBatchWrite(storage)) return await appendEventIfCurrent(storage, namespace, runId, event, {
|
|
45
|
+
detectDuplicate,
|
|
46
|
+
previousEventHistory: await storage.get(makeEventsKey(namespace, runId))
|
|
47
|
+
});
|
|
48
|
+
const eventsStorageKey = makeEventsKey(namespace, runId);
|
|
49
|
+
return await retryEventAppend(storage, eventsStorageKey, runId, event, detectDuplicate, async (appendState, attempt) => {
|
|
50
|
+
const projectionPlan = await planProjection?.(attempt);
|
|
51
|
+
return await storage.compareAndSetMany([createEventHistoryCompareAndSetItem(eventsStorageKey, appendState.raw, appendState.nextEvents), ...projectionPlan?.item === void 0 ? [] : [projectionPlan.item]]);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async function appendEventIfRunRevisionCurrentAtomically(storage, namespace, currentRun, event, detectDuplicate) {
|
|
55
|
+
const runId = currentRun.id;
|
|
56
|
+
const runStorageKey = makeRunKey(namespace, runId);
|
|
57
|
+
const eventsStorageKey = makeEventsKey(namespace, runId);
|
|
58
|
+
for (let attempt = 0; attempt < MAX_APPEND_EVENT_ATTEMPTS; attempt++) {
|
|
59
|
+
const appendState = await readEventAppendState(storage, eventsStorageKey, runId, event, detectDuplicate);
|
|
60
|
+
const duplicate = appendState.duplicate;
|
|
61
|
+
if (duplicate !== void 0) {
|
|
62
|
+
if (await storage.compareAndSetMany(createRunRevisionGuardedEventHistoryCompareAndSetItems(runStorageKey, currentRun, eventsStorageKey, appendState.raw, appendState.currentEvents))) return duplicate;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (await storage.compareAndSetMany(createRunRevisionGuardedEventHistoryCompareAndSetItems(runStorageKey, currentRun, eventsStorageKey, appendState.raw, appendState.nextEvents))) return makeAppendedEventOutcome(appendState.nextEvents, appendState.raw);
|
|
66
|
+
if (event.kind === "message_sent") return makeStaleRunAppendOutcome();
|
|
67
|
+
}
|
|
68
|
+
return makeStaleRunAppendOutcome();
|
|
69
|
+
}
|
|
70
|
+
async function appendEventIfCurrent(storage, namespace, runId, event, options = {}) {
|
|
71
|
+
const key = makeEventsKey(namespace, runId);
|
|
72
|
+
if (!supportsConditionalWrite(storage)) {
|
|
73
|
+
const current = (await getStoredEventHistory(storage, key)).events;
|
|
74
|
+
const duplicate = options.detectDuplicate?.(runId, current, event);
|
|
75
|
+
if (duplicate !== void 0) return duplicate;
|
|
76
|
+
const events = [...current, event];
|
|
77
|
+
await storage.set(key, toStorageValue(events));
|
|
78
|
+
return makeAppendedEventOutcome(events, options.previousEventHistory);
|
|
79
|
+
}
|
|
80
|
+
return await retryEventAppend(storage, key, runId, event, options.detectDuplicate, async (appendState) => await storage.compareAndSet(key, appendState.raw, toStorageValue(appendState.nextEvents)));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Reads the event history, returns a detected duplicate, and otherwise retries `write` until it
|
|
84
|
+
* lands or the attempts run out.
|
|
85
|
+
*/
|
|
86
|
+
async function retryEventAppend(storage, key, runId, event, detectDuplicate, write) {
|
|
87
|
+
for (let attempt = 0; attempt < MAX_APPEND_EVENT_ATTEMPTS; attempt++) {
|
|
88
|
+
const appendState = await readEventAppendState(storage, key, runId, event, detectDuplicate);
|
|
89
|
+
if (appendState.duplicate !== void 0) return appendState.duplicate;
|
|
90
|
+
if (await write(appendState, attempt)) return makeAppendedEventOutcome(appendState.nextEvents, appendState.raw);
|
|
91
|
+
}
|
|
92
|
+
throw new WorkflowStateError(`Failed to append workflow event for run ${runId} after ${MAX_APPEND_EVENT_ATTEMPTS} attempts`, {
|
|
93
|
+
code: WorkflowErrorCode.STATE_WORKFLOW_EVENT_APPEND_FAILED,
|
|
94
|
+
details: {
|
|
95
|
+
runId,
|
|
96
|
+
attempts: MAX_APPEND_EVENT_ATTEMPTS
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async function readEventAppendState(storage, eventsStorageKey, runId, event, detectDuplicate) {
|
|
101
|
+
const { raw, events: currentEvents } = await getStoredEventHistory(storage, eventsStorageKey);
|
|
102
|
+
const duplicate = detectDuplicate?.(runId, currentEvents, event);
|
|
103
|
+
return {
|
|
104
|
+
raw,
|
|
105
|
+
currentEvents,
|
|
106
|
+
duplicate,
|
|
107
|
+
nextEvents: duplicate === void 0 ? [...currentEvents, event] : currentEvents
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
async function appendEventWithProjections(storage, namespace, runId, event, projectionPipeline) {
|
|
111
|
+
const appendProjectionPipeline = projectionPipeline ?? await createAppendProjectionPipeline(storage, namespace, runId, event);
|
|
112
|
+
const outcome = await appendEventWithAtomicProjectionPlan(storage, namespace, runId, event, appendProjectionPipeline.planAtomicProjections, duplicateMessageAppendOutcome);
|
|
113
|
+
await appendProjectionPipeline.finalizePostCommit(outcome);
|
|
114
|
+
return outcome;
|
|
115
|
+
}
|
|
116
|
+
async function appendEventWithProjectionPipelineIfRunCurrent(storage, namespace, currentRun, event) {
|
|
117
|
+
const runId = currentRun.id;
|
|
118
|
+
if (isRunStaleForAppend(currentRun, event)) return { outcome: makeStaleRunAppendOutcome() };
|
|
119
|
+
const projectionPipeline = await createAppendProjectionPipeline(storage, namespace, runId, event);
|
|
120
|
+
if (event.kind === "message_sent" && !supportsAtomicBatchWrite(storage)) return await appendMessageEventIfRunCurrent(storage, namespace, currentRun, event, projectionPipeline);
|
|
121
|
+
if (!supportsAtomicBatchWrite(storage) || projectionPipeline.materializesAtomically) return workflowEventAppendProjectionOutcome(await appendEventIfRunRevisionCurrentWithPostAppendGuard(storage, namespace, currentRun, event, projectionPipeline), projectionPipeline);
|
|
122
|
+
return workflowEventAppendProjectionOutcome(await appendEventIfRunRevisionCurrentAtomically(storage, namespace, currentRun, event, duplicateMessageAppendOutcome), projectionPipeline);
|
|
123
|
+
}
|
|
124
|
+
function workflowEventAppendProjectionOutcome(outcome, projectionPipeline) {
|
|
125
|
+
if (projectionPipeline === void 0) return { outcome };
|
|
126
|
+
return {
|
|
127
|
+
outcome,
|
|
128
|
+
projectionPipeline
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
async function appendEventIfRunRevisionCurrentWithPostAppendGuard(storage, namespace, currentRun, event, projectionPipeline) {
|
|
132
|
+
const runId = currentRun.id;
|
|
133
|
+
if (!await isStoredRunRevisionCurrent(storage, namespace, currentRun)) return makeStaleRunAppendOutcome();
|
|
134
|
+
const outcome = await appendEventWithProjections(storage, namespace, runId, event, projectionPipeline);
|
|
135
|
+
if (outcome.status !== "appended") return outcome;
|
|
136
|
+
return await guardAppendedEventAgainstStaleRun(storage, namespace, runId, event, outcome);
|
|
137
|
+
}
|
|
138
|
+
async function appendMessageEventIfRunCurrent(storage, namespace, currentRun, event, projectionPipeline) {
|
|
139
|
+
const runId = currentRun.id;
|
|
140
|
+
if (!await isStoredRunRevisionCurrent(storage, namespace, currentRun)) return { outcome: makeStaleRunAppendOutcome() };
|
|
141
|
+
if (!supportsConditionalWrite(storage)) {
|
|
142
|
+
const outcome = await appendEventWithProjections(storage, namespace, runId, event, projectionPipeline);
|
|
143
|
+
if (outcome.status !== "appended") return {
|
|
144
|
+
outcome,
|
|
145
|
+
projectionPipeline
|
|
146
|
+
};
|
|
147
|
+
return {
|
|
148
|
+
outcome: await guardAppendedEventAgainstStaleRun(storage, namespace, runId, event, outcome),
|
|
149
|
+
projectionPipeline
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
const outcome = await appendEventIfCurrent(storage, namespace, runId, event, { detectDuplicate: duplicateMessageAppendOutcome });
|
|
153
|
+
if (outcome.status !== "appended") {
|
|
154
|
+
if (!await isStoredRunRevisionCurrent(storage, namespace, currentRun)) return {
|
|
155
|
+
outcome: makeStaleRunAppendOutcome(),
|
|
156
|
+
projectionPipeline
|
|
157
|
+
};
|
|
158
|
+
return {
|
|
159
|
+
outcome,
|
|
160
|
+
projectionPipeline
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (!await isStoredRunRevisionCurrent(storage, namespace, currentRun)) {
|
|
164
|
+
await guardAppendedEventAgainstStaleRun(storage, namespace, runId, event, outcome);
|
|
165
|
+
return {
|
|
166
|
+
outcome: makeStaleRunAppendOutcome(),
|
|
167
|
+
projectionPipeline
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
outcome: await guardAppendedEventAgainstStaleRun(storage, namespace, runId, event, outcome),
|
|
172
|
+
projectionPipeline
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async function guardAppendedEventAgainstStaleRun(storage, namespace, runId, event, outcome) {
|
|
176
|
+
if (await rollbackAppendedEventIfRunStale(storage, namespace, runId, event, outcome.events)) return makeStaleRunAppendOutcome();
|
|
177
|
+
return outcome;
|
|
178
|
+
}
|
|
179
|
+
async function createAppendProjectionPipeline(storage, namespace, runId, event) {
|
|
180
|
+
if (!supportsAtomicBatchWrite(storage)) return createAppendProjectionPipelineFromStepAttemptPlan(storage, namespace, runId, event, void 0);
|
|
181
|
+
return createAppendProjectionPipelineFromStepAttemptPlan(storage, namespace, runId, event, await createStepAttemptMaterializationStoragePlan(storage, namespace, runId, event));
|
|
182
|
+
}
|
|
183
|
+
function createAppendProjectionPipelineFromStepAttemptPlan(storage, namespace, runId, event, initialStepAttemptPlan) {
|
|
184
|
+
return {
|
|
185
|
+
materializesAtomically: initialStepAttemptPlan?.materializes === true,
|
|
186
|
+
planAtomicProjections: createAppendAtomicProjectionPlanner(storage, namespace, runId, event, initialStepAttemptPlan),
|
|
187
|
+
async finalize(outcome) {
|
|
188
|
+
return await projectMessageIdempotencyIndexForAppendOutcome(storage, namespace, runId, event, outcome);
|
|
189
|
+
},
|
|
190
|
+
async finalizePostCommit(outcome) {
|
|
191
|
+
if (!supportsAtomicBatchWrite(storage)) await materializeStepAttemptForAppendOutcome(storage, namespace, runId, event, outcome);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function createAppendAtomicProjectionPlanner(storage, namespace, runId, event, initialStepAttemptPlan) {
|
|
196
|
+
if (!supportsAtomicBatchWrite(storage)) return;
|
|
197
|
+
return async (attempt) => attempt === 0 && initialStepAttemptPlan !== void 0 ? initialStepAttemptPlan : await createStepAttemptMaterializationStoragePlan(storage, namespace, runId, event);
|
|
198
|
+
}
|
|
199
|
+
async function getStoredEventHistory(storage, key) {
|
|
200
|
+
const raw = await storage.get(key);
|
|
201
|
+
return {
|
|
202
|
+
raw,
|
|
203
|
+
events: Array.isArray(raw) ? raw.filter(isReadableEventRecord) : []
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async function getStoredCleanupEventHistory(storage, key) {
|
|
207
|
+
const history = await getStoredEventHistory(storage, key);
|
|
208
|
+
return {
|
|
209
|
+
raw: history.raw,
|
|
210
|
+
events: history.events.filter(isCleanupEventRecord)
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function isSameEventIdentity(left, right) {
|
|
214
|
+
if (left.kind !== right.kind || Temporal.Instant.compare(left.timestamp, right.timestamp) !== 0) return false;
|
|
215
|
+
const descriptor = getEventDescriptor(left.kind);
|
|
216
|
+
return eventFieldsMatch(left, right, descriptor.identityFields) && isSameEventValueFields(left, right, descriptor.valueIdentityFields) && isSameEventStringListFields(left, right, descriptor.stringListIdentityFields);
|
|
217
|
+
}
|
|
218
|
+
function isSameEventValueFields(left, right, fields = []) {
|
|
219
|
+
return fields.every((field) => deepEquals(getEventField(left, field), getEventField(right, field)));
|
|
220
|
+
}
|
|
221
|
+
function isSameEventStringListFields(left, right, fields = []) {
|
|
222
|
+
return fields.every((field) => {
|
|
223
|
+
const leftValue = getEventField(left, field);
|
|
224
|
+
const rightValue = getEventField(right, field);
|
|
225
|
+
const leftValues = Array.isArray(leftValue) && leftValue.every((item) => isString(item) && item.trim() !== "") ? leftValue : void 0;
|
|
226
|
+
const rightValues = Array.isArray(rightValue) && rightValue.every((item) => isString(item) && item.trim() !== "") ? rightValue : void 0;
|
|
227
|
+
if (leftValues === void 0 || rightValues === void 0) return leftValues === rightValues;
|
|
228
|
+
if (leftValues.length !== rightValues.length) return false;
|
|
229
|
+
return leftValues.every((value, index) => value === rightValues[index]);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
async function rollbackAppendedEventIfCurrent(storage, namespace, runId, expectedEvents, previousEventHistory) {
|
|
233
|
+
if (expectedEvents.length === 0) return false;
|
|
234
|
+
const key = makeEventsKey(namespace, runId);
|
|
235
|
+
const rolledBackEvents = expectedEvents.slice(0, -1);
|
|
236
|
+
if (supportsConditionalWrite(storage)) return await storage.compareAndSet(key, toStorageValue(expectedEvents), previousEventHistory ?? toStorageValue(rolledBackEvents));
|
|
237
|
+
const current = (await getStoredEventHistory(storage, key)).events;
|
|
238
|
+
const expectedLast = expectedEvents.at(-1);
|
|
239
|
+
const currentLast = current.at(-1);
|
|
240
|
+
if (current.length !== expectedEvents.length || expectedLast === void 0 || currentLast === void 0 || !isSameEventIdentity(currentLast, expectedLast)) return false;
|
|
241
|
+
await storage.set(key, previousEventHistory ?? toStorageValue(rolledBackEvents));
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
function createEventHistoryCompareAndSetItem(eventsStorageKey, expected, events) {
|
|
245
|
+
return {
|
|
246
|
+
key: eventsStorageKey,
|
|
247
|
+
expected,
|
|
248
|
+
value: toStorageValue(events)
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function createRunRevisionCompareAndSetItem(runStorageKey, currentRun) {
|
|
252
|
+
const value = toStorageValue(currentRun);
|
|
253
|
+
return {
|
|
254
|
+
key: runStorageKey,
|
|
255
|
+
expected: value,
|
|
256
|
+
value
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function createRunRevisionGuardedEventHistoryCompareAndSetItems(runStorageKey, currentRun, eventsStorageKey, expectedEvents, events) {
|
|
260
|
+
return [createRunRevisionCompareAndSetItem(runStorageKey, currentRun), createEventHistoryCompareAndSetItem(eventsStorageKey, expectedEvents, events)];
|
|
261
|
+
}
|
|
262
|
+
//#endregion
|
|
263
|
+
export { appendEventWithProjectionPipelineIfRunCurrent, appendEventWithProjections, appendWorkflowEvent, appendWorkflowEventIfRunCurrent, getStoredCleanupEventHistory, getStoredEventHistory, getWorkflowEvents, isSameEventIdentity, rollbackAppendedEventIfCurrent };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RunId } from "../types/ids.mjs";
|
|
2
|
+
import { RunRecord } from "../types/run.mjs";
|
|
3
|
+
import { EventRecord } from "../types/events.mjs";
|
|
4
|
+
import { IdempotencyKeyOptions, MessageIdempotencyIndex, WorkflowStorage } from "../types/store.mjs";
|
|
5
|
+
import { EventAppendSuccessOutcome } from "./events.mjs";
|
|
6
|
+
//#region src/store/indexes.d.ts
|
|
7
|
+
interface DuplicateMessageAppendOutcome {
|
|
8
|
+
readonly status: "duplicate";
|
|
9
|
+
readonly events: readonly EventRecord[];
|
|
10
|
+
}
|
|
11
|
+
export declare function duplicateMessageAppendOutcome(runId: RunId, events: readonly EventRecord[], event: EventRecord): DuplicateMessageAppendOutcome | undefined;
|
|
12
|
+
export declare function projectMessageIdempotencyIndexForAppendOutcome(storage: WorkflowStorage, namespace: string, runId: RunId, event: EventRecord, outcome: EventAppendSuccessOutcome): Promise<readonly EventRecord[]>;
|
|
13
|
+
export declare function repairMessageIdempotencyIndexes(storage: WorkflowStorage, namespace: string, runId: RunId): Promise<readonly MessageIdempotencyIndex[]>;
|
|
14
|
+
export declare function hasMessageIdempotencyKey(storage: WorkflowStorage, namespace: string, runId: RunId, idempotencyKey: string): Promise<boolean>;
|
|
15
|
+
export declare function messageIdempotencyIndexValuesFromEvents(events: readonly EventRecord[], runId: RunId): readonly {
|
|
16
|
+
readonly idempotencyKey: string;
|
|
17
|
+
readonly value: MessageIdempotencyIndex;
|
|
18
|
+
}[];
|
|
19
|
+
interface IdempotencyRunReader {
|
|
20
|
+
getRun(runId: string): Promise<RunRecord | undefined>;
|
|
21
|
+
}
|
|
22
|
+
export declare function createRunWithIdempotency(storage: WorkflowStorage, namespace: string, store: IdempotencyRunReader, run: RunRecord): Promise<RunRecord>;
|
|
23
|
+
export declare function getRunByIdempotencyKey(storage: WorkflowStorage, namespace: string, store: IdempotencyRunReader, options: IdempotencyKeyOptions): Promise<RunRecord | undefined>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { WorkflowStateError } from "../errors/base.mjs";
|
|
2
|
+
import { WorkflowMessageIdempotencyConflictError } from "../errors/message.mjs";
|
|
3
|
+
import "../errors/mod.mjs";
|
|
4
|
+
import { makeEventsKey, makeIdempotencyKey, makeMessageIdempotencyKey, makeRunKey } from "../store-keys.mjs";
|
|
5
|
+
import { History } from "../history/replay.mjs";
|
|
6
|
+
import { supportsAtomicBatchWrite, supportsConditionalWrite } from "./capabilities.mjs";
|
|
7
|
+
import { toStorageValue } from "./storage-value.mjs";
|
|
8
|
+
import { isReadableRunRecord, isSameMessageIdempotencyIndex } from "./validation.mjs";
|
|
9
|
+
import { requireReadableStoredRun } from "./run.mjs";
|
|
10
|
+
import { getStoredEventHistory, rollbackAppendedEventIfCurrent } from "./events.mjs";
|
|
11
|
+
import { deepEquals, isString } from "@temelj/value";
|
|
12
|
+
//#region src/store/indexes.ts
|
|
13
|
+
function duplicateMessageAppendOutcome(runId, events, event) {
|
|
14
|
+
if (!isMessageIdempotencyEvent(event)) return;
|
|
15
|
+
const existing = new History(events).messageByIdempotencyKey(event.idempotencyKey);
|
|
16
|
+
if (existing === void 0) return;
|
|
17
|
+
requireDuplicateMessageEventMatches(runId, existing, event);
|
|
18
|
+
return {
|
|
19
|
+
status: "duplicate",
|
|
20
|
+
events
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function isMessageIdempotencyEvent(event) {
|
|
24
|
+
return event.kind === "message_sent" && event.idempotencyKey !== void 0;
|
|
25
|
+
}
|
|
26
|
+
function requireDuplicateMessageEventMatches(runId, existing, event) {
|
|
27
|
+
if (existing.messageId === event.messageId && deepEquals(existing.payload, event.payload)) return;
|
|
28
|
+
WorkflowMessageIdempotencyConflictError.conflict({
|
|
29
|
+
runId,
|
|
30
|
+
messageId: existing.messageId,
|
|
31
|
+
idempotencyKey: event.idempotencyKey
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async function indexMessageIdempotencyKey(storage, namespace, runId, event, events) {
|
|
35
|
+
if (event.kind !== "message_sent" || event.idempotencyKey === void 0) return;
|
|
36
|
+
await requireReadableStoredRun(storage, namespace, runId);
|
|
37
|
+
const indexedEvent = indexableMessageEventByIdempotencyKey(new History(events), event.idempotencyKey);
|
|
38
|
+
if (indexedEvent === void 0) return;
|
|
39
|
+
const key = makeMessageIdempotencyKey(namespace, runId, event.idempotencyKey);
|
|
40
|
+
const value = {
|
|
41
|
+
runId,
|
|
42
|
+
messageId: indexedEvent.messageId,
|
|
43
|
+
timestamp: indexedEvent.timestamp
|
|
44
|
+
};
|
|
45
|
+
if (!supportsConditionalWrite(storage)) {
|
|
46
|
+
const current = await storage.get(key);
|
|
47
|
+
if (current !== void 0) {
|
|
48
|
+
if (isSameMessageIdempotencyIndex(current, value)) return;
|
|
49
|
+
WorkflowMessageIdempotencyConflictError.conflict({
|
|
50
|
+
runId,
|
|
51
|
+
messageId: indexedEvent.messageId,
|
|
52
|
+
idempotencyKey: event.idempotencyKey
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
await storage.set(key, toStorageValue(value));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (await storage.compareAndSet(key, void 0, toStorageValue(value))) return;
|
|
59
|
+
const current = await storage.get(key);
|
|
60
|
+
if (isSameMessageIdempotencyIndex(current, value)) return;
|
|
61
|
+
WorkflowMessageIdempotencyConflictError.conflict({
|
|
62
|
+
runId,
|
|
63
|
+
messageId: indexedEvent.messageId,
|
|
64
|
+
idempotencyKey: event.idempotencyKey
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async function projectMessageIdempotencyIndexForAppendOutcome(storage, namespace, runId, event, outcome) {
|
|
68
|
+
try {
|
|
69
|
+
await indexMessageIdempotencyKey(storage, namespace, runId, event, outcome.events);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (outcome.status === "appended") await rollbackAppendedEventIfCurrent(storage, namespace, runId, outcome.events, outcome.previousEventHistory);
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
return outcome.events;
|
|
75
|
+
}
|
|
76
|
+
async function reconcileMessageIdempotencyIndexes(storage, namespace, runId, events) {
|
|
77
|
+
await requireReadableStoredRun(storage, namespace, runId);
|
|
78
|
+
const indexes = messageIdempotencyIndexValuesFromEvents(events, runId);
|
|
79
|
+
await Promise.all(indexes.map(async ({ idempotencyKey, value }) => {
|
|
80
|
+
await storeMessageIdempotencyIndex(storage, namespace, runId, idempotencyKey, value);
|
|
81
|
+
}));
|
|
82
|
+
return indexes.map((index) => index.value);
|
|
83
|
+
}
|
|
84
|
+
async function repairMessageIdempotencyIndexes(storage, namespace, runId) {
|
|
85
|
+
await requireReadableStoredRun(storage, namespace, runId);
|
|
86
|
+
return await reconcileMessageIdempotencyIndexes(storage, namespace, runId, (await getStoredEventHistory(storage, makeEventsKey(namespace, runId))).events);
|
|
87
|
+
}
|
|
88
|
+
async function hasMessageIdempotencyKey(storage, namespace, runId, idempotencyKey) {
|
|
89
|
+
return await storage.get(makeMessageIdempotencyKey(namespace, runId, idempotencyKey)) !== void 0;
|
|
90
|
+
}
|
|
91
|
+
function indexableMessageEventByIdempotencyKey(history, idempotencyKey) {
|
|
92
|
+
const event = history.messageByIdempotencyKey(idempotencyKey);
|
|
93
|
+
return event !== void 0 && isIndexableMessageIdempotencyEvent(event) ? event : void 0;
|
|
94
|
+
}
|
|
95
|
+
function messageIdempotencyIndexValuesFromEvents(events, runId) {
|
|
96
|
+
return new History(events).latestMessagesByIdempotencyKey().filter(isIndexableMessageIdempotencyEvent).map((event) => ({
|
|
97
|
+
idempotencyKey: event.idempotencyKey,
|
|
98
|
+
value: {
|
|
99
|
+
runId,
|
|
100
|
+
messageId: event.messageId,
|
|
101
|
+
timestamp: event.timestamp
|
|
102
|
+
}
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
function isIndexableMessageIdempotencyEvent(event) {
|
|
106
|
+
return event.kind === "message_sent" && event.idempotencyKey !== void 0 && event.messageId.trim() !== "";
|
|
107
|
+
}
|
|
108
|
+
async function storeMessageIdempotencyIndex(storage, namespace, runId, idempotencyKey, value) {
|
|
109
|
+
const key = makeMessageIdempotencyKey(namespace, runId, idempotencyKey);
|
|
110
|
+
const current = await storage.get(key);
|
|
111
|
+
if (isSameMessageIdempotencyIndex(current, value)) return;
|
|
112
|
+
if (!supportsConditionalWrite(storage)) {
|
|
113
|
+
await storage.set(key, toStorageValue(value));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (!await storage.compareAndSet(key, current, toStorageValue(value))) WorkflowMessageIdempotencyConflictError.conflict({
|
|
117
|
+
runId,
|
|
118
|
+
messageId: value.messageId,
|
|
119
|
+
idempotencyKey
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
const MAX_IDEMPOTENT_CREATE_WAIT_ATTEMPTS = 16;
|
|
123
|
+
async function createRunWithIdempotency(storage, namespace, store, run) {
|
|
124
|
+
if (run.namespace !== namespace) throw WorkflowStateError.runNamespaceMismatch(String(run.namespace), namespace);
|
|
125
|
+
const keyOptions = idempotencyKeyOptionsForRun(run);
|
|
126
|
+
if (supportsAtomicBatchWrite(storage)) return await createRunAtomicallyWithIdempotency(storage, namespace, store, run, keyOptions);
|
|
127
|
+
const idempotencyClaim = keyOptions === void 0 ? void 0 : await claimIdempotencyIndex(storage, namespace, store, run, keyOptions);
|
|
128
|
+
if (idempotencyClaim?.status === "existing") return idempotencyClaim.run;
|
|
129
|
+
if (keyOptions !== void 0) assertIdempotencyClaimed(run.id, idempotencyClaim);
|
|
130
|
+
try {
|
|
131
|
+
await createRunRecordAndEventHistory(storage, namespace, run);
|
|
132
|
+
return run;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
await rollbackIdempotencyClaim(storage, idempotencyClaim);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function createRunRecordAndEventHistory(storage, namespace, run) {
|
|
139
|
+
const runKey = makeRunKey(namespace, run.id);
|
|
140
|
+
const eventsKey = makeEventsKey(namespace, run.id);
|
|
141
|
+
let claim = {};
|
|
142
|
+
try {
|
|
143
|
+
if (!supportsConditionalWrite(storage)) {
|
|
144
|
+
if (await storage.get(runKey) !== void 0) WorkflowStateError.runIdAlreadyExists(run.id);
|
|
145
|
+
if (await storage.get(eventsKey) !== void 0) WorkflowStateError.eventHistoryAlreadyExists(run.id);
|
|
146
|
+
await storage.set(runKey, toStorageValue(run));
|
|
147
|
+
claim = { runKey };
|
|
148
|
+
await storage.set(eventsKey, toStorageValue([]));
|
|
149
|
+
return {
|
|
150
|
+
...claim,
|
|
151
|
+
eventsKey
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (!await storage.compareAndSet(runKey, void 0, toStorageValue(run))) WorkflowStateError.runIdAlreadyExists(run.id);
|
|
155
|
+
claim = { runKey };
|
|
156
|
+
if (!await storage.compareAndSet(eventsKey, void 0, toStorageValue([]))) WorkflowStateError.eventHistoryAlreadyExists(run.id);
|
|
157
|
+
return {
|
|
158
|
+
...claim,
|
|
159
|
+
eventsKey
|
|
160
|
+
};
|
|
161
|
+
} catch (error) {
|
|
162
|
+
await rollbackRunCreationClaim(storage, claim);
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async function rollbackRunCreationClaim(storage, claim) {
|
|
167
|
+
await storage.deleteMany([...claim.runKey === void 0 ? [] : [claim.runKey], ...claim.eventsKey === void 0 ? [] : [claim.eventsKey]]);
|
|
168
|
+
}
|
|
169
|
+
async function rollbackIdempotencyClaim(storage, claim) {
|
|
170
|
+
if (claim?.status !== "claimed") return;
|
|
171
|
+
if (!supportsConditionalWrite(storage)) {
|
|
172
|
+
await storage.delete(claim.key);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
await storage.compareAndSet(claim.key, claim.value, void 0);
|
|
176
|
+
}
|
|
177
|
+
async function claimIdempotencyIndex(storage, namespace, store, run, keyOptions) {
|
|
178
|
+
const key = makeIdempotencyKey(namespace, keyOptions);
|
|
179
|
+
const value = toStorageValue(run.id);
|
|
180
|
+
if (!supportsConditionalWrite(storage)) {
|
|
181
|
+
const existingRun = await getRunByIdempotencyKey(storage, namespace, store, keyOptions);
|
|
182
|
+
if (existingRun !== void 0) return {
|
|
183
|
+
status: "existing",
|
|
184
|
+
run: existingRun
|
|
185
|
+
};
|
|
186
|
+
await storage.set(key, value);
|
|
187
|
+
return {
|
|
188
|
+
status: "claimed",
|
|
189
|
+
key,
|
|
190
|
+
value
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (await storage.compareAndSet(key, void 0, value)) return {
|
|
194
|
+
status: "claimed",
|
|
195
|
+
key,
|
|
196
|
+
value
|
|
197
|
+
};
|
|
198
|
+
const existingRun = await waitForRunByIdempotencyKey(storage, namespace, store, keyOptions);
|
|
199
|
+
if (existingRun !== void 0) return {
|
|
200
|
+
status: "existing",
|
|
201
|
+
run: existingRun
|
|
202
|
+
};
|
|
203
|
+
if (!await releaseStaleIdempotencyIndex(storage, namespace, store, keyOptions)) WorkflowStateError.idempotencyKeyClaimedWithoutRun(run.id);
|
|
204
|
+
if (await storage.compareAndSet(key, void 0, value)) return {
|
|
205
|
+
status: "claimed",
|
|
206
|
+
key,
|
|
207
|
+
value
|
|
208
|
+
};
|
|
209
|
+
const reclaimedExistingRun = await waitForRunByIdempotencyKey(storage, namespace, store, keyOptions);
|
|
210
|
+
if (reclaimedExistingRun !== void 0) return {
|
|
211
|
+
status: "existing",
|
|
212
|
+
run: reclaimedExistingRun
|
|
213
|
+
};
|
|
214
|
+
WorkflowStateError.idempotencyKeyClaimedWithoutRun(run.id);
|
|
215
|
+
}
|
|
216
|
+
function assertIdempotencyClaimed(runId, claim) {
|
|
217
|
+
if (claim?.status !== "claimed") WorkflowStateError.idempotencyKeyClaimedWithoutRun(runId);
|
|
218
|
+
}
|
|
219
|
+
async function createRunAtomicallyWithIdempotency(storage, namespace, store, run, keyOptions) {
|
|
220
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
221
|
+
if (await storage.compareAndSetMany([
|
|
222
|
+
...atomicIdempotencyClaimItems(namespace, run, keyOptions),
|
|
223
|
+
{
|
|
224
|
+
key: makeRunKey(namespace, run.id),
|
|
225
|
+
expected: void 0,
|
|
226
|
+
value: toStorageValue(run)
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
key: makeEventsKey(namespace, run.id),
|
|
230
|
+
expected: void 0,
|
|
231
|
+
value: toStorageValue([])
|
|
232
|
+
}
|
|
233
|
+
])) return run;
|
|
234
|
+
if (keyOptions === void 0) WorkflowStateError.runIdAlreadyExists(run.id);
|
|
235
|
+
const existingRun = await waitForRunByIdempotencyKey(storage, namespace, store, keyOptions);
|
|
236
|
+
if (existingRun !== void 0) return existingRun;
|
|
237
|
+
if (attempt === 0 && await releaseStaleIdempotencyIndex(storage, namespace, store, keyOptions)) continue;
|
|
238
|
+
WorkflowStateError.idempotencyKeyClaimedWithoutRun(run.id);
|
|
239
|
+
}
|
|
240
|
+
throw WorkflowStateError.runIdAlreadyExists(run.id);
|
|
241
|
+
}
|
|
242
|
+
function atomicIdempotencyClaimItems(namespace, run, keyOptions) {
|
|
243
|
+
return keyOptions === void 0 ? [] : [{
|
|
244
|
+
key: makeIdempotencyKey(namespace, keyOptions),
|
|
245
|
+
expected: void 0,
|
|
246
|
+
value: toStorageValue(run.id)
|
|
247
|
+
}];
|
|
248
|
+
}
|
|
249
|
+
async function getRunByIdempotencyKey(storage, namespace, store, options) {
|
|
250
|
+
const runId = await storage.get(makeIdempotencyKey(namespace, options));
|
|
251
|
+
if (!(isString(runId) && runId.trim() !== "")) return;
|
|
252
|
+
const run = await store.getRun(runId);
|
|
253
|
+
return run !== void 0 && isReadableRunRecord(run, run.namespace) && run.workflowName === options.workflowName && run.workflowVersion === options.workflowVersion && run.idempotencyKey === options.idempotencyKey ? run : void 0;
|
|
254
|
+
}
|
|
255
|
+
function idempotencyKeyOptionsForRun(run) {
|
|
256
|
+
if (run.idempotencyKey === void 0) return void 0;
|
|
257
|
+
return {
|
|
258
|
+
workflowName: run.workflowName,
|
|
259
|
+
workflowVersion: run.workflowVersion,
|
|
260
|
+
idempotencyKey: run.idempotencyKey
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
async function waitForRunByIdempotencyKey(storage, namespace, store, options) {
|
|
264
|
+
for (let attempt = 0; attempt < MAX_IDEMPOTENT_CREATE_WAIT_ATTEMPTS; attempt++) {
|
|
265
|
+
const run = await getRunByIdempotencyKey(storage, namespace, store, options);
|
|
266
|
+
if (run !== void 0) return run;
|
|
267
|
+
await Promise.resolve();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async function releaseStaleIdempotencyIndex(storage, namespace, store, options) {
|
|
271
|
+
if (!supportsConditionalWrite(storage)) return false;
|
|
272
|
+
const key = makeIdempotencyKey(namespace, options);
|
|
273
|
+
const value = await storage.get(key);
|
|
274
|
+
if (value === void 0) return false;
|
|
275
|
+
if (isString(value) && value.trim() !== "") {
|
|
276
|
+
const run = await store.getRun(value);
|
|
277
|
+
if (run !== void 0 && isReadableRunRecord(run, run.namespace) && run.workflowName === options.workflowName && run.workflowVersion === options.workflowVersion && run.idempotencyKey === options.idempotencyKey) return false;
|
|
278
|
+
}
|
|
279
|
+
return await storage.compareAndSet(key, value, void 0);
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
export { createRunWithIdempotency, duplicateMessageAppendOutcome, getRunByIdempotencyKey, hasMessageIdempotencyKey, messageIdempotencyIndexValuesFromEvents, projectMessageIdempotencyIndexForAppendOutcome, repairMessageIdempotencyIndexes };
|