@adonis-agora/durable 0.1.0
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 +29 -0
- package/dist/assets/dashboard.html +446 -0
- package/dist/commands/main.d.ts +15 -0
- package/dist/commands/main.d.ts.map +1 -0
- package/dist/commands/main.js +15 -0
- package/dist/commands/main.js.map +1 -0
- package/dist/commands/retry.d.ts +16 -0
- package/dist/commands/retry.d.ts.map +1 -0
- package/dist/commands/retry.js +34 -0
- package/dist/commands/retry.js.map +1 -0
- package/dist/commands/runs.d.ts +17 -0
- package/dist/commands/runs.d.ts.map +1 -0
- package/dist/commands/runs.js +40 -0
- package/dist/commands/runs.js.map +1 -0
- package/dist/commands/work.d.ts +18 -0
- package/dist/commands/work.d.ts.map +1 -0
- package/dist/commands/work.js +58 -0
- package/dist/commands/work.js.map +1 -0
- package/dist/configure.d.ts +15 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +26 -0
- package/dist/configure.js.map +1 -0
- package/dist/providers/dashboard_provider.d.ts +27 -0
- package/dist/providers/dashboard_provider.d.ts.map +1 -0
- package/dist/providers/dashboard_provider.js +94 -0
- package/dist/providers/dashboard_provider.js.map +1 -0
- package/dist/providers/durable_provider.d.ts +36 -0
- package/dist/providers/durable_provider.d.ts.map +1 -0
- package/dist/providers/durable_provider.js +113 -0
- package/dist/providers/durable_provider.js.map +1 -0
- package/dist/src/admission-redis/index.d.ts +2 -0
- package/dist/src/admission-redis/index.d.ts.map +1 -0
- package/dist/src/admission-redis/index.js +2 -0
- package/dist/src/admission-redis/index.js.map +1 -0
- package/dist/src/admission-redis/redis-admission-backend.d.ts +83 -0
- package/dist/src/admission-redis/redis-admission-backend.d.ts.map +1 -0
- package/dist/src/admission-redis/redis-admission-backend.js +200 -0
- package/dist/src/admission-redis/redis-admission-backend.js.map +1 -0
- package/dist/src/admission.d.ts +49 -0
- package/dist/src/admission.d.ts.map +1 -0
- package/dist/src/admission.js +30 -0
- package/dist/src/admission.js.map +1 -0
- package/dist/src/backoff.d.ts +5 -0
- package/dist/src/backoff.d.ts.map +1 -0
- package/dist/src/backoff.js +11 -0
- package/dist/src/backoff.js.map +1 -0
- package/dist/src/checkpoints.d.ts +42 -0
- package/dist/src/checkpoints.d.ts.map +1 -0
- package/dist/src/checkpoints.js +57 -0
- package/dist/src/checkpoints.js.map +1 -0
- package/dist/src/codec-state-store.d.ts +60 -0
- package/dist/src/codec-state-store.d.ts.map +1 -0
- package/dist/src/codec-state-store.js +129 -0
- package/dist/src/codec-state-store.js.map +1 -0
- package/dist/src/commands/index.d.ts +3 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/index.js +3 -0
- package/dist/src/commands/index.js.map +1 -0
- package/dist/src/commands/runs.d.ts +24 -0
- package/dist/src/commands/runs.d.ts.map +1 -0
- package/dist/src/commands/runs.js +39 -0
- package/dist/src/commands/runs.js.map +1 -0
- package/dist/src/commands/worker.d.ts +61 -0
- package/dist/src/commands/worker.d.ts.map +1 -0
- package/dist/src/commands/worker.js +74 -0
- package/dist/src/commands/worker.js.map +1 -0
- package/dist/src/completion.d.ts +15 -0
- package/dist/src/completion.d.ts.map +1 -0
- package/dist/src/completion.js +10 -0
- package/dist/src/completion.js.map +1 -0
- package/dist/src/dashboard/define_config.d.ts +48 -0
- package/dist/src/dashboard/define_config.d.ts.map +1 -0
- package/dist/src/dashboard/define_config.js +57 -0
- package/dist/src/dashboard/define_config.js.map +1 -0
- package/dist/src/dashboard/handlers.d.ts +47 -0
- package/dist/src/dashboard/handlers.d.ts.map +1 -0
- package/dist/src/dashboard/handlers.js +163 -0
- package/dist/src/dashboard/handlers.js.map +1 -0
- package/dist/src/dashboard/html.d.ts +7 -0
- package/dist/src/dashboard/html.d.ts.map +1 -0
- package/dist/src/dashboard/html.js +24 -0
- package/dist/src/dashboard/html.js.map +1 -0
- package/dist/src/dashboard/index.d.ts +8 -0
- package/dist/src/dashboard/index.d.ts.map +1 -0
- package/dist/src/dashboard/index.js +6 -0
- package/dist/src/dashboard/index.js.map +1 -0
- package/dist/src/define_config.d.ts +72 -0
- package/dist/src/define_config.d.ts.map +1 -0
- package/dist/src/define_config.js +8 -0
- package/dist/src/define_config.js.map +1 -0
- package/dist/src/diagnostics-bridge.d.ts +22 -0
- package/dist/src/diagnostics-bridge.d.ts.map +1 -0
- package/dist/src/diagnostics-bridge.js +25 -0
- package/dist/src/diagnostics-bridge.js.map +1 -0
- package/dist/src/duration.d.ts +6 -0
- package/dist/src/duration.d.ts.map +1 -0
- package/dist/src/duration.js +39 -0
- package/dist/src/duration.js.map +1 -0
- package/dist/src/engine.d.ts +583 -0
- package/dist/src/engine.d.ts.map +1 -0
- package/dist/src/engine.js +1894 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/entities.d.ts +44 -0
- package/dist/src/entities.d.ts.map +1 -0
- package/dist/src/entities.js +64 -0
- package/dist/src/entities.js.map +1 -0
- package/dist/src/errors.d.ts +68 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +102 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/event-accumulators.d.ts +39 -0
- package/dist/src/event-accumulators.d.ts.map +1 -0
- package/dist/src/event-accumulators.js +70 -0
- package/dist/src/event-accumulators.js.map +1 -0
- package/dist/src/events.d.ts +9 -0
- package/dist/src/events.d.ts.map +1 -0
- package/dist/src/events.js +35 -0
- package/dist/src/events.js.map +1 -0
- package/dist/src/index.d.ts +36 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +37 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces.d.ts +909 -0
- package/dist/src/interfaces.d.ts.map +1 -0
- package/dist/src/interfaces.js +2 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/metrics.d.ts +44 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +78 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/otel/durable-metrics.d.ts +42 -0
- package/dist/src/otel/durable-metrics.d.ts.map +1 -0
- package/dist/src/otel/durable-metrics.js +75 -0
- package/dist/src/otel/durable-metrics.js.map +1 -0
- package/dist/src/otel/durable-otel.d.ts +20 -0
- package/dist/src/otel/durable-otel.d.ts.map +1 -0
- package/dist/src/otel/durable-otel.js +74 -0
- package/dist/src/otel/durable-otel.js.map +1 -0
- package/dist/src/otel/index.d.ts +4 -0
- package/dist/src/otel/index.d.ts.map +1 -0
- package/dist/src/otel/index.js +4 -0
- package/dist/src/otel/index.js.map +1 -0
- package/dist/src/otel/traceparent.d.ts +17 -0
- package/dist/src/otel/traceparent.d.ts.map +1 -0
- package/dist/src/otel/traceparent.js +21 -0
- package/dist/src/otel/traceparent.js.map +1 -0
- package/dist/src/pollers.d.ts +33 -0
- package/dist/src/pollers.d.ts.map +1 -0
- package/dist/src/pollers.js +76 -0
- package/dist/src/pollers.js.map +1 -0
- package/dist/src/protocol.d.ts +17 -0
- package/dist/src/protocol.d.ts.map +1 -0
- package/dist/src/protocol.js +47 -0
- package/dist/src/protocol.js.map +1 -0
- package/dist/src/queue.d.ts +113 -0
- package/dist/src/queue.d.ts.map +1 -0
- package/dist/src/queue.js +128 -0
- package/dist/src/queue.js.map +1 -0
- package/dist/src/remote-step-factory.d.ts +15 -0
- package/dist/src/remote-step-factory.d.ts.map +1 -0
- package/dist/src/remote-step-factory.js +12 -0
- package/dist/src/remote-step-factory.js.map +1 -0
- package/dist/src/remote-workflow-executor.d.ts +24 -0
- package/dist/src/remote-workflow-executor.d.ts.map +1 -0
- package/dist/src/remote-workflow-executor.js +70 -0
- package/dist/src/remote-workflow-executor.js.map +1 -0
- package/dist/src/scheduler.d.ts +67 -0
- package/dist/src/scheduler.d.ts.map +1 -0
- package/dist/src/scheduler.js +111 -0
- package/dist/src/scheduler.js.map +1 -0
- package/dist/src/search-attributes.d.ts +48 -0
- package/dist/src/search-attributes.d.ts.map +1 -0
- package/dist/src/search-attributes.js +98 -0
- package/dist/src/search-attributes.js.map +1 -0
- package/dist/src/singleton-gate.d.ts +44 -0
- package/dist/src/singleton-gate.d.ts.map +1 -0
- package/dist/src/singleton-gate.js +90 -0
- package/dist/src/singleton-gate.js.map +1 -0
- package/dist/src/step-logger.d.ts +9 -0
- package/dist/src/step-logger.d.ts.map +1 -0
- package/dist/src/step-logger.js +89 -0
- package/dist/src/step-logger.js.map +1 -0
- package/dist/src/stores/factory.d.ts +42 -0
- package/dist/src/stores/factory.d.ts.map +1 -0
- package/dist/src/stores/factory.js +29 -0
- package/dist/src/stores/factory.js.map +1 -0
- package/dist/src/stores/lucid-helpers.d.ts +11 -0
- package/dist/src/stores/lucid-helpers.d.ts.map +1 -0
- package/dist/src/stores/lucid-helpers.js +38 -0
- package/dist/src/stores/lucid-helpers.js.map +1 -0
- package/dist/src/stores/lucid-mappers.d.ts +58 -0
- package/dist/src/stores/lucid-mappers.d.ts.map +1 -0
- package/dist/src/stores/lucid-mappers.js +174 -0
- package/dist/src/stores/lucid-mappers.js.map +1 -0
- package/dist/src/stores/lucid-schema.d.ts +28 -0
- package/dist/src/stores/lucid-schema.d.ts.map +1 -0
- package/dist/src/stores/lucid-schema.js +115 -0
- package/dist/src/stores/lucid-schema.js.map +1 -0
- package/dist/src/stores/lucid.d.ts +69 -0
- package/dist/src/stores/lucid.d.ts.map +1 -0
- package/dist/src/stores/lucid.js +342 -0
- package/dist/src/stores/lucid.js.map +1 -0
- package/dist/src/telescope/dashboard.d.ts +15 -0
- package/dist/src/telescope/dashboard.d.ts.map +1 -0
- package/dist/src/telescope/dashboard.js +113 -0
- package/dist/src/telescope/dashboard.js.map +1 -0
- package/dist/src/telescope/data-providers.d.ts +20 -0
- package/dist/src/telescope/data-providers.d.ts.map +1 -0
- package/dist/src/telescope/data-providers.js +322 -0
- package/dist/src/telescope/data-providers.js.map +1 -0
- package/dist/src/telescope/extension.d.ts +22 -0
- package/dist/src/telescope/extension.d.ts.map +1 -0
- package/dist/src/telescope/extension.js +38 -0
- package/dist/src/telescope/extension.js.map +1 -0
- package/dist/src/telescope/index.d.ts +5 -0
- package/dist/src/telescope/index.d.ts.map +1 -0
- package/dist/src/telescope/index.js +4 -0
- package/dist/src/telescope/index.js.map +1 -0
- package/dist/src/telescope/telescope-sdk.d.ts +123 -0
- package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
- package/dist/src/telescope/telescope-sdk.js +12 -0
- package/dist/src/telescope/telescope-sdk.js.map +1 -0
- package/dist/src/test-helpers.d.ts +11 -0
- package/dist/src/test-helpers.d.ts.map +1 -0
- package/dist/src/test-helpers.js +12 -0
- package/dist/src/test-helpers.js.map +1 -0
- package/dist/src/testing/in-memory-state-store.d.ts +64 -0
- package/dist/src/testing/in-memory-state-store.d.ts.map +1 -0
- package/dist/src/testing/in-memory-state-store.js +259 -0
- package/dist/src/testing/in-memory-state-store.js.map +1 -0
- package/dist/src/testing/in-memory-transport.d.ts +25 -0
- package/dist/src/testing/in-memory-transport.d.ts.map +1 -0
- package/dist/src/testing/in-memory-transport.js +49 -0
- package/dist/src/testing/in-memory-transport.js.map +1 -0
- package/dist/src/testing-kit/admission-backend-conformance.d.ts +18 -0
- package/dist/src/testing-kit/admission-backend-conformance.d.ts.map +1 -0
- package/dist/src/testing-kit/admission-backend-conformance.js +81 -0
- package/dist/src/testing-kit/admission-backend-conformance.js.map +1 -0
- package/dist/src/testing-kit/assertions.d.ts +10 -0
- package/dist/src/testing-kit/assertions.d.ts.map +1 -0
- package/dist/src/testing-kit/assertions.js +41 -0
- package/dist/src/testing-kit/assertions.js.map +1 -0
- package/dist/src/testing-kit/harness.d.ts +28 -0
- package/dist/src/testing-kit/harness.d.ts.map +1 -0
- package/dist/src/testing-kit/harness.js +42 -0
- package/dist/src/testing-kit/harness.js.map +1 -0
- package/dist/src/testing-kit/index.d.ts +8 -0
- package/dist/src/testing-kit/index.d.ts.map +1 -0
- package/dist/src/testing-kit/index.js +8 -0
- package/dist/src/testing-kit/index.js.map +1 -0
- package/dist/src/testing-kit/replay.d.ts +22 -0
- package/dist/src/testing-kit/replay.d.ts.map +1 -0
- package/dist/src/testing-kit/replay.js +38 -0
- package/dist/src/testing-kit/replay.js.map +1 -0
- package/dist/src/testing-kit/state-store-conformance.d.ts +51 -0
- package/dist/src/testing-kit/state-store-conformance.d.ts.map +1 -0
- package/dist/src/testing-kit/state-store-conformance.js +430 -0
- package/dist/src/testing-kit/state-store-conformance.js.map +1 -0
- package/dist/src/testing-kit/steps.d.ts +5 -0
- package/dist/src/testing-kit/steps.d.ts.map +1 -0
- package/dist/src/testing-kit/steps.js +15 -0
- package/dist/src/testing-kit/steps.js.map +1 -0
- package/dist/src/testing-kit/transport-conformance.d.ts +16 -0
- package/dist/src/testing-kit/transport-conformance.d.ts.map +1 -0
- package/dist/src/testing-kit/transport-conformance.js +64 -0
- package/dist/src/testing-kit/transport-conformance.js.map +1 -0
- package/dist/src/tokens.d.ts +18 -0
- package/dist/src/tokens.d.ts.map +1 -0
- package/dist/src/tokens.js +18 -0
- package/dist/src/tokens.js.map +1 -0
- package/dist/src/transport-pool.d.ts +30 -0
- package/dist/src/transport-pool.d.ts.map +1 -0
- package/dist/src/transport-pool.js +82 -0
- package/dist/src/transport-pool.js.map +1 -0
- package/dist/src/transports/db-helpers.d.ts +10 -0
- package/dist/src/transports/db-helpers.d.ts.map +1 -0
- package/dist/src/transports/db-helpers.js +33 -0
- package/dist/src/transports/db-helpers.js.map +1 -0
- package/dist/src/transports/db-schema.d.ts +28 -0
- package/dist/src/transports/db-schema.d.ts.map +1 -0
- package/dist/src/transports/db-schema.js +98 -0
- package/dist/src/transports/db-schema.js.map +1 -0
- package/dist/src/transports/db.d.ts +81 -0
- package/dist/src/transports/db.d.ts.map +1 -0
- package/dist/src/transports/db.js +340 -0
- package/dist/src/transports/db.js.map +1 -0
- package/dist/src/transports/factory.d.ts +79 -0
- package/dist/src/transports/factory.d.ts.map +1 -0
- package/dist/src/transports/factory.js +57 -0
- package/dist/src/transports/factory.js.map +1 -0
- package/dist/src/transports/queue-mock-adapter.d.ts +39 -0
- package/dist/src/transports/queue-mock-adapter.d.ts.map +1 -0
- package/dist/src/transports/queue-mock-adapter.js +86 -0
- package/dist/src/transports/queue-mock-adapter.js.map +1 -0
- package/dist/src/transports/queue.d.ts +84 -0
- package/dist/src/transports/queue.d.ts.map +1 -0
- package/dist/src/transports/queue.js +210 -0
- package/dist/src/transports/queue.js.map +1 -0
- package/dist/src/workflow-ctx.d.ts +64 -0
- package/dist/src/workflow-ctx.d.ts.map +1 -0
- package/dist/src/workflow-ctx.js +457 -0
- package/dist/src/workflow-ctx.js.map +1 -0
- package/dist/src/workflow-ref.d.ts +34 -0
- package/dist/src/workflow-ref.d.ts.map +1 -0
- package/dist/src/workflow-ref.js +28 -0
- package/dist/src/workflow-ref.js.map +1 -0
- package/dist/stubs/config/durable.stub +49 -0
- package/dist/stubs/config/durable_dashboard.stub +17 -0
- package/dist/stubs/database/migrations/create_durable_tables.stub +87 -0
- package/dist/stubs/database/migrations/create_durable_transport_tables.stub +75 -0
- package/dist/stubs/main.d.ts +3 -0
- package/dist/stubs/main.d.ts.map +1 -0
- package/dist/stubs/main.js +4 -0
- package/dist/stubs/main.js.map +1 -0
- package/package.json +154 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import { backoffDelay } from './backoff.js';
|
|
2
|
+
import { instantCheckpoint } from './checkpoints.js';
|
|
3
|
+
import { unwrapCompletion } from './completion.js';
|
|
4
|
+
import { parseDuration } from './duration.js';
|
|
5
|
+
import { ContinueAsNew, FatalError, NonDeterminismError, SignalTimeoutError, WorkflowSuspended, } from './errors.js';
|
|
6
|
+
import { eventToken } from './events.js';
|
|
7
|
+
import { breakpointToken } from './protocol.js';
|
|
8
|
+
import { createStepLogger } from './step-logger.js';
|
|
9
|
+
import { workflowName } from './workflow-ref.js';
|
|
10
|
+
/** Normalize the `ctx.child`/`ctx.startChild` 3rd arg: a bare string is shorthand for `{ childId }`. */
|
|
11
|
+
function normalizeChildOptions(options) {
|
|
12
|
+
return typeof options === 'string' ? { childId: options } : (options ?? {});
|
|
13
|
+
}
|
|
14
|
+
/** The per-run logical position counter. `rewind()` gives a position back (see `ctx.patched`). */
|
|
15
|
+
class Position {
|
|
16
|
+
seq = -1;
|
|
17
|
+
next() {
|
|
18
|
+
this.seq += 1;
|
|
19
|
+
return this.seq;
|
|
20
|
+
}
|
|
21
|
+
rewind() {
|
|
22
|
+
this.seq -= 1;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build the {@link WorkflowCtx} handed to a workflow body. Every primitive is a closure over the
|
|
27
|
+
* position counter (the per-run logical position) and the saga `compensations` stack, so `task`/
|
|
28
|
+
* `child` compose `step`/`waitForSignal` directly. All durability goes through {@link CtxHost}, so
|
|
29
|
+
* the workflow body stays deterministic.
|
|
30
|
+
*/
|
|
31
|
+
export function createWorkflowCtx(host, runId, compensations, workflow = '') {
|
|
32
|
+
const { store, replay } = host;
|
|
33
|
+
const pos = new Position();
|
|
34
|
+
// Read the checkpoint at `seq`: from the per-execution snapshot when present (no DB round-trip),
|
|
35
|
+
// otherwise from the live store. Absence in the snapshot means "written after the snapshot" (the
|
|
36
|
+
// signal/timer/child this resume wakes on, or nothing yet) — those MUST hit the store. Identical
|
|
37
|
+
// behaviour to a raw `store.getCheckpoint`, just memoized for the completed prefix.
|
|
38
|
+
const readCheckpoint = (seq) => {
|
|
39
|
+
const hit = replay?.get(seq);
|
|
40
|
+
if (hit !== undefined)
|
|
41
|
+
return hit;
|
|
42
|
+
return store.getCheckpoint(runId, seq);
|
|
43
|
+
};
|
|
44
|
+
// Persist a checkpoint AND reflect it in the snapshot, so a later same-execution read of this seq
|
|
45
|
+
// (e.g. a re-read within the same call) sees it instead of falling back to the store.
|
|
46
|
+
const writeCheckpoint = async (cp) => {
|
|
47
|
+
await store.saveCheckpoint(cp);
|
|
48
|
+
replay?.set(cp.seq, cp);
|
|
49
|
+
};
|
|
50
|
+
const step = async (name, fn, options) => {
|
|
51
|
+
const current = pos.next();
|
|
52
|
+
const existing = await readCheckpoint(current);
|
|
53
|
+
if (existing && existing.name !== name) {
|
|
54
|
+
throw new NonDeterminismError(runId, current, name, existing.name);
|
|
55
|
+
}
|
|
56
|
+
if (existing && existing.status === 'completed') {
|
|
57
|
+
// Register the compensation on replay too, so a saga undoes ALL completed steps — even
|
|
58
|
+
// those done in an earlier (since-suspended) pass — not just the ones run this pass.
|
|
59
|
+
if (options?.compensate)
|
|
60
|
+
compensations.push({ name, fn: options.compensate });
|
|
61
|
+
return existing.output;
|
|
62
|
+
}
|
|
63
|
+
const maxAttempts = Math.max(1, options?.retries ?? 1);
|
|
64
|
+
const startedAt = new Date();
|
|
65
|
+
// Announce the body has begun (and, when enabled, checkpoint it `running`) so the step is
|
|
66
|
+
// visible in flight — not only once it settles. Skipped on replay: a completed step returns
|
|
67
|
+
// above before reaching here, so this fires once, when the body actually first runs.
|
|
68
|
+
await host.startStep({
|
|
69
|
+
runId,
|
|
70
|
+
seq: current,
|
|
71
|
+
name,
|
|
72
|
+
kind: 'local',
|
|
73
|
+
attempts: 1,
|
|
74
|
+
enqueuedAt: startedAt,
|
|
75
|
+
startedAt,
|
|
76
|
+
});
|
|
77
|
+
for (let attempt = 1;; attempt += 1) {
|
|
78
|
+
// Events are scoped per attempt — a retry starts a clean log, so the checkpoint reflects
|
|
79
|
+
// only the attempt that actually completed (or the final failing one).
|
|
80
|
+
const events = [];
|
|
81
|
+
try {
|
|
82
|
+
const invocation = {
|
|
83
|
+
runId,
|
|
84
|
+
workflow,
|
|
85
|
+
stepName: name,
|
|
86
|
+
seq: current,
|
|
87
|
+
attempt,
|
|
88
|
+
};
|
|
89
|
+
const body = () => fn(createStepLogger(events, host.clock));
|
|
90
|
+
const output = host.interceptStep
|
|
91
|
+
? await host.interceptStep(invocation, body)
|
|
92
|
+
: await body();
|
|
93
|
+
await host.completeStep({
|
|
94
|
+
runId,
|
|
95
|
+
seq: current,
|
|
96
|
+
name,
|
|
97
|
+
kind: 'local',
|
|
98
|
+
output,
|
|
99
|
+
events,
|
|
100
|
+
attempts: attempt,
|
|
101
|
+
enqueuedAt: startedAt,
|
|
102
|
+
startedAt,
|
|
103
|
+
});
|
|
104
|
+
if (options?.compensate)
|
|
105
|
+
compensations.push({ name, fn: options.compensate });
|
|
106
|
+
return output;
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
if (err instanceof FatalError || attempt >= maxAttempts) {
|
|
110
|
+
await host.failStep({
|
|
111
|
+
runId,
|
|
112
|
+
seq: current,
|
|
113
|
+
name,
|
|
114
|
+
kind: 'local',
|
|
115
|
+
error: {
|
|
116
|
+
message: err instanceof Error ? err.message : String(err),
|
|
117
|
+
stack: err instanceof Error ? err.stack : undefined,
|
|
118
|
+
},
|
|
119
|
+
events,
|
|
120
|
+
attempts: attempt,
|
|
121
|
+
enqueuedAt: startedAt,
|
|
122
|
+
startedAt,
|
|
123
|
+
});
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
// Wait out the backoff before the next attempt (no-op when backoffMs is unset).
|
|
127
|
+
const wait = backoffDelay(attempt, options);
|
|
128
|
+
if (wait > 0)
|
|
129
|
+
await new Promise((resolve) => setTimeout(resolve, wait));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
// Exactly-once DB step: run the body and write the step checkpoint in ONE store transaction, so the
|
|
134
|
+
// business write commits atomically with the "done" marker (a plain step checkpoints AFTER the body,
|
|
135
|
+
// so a crash in between re-runs it). Replay returns the recorded output without re-running.
|
|
136
|
+
const transaction = async (name, fn) => {
|
|
137
|
+
if (!store.transaction) {
|
|
138
|
+
throw new Error('ctx.transaction needs a store that supports transactions (the SQL adapters do). Use ctx.step for non-transactional work.');
|
|
139
|
+
}
|
|
140
|
+
const current = pos.next();
|
|
141
|
+
const existing = await readCheckpoint(current);
|
|
142
|
+
if (existing && existing.name !== name) {
|
|
143
|
+
throw new NonDeterminismError(runId, current, name, existing.name);
|
|
144
|
+
}
|
|
145
|
+
if (existing && existing.status === 'completed')
|
|
146
|
+
return existing.output;
|
|
147
|
+
return store.transaction(async (tx) => {
|
|
148
|
+
const output = await fn(tx.raw);
|
|
149
|
+
const cp = instantCheckpoint({ runId, seq: current, name, kind: 'local', output });
|
|
150
|
+
await tx.saveCheckpoint(cp);
|
|
151
|
+
// Reflect the committed checkpoint in the snapshot, keeping the writeback invariant uniform.
|
|
152
|
+
replay?.set(current, cp);
|
|
153
|
+
return output;
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
// Shared by sleep / sleepUntil: record a durable timer at this position and suspend until `wakeAt`
|
|
157
|
+
// (epoch ms). The wakeAt is computed by the caller — but only used on the first run; on replay the
|
|
158
|
+
// recorded checkpoint's wakeAt wins, so a clock change can't shift an already-scheduled timer.
|
|
159
|
+
const suspendUntil = async (wakeAt) => {
|
|
160
|
+
const current = pos.next();
|
|
161
|
+
const now = host.clock();
|
|
162
|
+
const existing = await readCheckpoint(current);
|
|
163
|
+
if (existing) {
|
|
164
|
+
// Timer already recorded: resume if due, otherwise re-suspend cheaply.
|
|
165
|
+
if (now >= (existing.wakeAt ?? 0))
|
|
166
|
+
return;
|
|
167
|
+
throw new WorkflowSuspended(existing.wakeAt ?? now);
|
|
168
|
+
}
|
|
169
|
+
const at = wakeAt();
|
|
170
|
+
await writeCheckpoint(instantCheckpoint({ runId, seq: current, name: 'sleep', kind: 'sleep', wakeAt: at }));
|
|
171
|
+
throw new WorkflowSuspended(at);
|
|
172
|
+
};
|
|
173
|
+
const sleep = (duration) => suspendUntil(() => host.clock() + parseDuration(duration));
|
|
174
|
+
const sleepUntil = (when) => suspendUntil(() => (typeof when === 'number' ? when : when.getTime()));
|
|
175
|
+
// End this run and hand off to a fresh execution (clean history) with the new input. Terminal —
|
|
176
|
+
// it always throws, so any code after it in the workflow is unreachable.
|
|
177
|
+
const continueAsNew = (input) => {
|
|
178
|
+
throw new ContinueAsNew(input);
|
|
179
|
+
};
|
|
180
|
+
// NOTE (determinism): a bounded wait consumes TWO logical positions (deadline + wait), an
|
|
181
|
+
// unbounded one consumes ONE. So adding or removing `{ timeoutMs }` on an existing `waitForSignal`
|
|
182
|
+
// shifts the seq of every later step — treat it as a workflow-version change for in-flight runs.
|
|
183
|
+
// Consume a buffered signal (one delivered before this run was waiting), recording it as the
|
|
184
|
+
// signal checkpoint at `seq` so it resumes immediately instead of suspending. Replay-safe: the
|
|
185
|
+
// checkpoint makes the consumption deterministic.
|
|
186
|
+
const consumeBuffered = async (token, seq) => {
|
|
187
|
+
const buffered = await store.takeBufferedSignal(token);
|
|
188
|
+
if (!buffered)
|
|
189
|
+
return null;
|
|
190
|
+
await writeCheckpoint(instantCheckpoint({
|
|
191
|
+
runId,
|
|
192
|
+
seq,
|
|
193
|
+
name: `signal:${token}`,
|
|
194
|
+
kind: 'signal',
|
|
195
|
+
output: buffered.payload,
|
|
196
|
+
}));
|
|
197
|
+
return { value: buffered.payload };
|
|
198
|
+
};
|
|
199
|
+
const waitForSignal = async (token, opts) => {
|
|
200
|
+
if (opts?.timeoutMs == null) {
|
|
201
|
+
const current = pos.next();
|
|
202
|
+
const existing = await readCheckpoint(current);
|
|
203
|
+
if (existing && existing.status === 'completed')
|
|
204
|
+
return existing.output;
|
|
205
|
+
const buffered = await consumeBuffered(token, current);
|
|
206
|
+
if (buffered)
|
|
207
|
+
return buffered.value;
|
|
208
|
+
await store.putSignalWaiter({ token, runId, seq: current });
|
|
209
|
+
throw new WorkflowSuspended();
|
|
210
|
+
}
|
|
211
|
+
const timeoutMs = opts.timeoutMs;
|
|
212
|
+
const deadlineSeq = pos.next();
|
|
213
|
+
const waitSeq = pos.next();
|
|
214
|
+
// The deadline is recorded durably as a timer checkpoint so replay knows it; the run also gets a
|
|
215
|
+
// run-level wakeAt (via WorkflowSuspended) so the timer poller resumes it at the deadline.
|
|
216
|
+
const recorded = await readCheckpoint(deadlineSeq);
|
|
217
|
+
const deadline = recorded?.wakeAt ?? host.clock() + timeoutMs;
|
|
218
|
+
if (!recorded) {
|
|
219
|
+
await writeCheckpoint(instantCheckpoint({
|
|
220
|
+
runId,
|
|
221
|
+
seq: deadlineSeq,
|
|
222
|
+
name: `timeout:${token}`,
|
|
223
|
+
kind: 'sleep',
|
|
224
|
+
wakeAt: deadline,
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
const waited = await readCheckpoint(waitSeq);
|
|
228
|
+
if (waited && waited.status === 'completed')
|
|
229
|
+
return waited.output;
|
|
230
|
+
const buffered = await consumeBuffered(token, waitSeq);
|
|
231
|
+
if (buffered)
|
|
232
|
+
return buffered.value;
|
|
233
|
+
if (host.clock() >= deadline) {
|
|
234
|
+
await store.takeSignalWaiter(token).catch(() => undefined);
|
|
235
|
+
throw new SignalTimeoutError(token, timeoutMs);
|
|
236
|
+
}
|
|
237
|
+
await store.putSignalWaiter({ token, runId, seq: waitSeq });
|
|
238
|
+
throw new WorkflowSuspended(deadline);
|
|
239
|
+
};
|
|
240
|
+
// Wait for a named event delivered by engine.publishEvent(name, payload). Like waitForSignal, but
|
|
241
|
+
// name-based pub/sub with optional `match` filtering — the token embeds name + match (see events.ts),
|
|
242
|
+
// so a publish fans out to the runs whose match the payload satisfies.
|
|
243
|
+
const waitForEvent = async (name, opts) => {
|
|
244
|
+
if (opts?.timeoutMs == null) {
|
|
245
|
+
const current = pos.next();
|
|
246
|
+
const token = eventToken(name, opts?.match, runId, current);
|
|
247
|
+
const existing = await readCheckpoint(current);
|
|
248
|
+
if (existing && existing.status === 'completed')
|
|
249
|
+
return existing.output;
|
|
250
|
+
await store.putSignalWaiter({ token, runId, seq: current });
|
|
251
|
+
throw new WorkflowSuspended();
|
|
252
|
+
}
|
|
253
|
+
const timeoutMs = opts.timeoutMs;
|
|
254
|
+
const deadlineSeq = pos.next();
|
|
255
|
+
const waitSeq = pos.next();
|
|
256
|
+
const token = eventToken(name, opts.match, runId, waitSeq);
|
|
257
|
+
const recorded = await readCheckpoint(deadlineSeq);
|
|
258
|
+
const deadline = recorded?.wakeAt ?? host.clock() + timeoutMs;
|
|
259
|
+
if (!recorded) {
|
|
260
|
+
await writeCheckpoint(instantCheckpoint({
|
|
261
|
+
runId,
|
|
262
|
+
seq: deadlineSeq,
|
|
263
|
+
name: `timeout:event:${name}`,
|
|
264
|
+
kind: 'sleep',
|
|
265
|
+
wakeAt: deadline,
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
const waited = await readCheckpoint(waitSeq);
|
|
269
|
+
if (waited && waited.status === 'completed')
|
|
270
|
+
return waited.output;
|
|
271
|
+
if (host.clock() >= deadline) {
|
|
272
|
+
await store.takeSignalWaiter(token).catch(() => undefined);
|
|
273
|
+
throw new SignalTimeoutError(`event:${name}`, timeoutMs);
|
|
274
|
+
}
|
|
275
|
+
await store.putSignalWaiter({ token, runId, seq: waitSeq });
|
|
276
|
+
throw new WorkflowSuspended(deadline);
|
|
277
|
+
};
|
|
278
|
+
// An external task = a checkpointed dispatch + a wait for its async-completion `Completion`
|
|
279
|
+
// (delivered by engine.completeTask/failTask). The whole "fire at a foreign system, suspend,
|
|
280
|
+
// resume when it reports back" pattern as one call.
|
|
281
|
+
const task = async (name, dispatch, options) => {
|
|
282
|
+
await step(`task:dispatch:${name}`, dispatch, options);
|
|
283
|
+
return unwrapCompletion(await waitForSignal(`task:${runId}:${name}`), `task "${name}"`);
|
|
284
|
+
};
|
|
285
|
+
// Child workflow (await result): start it once, then suspend on a `child:<id>` waiter the child
|
|
286
|
+
// signals on its terminal state (see engine.notifyParent).
|
|
287
|
+
const child = async (workflow, input, options) => {
|
|
288
|
+
const { childId, priority } = normalizeChildOptions(options);
|
|
289
|
+
const current = pos.next();
|
|
290
|
+
const id = childId ?? `${runId}.child.${current}`;
|
|
291
|
+
const existing = await readCheckpoint(current);
|
|
292
|
+
if (existing && existing.status === 'completed') {
|
|
293
|
+
return unwrapCompletion(existing.output, `child "${id}"`);
|
|
294
|
+
}
|
|
295
|
+
await store.putSignalWaiter({ token: `child:${id}`, runId, seq: current });
|
|
296
|
+
if (!(await store.getRun(id)))
|
|
297
|
+
host.startChild(workflowName(workflow), input, id, priority);
|
|
298
|
+
// Make the awaited child visible in the parent's timeline WHILE it runs: a `running` placeholder
|
|
299
|
+
// at this seq with the same `signal:child:<id>` name the signal resolution later overwrites as
|
|
300
|
+
// `completed`. So the dashboard shows the child node (and can inline-expand it) live, instead of
|
|
301
|
+
// it appearing only when it finishes. Written once (skipped on replay, where `existing` is set);
|
|
302
|
+
// `running` is ignored by replay history, so it never short-circuits determinism.
|
|
303
|
+
if (!existing) {
|
|
304
|
+
await writeCheckpoint(instantCheckpoint({
|
|
305
|
+
runId,
|
|
306
|
+
seq: current,
|
|
307
|
+
name: `signal:child:${id}`,
|
|
308
|
+
kind: 'signal',
|
|
309
|
+
status: 'running',
|
|
310
|
+
}));
|
|
311
|
+
}
|
|
312
|
+
throw new WorkflowSuspended();
|
|
313
|
+
};
|
|
314
|
+
// Child workflow (fire-and-forget): dispatch it once and return its id WITHOUT suspending. The
|
|
315
|
+
// start is checkpointed at this position so replay returns the same id without re-dispatching, and
|
|
316
|
+
// is idempotent by id, so `child(..., sameId)` later joins the same run rather than starting a new
|
|
317
|
+
// one (start + join scatter-gather).
|
|
318
|
+
const startChild = async (workflow, input, options) => {
|
|
319
|
+
const { childId, priority } = normalizeChildOptions(options);
|
|
320
|
+
const current = pos.next();
|
|
321
|
+
const id = childId ?? `${runId}.child.${current}`;
|
|
322
|
+
const existing = await readCheckpoint(current);
|
|
323
|
+
if (existing && existing.status === 'completed')
|
|
324
|
+
return existing.output;
|
|
325
|
+
if (!(await store.getRun(id)))
|
|
326
|
+
host.startChild(workflowName(workflow), input, id, priority);
|
|
327
|
+
await writeCheckpoint(instantCheckpoint({ runId, seq: current, name: `spawn:${id}`, kind: 'local', output: id }));
|
|
328
|
+
return id;
|
|
329
|
+
};
|
|
330
|
+
// Call a durable entity op and await its result: register a reply waiter at this position, dispatch
|
|
331
|
+
// the op with the reply token, and suspend until the entity signals the result back (checkpointed,
|
|
332
|
+
// so replay returns it without re-dispatching).
|
|
333
|
+
const callEntity = async (name, key, op, arg) => {
|
|
334
|
+
const current = pos.next();
|
|
335
|
+
const existing = await readCheckpoint(current);
|
|
336
|
+
if (existing && existing.status === 'completed')
|
|
337
|
+
return existing.output;
|
|
338
|
+
const reply = `entityreply:${runId}:${current}`;
|
|
339
|
+
await store.putSignalWaiter({ token: reply, runId, seq: current });
|
|
340
|
+
host.signalEntity?.(name, key, op, arg, reply);
|
|
341
|
+
throw new WorkflowSuspended();
|
|
342
|
+
};
|
|
343
|
+
// Send a durable entity op without awaiting a result — dispatched once (checkpointed, replay-safe).
|
|
344
|
+
const signalEntity = async (name, key, op, arg) => {
|
|
345
|
+
const current = pos.next();
|
|
346
|
+
const existing = await readCheckpoint(current);
|
|
347
|
+
if (existing && existing.status === 'completed')
|
|
348
|
+
return;
|
|
349
|
+
host.signalEntity?.(name, key, op, arg);
|
|
350
|
+
await writeCheckpoint(instantCheckpoint({ runId, seq: current, name: `entitysig:${name}:${key}`, kind: 'local' }));
|
|
351
|
+
};
|
|
352
|
+
// A breakpoint = a visible `pending` checkpoint + a signal waiter the dashboard resumes via
|
|
353
|
+
// `engine.continue`. Reuses the signal machinery, so resume overwrites the pending checkpoint
|
|
354
|
+
// with a completed one and the run replays past it.
|
|
355
|
+
const breakpoint = async (label) => {
|
|
356
|
+
const current = pos.next();
|
|
357
|
+
const existing = await readCheckpoint(current);
|
|
358
|
+
if (existing && existing.status === 'completed')
|
|
359
|
+
return;
|
|
360
|
+
if (!existing) {
|
|
361
|
+
await writeCheckpoint(instantCheckpoint({
|
|
362
|
+
runId,
|
|
363
|
+
seq: current,
|
|
364
|
+
name: label ? `breakpoint:${label}` : 'breakpoint',
|
|
365
|
+
kind: 'signal',
|
|
366
|
+
status: 'pending',
|
|
367
|
+
}));
|
|
368
|
+
await store.putSignalWaiter({ token: breakpointToken(runId, current), runId, seq: current });
|
|
369
|
+
}
|
|
370
|
+
throw new WorkflowSuspended();
|
|
371
|
+
};
|
|
372
|
+
// Guard an in-place change: a fresh run records a `patch:<id>` marker here and takes the new
|
|
373
|
+
// branch; a run recorded under the OLD code finds a real step at this position instead, so we
|
|
374
|
+
// rewind the logical position (the marker is transparent to it) and return false — its replay
|
|
375
|
+
// reads that old step next and follows the old branch. No position shift → no corruption.
|
|
376
|
+
const patched = async (id) => {
|
|
377
|
+
const marker = `patch:${id}`;
|
|
378
|
+
const current = pos.next();
|
|
379
|
+
const existing = await readCheckpoint(current);
|
|
380
|
+
if (existing) {
|
|
381
|
+
if (existing.name === marker)
|
|
382
|
+
return true;
|
|
383
|
+
if (existing.name.startsWith('patch:')) {
|
|
384
|
+
throw new NonDeterminismError(runId, current, marker, existing.name);
|
|
385
|
+
}
|
|
386
|
+
pos.rewind(); // not a marker: an old run's step lives here — give the position back to it
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
await writeCheckpoint(instantCheckpoint({ runId, seq: current, name: marker, kind: 'local', output: true }));
|
|
390
|
+
return true;
|
|
391
|
+
};
|
|
392
|
+
// An update point: suspend on a run-scoped `update:<runId>:<name>` token that engine.update
|
|
393
|
+
// delivers to (after its validator passes). Reuses the signal machinery; run-scoped like task/child.
|
|
394
|
+
const onUpdate = (name, opts) => waitForSignal(`update:${runId}:${name}`, opts);
|
|
395
|
+
// A queryable named value: a checkpoint whose `name` is `event:<key>`, so the latest value for a
|
|
396
|
+
// key is just the highest-seq such checkpoint (read by engine.getEvent). Replay-idempotent.
|
|
397
|
+
const setEvent = async (key, value) => {
|
|
398
|
+
const current = pos.next();
|
|
399
|
+
const name = `event:${key}`;
|
|
400
|
+
const existing = await readCheckpoint(current);
|
|
401
|
+
if (existing && existing.name !== name) {
|
|
402
|
+
throw new NonDeterminismError(runId, current, name, existing.name);
|
|
403
|
+
}
|
|
404
|
+
if (existing && existing.status === 'completed')
|
|
405
|
+
return; // replay: already published
|
|
406
|
+
await writeCheckpoint(instantCheckpoint({ runId, seq: current, name, kind: 'local', output: value }));
|
|
407
|
+
};
|
|
408
|
+
// A durable webhook reserves a logical position NOW to mint a stable token, so the url can be
|
|
409
|
+
// handed to a third party before `wait()` suspends. `wait()` then parks on that same position
|
|
410
|
+
// until the callback lands as engine.signal(token, body) — single position, replay-safe.
|
|
411
|
+
const webhook = () => {
|
|
412
|
+
const current = pos.next();
|
|
413
|
+
const token = `wh:${runId}:${current}`;
|
|
414
|
+
const wait = async () => {
|
|
415
|
+
const existing = await readCheckpoint(current);
|
|
416
|
+
if (existing && existing.status === 'completed')
|
|
417
|
+
return existing.output;
|
|
418
|
+
await store.putSignalWaiter({ token, runId, seq: current });
|
|
419
|
+
throw new WorkflowSuspended();
|
|
420
|
+
};
|
|
421
|
+
return { token, url: host.webhookUrl?.(token), wait };
|
|
422
|
+
};
|
|
423
|
+
// Deterministic non-deterministic sources: each is a checkpointed local step, so the value is
|
|
424
|
+
// captured on the first run and replayed verbatim (a raw Date.now()/Math.random() inside a
|
|
425
|
+
// workflow would differ across replays and corrupt the run).
|
|
426
|
+
const now = () => step('now', async () => host.clock());
|
|
427
|
+
const random = () => step('random', async () => Math.random());
|
|
428
|
+
const uuid = () => step('uuid', async () => globalThis.crypto.randomUUID());
|
|
429
|
+
return {
|
|
430
|
+
runId,
|
|
431
|
+
step,
|
|
432
|
+
transaction,
|
|
433
|
+
callEntity,
|
|
434
|
+
signalEntity,
|
|
435
|
+
sleep,
|
|
436
|
+
sleepUntil,
|
|
437
|
+
continueAsNew,
|
|
438
|
+
waitForSignal,
|
|
439
|
+
waitForEvent,
|
|
440
|
+
task,
|
|
441
|
+
child,
|
|
442
|
+
startChild,
|
|
443
|
+
breakpoint,
|
|
444
|
+
webhook,
|
|
445
|
+
setEvent,
|
|
446
|
+
onUpdate,
|
|
447
|
+
patched,
|
|
448
|
+
now,
|
|
449
|
+
random,
|
|
450
|
+
uuid,
|
|
451
|
+
call: (remote, input, opts) => host.callRemote(runId, pos.next(), remote, input, opts?.queue, opts?.transport, {
|
|
452
|
+
priority: opts?.priority,
|
|
453
|
+
fairnessKey: opts?.fairnessKey,
|
|
454
|
+
}),
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
//# sourceMappingURL=workflow-ctx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-ctx.js","sourceRoot":"","sources":["../../src/workflow-ctx.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A **workflow reference** is how one workflow names another to call it: either a registered workflow
|
|
3
|
+
* **name** (a string — the only option across runtimes, e.g. a Python workflow) or, for a same-runtime
|
|
4
|
+
* TypeScript workflow, its **class**. The class carries the input/output types through the call, so
|
|
5
|
+
* `ctx.child(ShippingWorkflow, input)` type-checks the input and returns a typed result — while a
|
|
6
|
+
* string stays available for the cross-runtime case.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The symbol the `@Workflow` decorator stamps a workflow's registered name onto, so a class ref can
|
|
10
|
+
* be resolved back to its name. A global-registry symbol (`Symbol.for`) so it survives duplicate
|
|
11
|
+
* copies of this package in a dependency tree.
|
|
12
|
+
*/
|
|
13
|
+
export declare const WORKFLOW_NAME_KEY: unique symbol;
|
|
14
|
+
/** Structural shape of a `@Workflow` class — its `run(ctx, input)` carries the input/output types. */
|
|
15
|
+
export type WorkflowClass<TInput = unknown, TOutput = unknown> = abstract new (...args: never[]) => {
|
|
16
|
+
run(ctx: never, input: TInput): Promise<TOutput> | TOutput;
|
|
17
|
+
};
|
|
18
|
+
/** A workflow reference: a registered name (cross-runtime) or a workflow class (typed, same-runtime). */
|
|
19
|
+
export type WorkflowRef<TInput = unknown, TOutput = unknown> = string | WorkflowClass<TInput, TOutput>;
|
|
20
|
+
/** The input type a workflow class's `run` accepts. */
|
|
21
|
+
export type WorkflowInputOf<C> = C extends abstract new (...args: never[]) => {
|
|
22
|
+
run(ctx: never, input: infer I): unknown;
|
|
23
|
+
} ? I : unknown;
|
|
24
|
+
/** The output type a workflow class's `run` resolves to (Promise unwrapped). */
|
|
25
|
+
export type WorkflowOutputOf<C> = C extends abstract new (...args: never[]) => {
|
|
26
|
+
run(ctx: never, input: never): infer R;
|
|
27
|
+
} ? Awaited<R> : unknown;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a {@link WorkflowRef} to its registered workflow name: a string is returned as-is; a
|
|
30
|
+
* `@Workflow` class is resolved via the name the decorator stamped on it. Throws if a class was
|
|
31
|
+
* never decorated (so it carries no registered name).
|
|
32
|
+
*/
|
|
33
|
+
export declare function workflowName(ref: WorkflowRef): string;
|
|
34
|
+
//# sourceMappingURL=workflow-ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-ref.d.ts","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAAO,MAAmD,CAAC;AAE3F,sGAAsG;AACtG,MAAM,MAAM,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,QAAQ,MACvE,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,yGAAyG;AACzG,MAAM,MAAM,WAAW,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IACvD,MAAM,GACN,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC,uDAAuD;AACvD,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MACjD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;CAC1C,GACG,CAAC,GACD,OAAO,CAAC;AAEZ,gFAAgF;AAChF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MAClD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;CACxC,GACG,OAAO,CAAC,CAAC,CAAC,GACV,OAAO,CAAC;AAEZ;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CASrD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A **workflow reference** is how one workflow names another to call it: either a registered workflow
|
|
3
|
+
* **name** (a string — the only option across runtimes, e.g. a Python workflow) or, for a same-runtime
|
|
4
|
+
* TypeScript workflow, its **class**. The class carries the input/output types through the call, so
|
|
5
|
+
* `ctx.child(ShippingWorkflow, input)` type-checks the input and returns a typed result — while a
|
|
6
|
+
* string stays available for the cross-runtime case.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The symbol the `@Workflow` decorator stamps a workflow's registered name onto, so a class ref can
|
|
10
|
+
* be resolved back to its name. A global-registry symbol (`Symbol.for`) so it survives duplicate
|
|
11
|
+
* copies of this package in a dependency tree.
|
|
12
|
+
*/
|
|
13
|
+
export const WORKFLOW_NAME_KEY = Symbol.for('@agora/durable:workflow-name');
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a {@link WorkflowRef} to its registered workflow name: a string is returned as-is; a
|
|
16
|
+
* `@Workflow` class is resolved via the name the decorator stamped on it. Throws if a class was
|
|
17
|
+
* never decorated (so it carries no registered name).
|
|
18
|
+
*/
|
|
19
|
+
export function workflowName(ref) {
|
|
20
|
+
if (typeof ref === 'string')
|
|
21
|
+
return ref;
|
|
22
|
+
const name = ref[WORKFLOW_NAME_KEY];
|
|
23
|
+
if (!name) {
|
|
24
|
+
throw new Error(`workflow class ${ref.name} has no registered name — is it decorated with @Workflow({ name })?`);
|
|
25
|
+
}
|
|
26
|
+
return name;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=workflow-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-ref.js","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAkB,MAAM,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;AAgC3F;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,MAAM,IAAI,GAAI,GAAwC,CAAC,iBAAiB,CAAC,CAAC;IAC1E,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,kBAAkB,GAAG,CAAC,IAAI,qEAAqE,CAChG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{{{
|
|
2
|
+
exports({ to: app.configPath('durable.ts') })
|
|
3
|
+
}}}
|
|
4
|
+
import { defineConfig, transports } from '@adonis-agora/durable'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for @adonis-agora/durable. Pick a `transport` (and optionally a `store`) by name from the
|
|
8
|
+
* maps below; each driver's peer dependency is imported lazily, only when selected. The default is
|
|
9
|
+
* the in-process `memory` transport + the in-memory store — single-process, no extra infrastructure.
|
|
10
|
+
*
|
|
11
|
+
* For cross-process / production, select the `queue` (@adonisjs/queue) or `db` (@adonisjs/lucid)
|
|
12
|
+
* transport, and the `lucid` store, then run `node ace migration:run`:
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { defineConfig, transports, stores } from '@adonis-agora/durable'
|
|
16
|
+
*
|
|
17
|
+
* export default defineConfig({
|
|
18
|
+
* transport: 'queue',
|
|
19
|
+
* transports: {
|
|
20
|
+
* memory: transports.memory(),
|
|
21
|
+
* // `connection` names an adapter from config/queue.ts (configure @adonisjs/queue first):
|
|
22
|
+
* queue: transports.queue({ connection: 'redis', group: 'durable' }),
|
|
23
|
+
* db: transports.db(),
|
|
24
|
+
* },
|
|
25
|
+
* store: 'lucid',
|
|
26
|
+
* stores: {
|
|
27
|
+
* lucid: stores.lucid(),
|
|
28
|
+
* },
|
|
29
|
+
* })
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export default defineConfig({
|
|
33
|
+
transport: 'memory',
|
|
34
|
+
transports: {
|
|
35
|
+
memory: transports.memory(),
|
|
36
|
+
},
|
|
37
|
+
// leaseMs: 30_000,
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Recurring workflows fired by the `durable:work` worker loop on every tick. Each window starts
|
|
41
|
+
* exactly once even with several worker instances racing (idempotent by the schedule's time-bucket
|
|
42
|
+
* run id). Use `everyMs` for a fixed interval, or `cron` + `timezone` for a calendar schedule (cron
|
|
43
|
+
* needs the optional `cron-parser` peer dependency). See docs/authoring/scheduling.
|
|
44
|
+
*/
|
|
45
|
+
// schedules: [
|
|
46
|
+
// { key: 'nightly-report', workflow: 'daily-report', cron: '0 2 * * *', timezone: 'America/Sao_Paulo' },
|
|
47
|
+
// { key: 'cache-sync', workflow: 'cache-sync', everyMs: 5 * 60 * 1000 },
|
|
48
|
+
// ],
|
|
49
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{{{
|
|
2
|
+
exports({ to: app.configPath('durable_dashboard.ts') })
|
|
3
|
+
}}}
|
|
4
|
+
import { defineConfig } from '@adonis-agora/durable/dashboard'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for the @adonis-agora/durable dashboard.
|
|
8
|
+
*
|
|
9
|
+
* By default the dashboard is open OUTSIDE production, and in production it
|
|
10
|
+
* requires a bearer token equal to `DURABLE_DASHBOARD_TOKEN` (deny if unset).
|
|
11
|
+
* Replace `authorize` with your own guard (session, role, IP allow-list, …).
|
|
12
|
+
*/
|
|
13
|
+
export default defineConfig({
|
|
14
|
+
// enabled: true,
|
|
15
|
+
// path: '/durable',
|
|
16
|
+
// authorize: (ctx) => ctx.auth.user?.isAdmin === true,
|
|
17
|
+
})
|