@voyant-travel/workflows-orchestrator 0.107.10
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 +201 -0
- package/NOTICE +52 -0
- package/README.md +76 -0
- package/dist/abort-registry.d.ts +6 -0
- package/dist/abort-registry.d.ts.map +1 -0
- package/dist/abort-registry.js +37 -0
- package/dist/concurrency.d.ts +31 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +145 -0
- package/dist/drive.d.ts +67 -0
- package/dist/drive.d.ts.map +1 -0
- package/dist/drive.js +373 -0
- package/dist/driver-inmemory.d.ts +30 -0
- package/dist/driver-inmemory.d.ts.map +1 -0
- package/dist/driver-inmemory.js +394 -0
- package/dist/event-router.d.ts +51 -0
- package/dist/event-router.d.ts.map +1 -0
- package/dist/event-router.js +68 -0
- package/dist/http-step-handler.d.ts +25 -0
- package/dist/http-step-handler.d.ts.map +1 -0
- package/dist/http-step-handler.js +78 -0
- package/dist/in-memory-store.d.ts +5 -0
- package/dist/in-memory-store.d.ts.map +1 -0
- package/dist/in-memory-store.js +41 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/journal-helpers.d.ts +3 -0
- package/dist/journal-helpers.d.ts.map +1 -0
- package/dist/journal-helpers.js +9 -0
- package/dist/orchestrator.d.ts +116 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +411 -0
- package/dist/resume-run.d.ts +40 -0
- package/dist/resume-run.d.ts.map +1 -0
- package/dist/resume-run.js +119 -0
- package/dist/schedule.d.ts +51 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/schedule.js +243 -0
- package/dist/testing/driver-compliance.d.ts +58 -0
- package/dist/testing/driver-compliance.d.ts.map +1 -0
- package/dist/testing/driver-compliance.js +667 -0
- package/dist/types.d.ts +182 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/package.json +51 -0
- package/src/__tests__/orchestrator-test-support.ts +18 -0
- package/src/abort-registry.ts +41 -0
- package/src/concurrency.ts +217 -0
- package/src/drive.ts +477 -0
- package/src/driver-inmemory.ts +511 -0
- package/src/event-router.ts +120 -0
- package/src/http-step-handler.ts +112 -0
- package/src/in-memory-store.ts +44 -0
- package/src/index.ts +73 -0
- package/src/journal-helpers.ts +11 -0
- package/src/orchestrator.ts +527 -0
- package/src/resume-run.ts +162 -0
- package/src/schedule.ts +310 -0
- package/src/testing/driver-compliance.ts +800 -0
- package/src/types.ts +201 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// Types the orchestrator core uses. Decoupled from any transport:
|
|
2
|
+
// the same RunRecord/Store shapes underpin the in-memory test store,
|
|
3
|
+
// the Durable-Object-backed production store, and any future adapters.
|
|
4
|
+
|
|
5
|
+
import type { RunTrigger, WaitpointKind } from "@voyant-travel/workflows"
|
|
6
|
+
import type {
|
|
7
|
+
StepHandlerError,
|
|
8
|
+
WorkflowStepRequest,
|
|
9
|
+
WorkflowStepResponse,
|
|
10
|
+
} from "@voyant-travel/workflows/handler"
|
|
11
|
+
import type {
|
|
12
|
+
CompensationJournalEntry,
|
|
13
|
+
JournalSlice,
|
|
14
|
+
StepJournalEntry,
|
|
15
|
+
WaitpointResolutionEntry,
|
|
16
|
+
} from "@voyant-travel/workflows/protocol"
|
|
17
|
+
|
|
18
|
+
export type {
|
|
19
|
+
CompensationJournalEntry,
|
|
20
|
+
JournalSlice,
|
|
21
|
+
RunTrigger,
|
|
22
|
+
StepJournalEntry,
|
|
23
|
+
WaitpointKind,
|
|
24
|
+
WaitpointResolutionEntry,
|
|
25
|
+
WorkflowStepRequest,
|
|
26
|
+
WorkflowStepResponse,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Terminal and non-terminal run statuses. Mirrors the wire statuses
|
|
31
|
+
* from docs/runtime-protocol.md §5 but only the states the orchestrator
|
|
32
|
+
* itself cares about.
|
|
33
|
+
*/
|
|
34
|
+
export type OrchestratorRunStatus =
|
|
35
|
+
| "running"
|
|
36
|
+
| "waiting"
|
|
37
|
+
| "completed"
|
|
38
|
+
| "failed"
|
|
39
|
+
| "cancelled"
|
|
40
|
+
| "compensated"
|
|
41
|
+
| "compensation_failed"
|
|
42
|
+
|
|
43
|
+
export interface PendingWaitpoint {
|
|
44
|
+
clientWaitpointId: string
|
|
45
|
+
kind: WaitpointKind
|
|
46
|
+
meta: Record<string, unknown>
|
|
47
|
+
timeoutMs?: number
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface StreamChunk {
|
|
51
|
+
streamId: string
|
|
52
|
+
seq: number
|
|
53
|
+
encoding: "text" | "json" | "base64"
|
|
54
|
+
chunk: unknown
|
|
55
|
+
final: boolean
|
|
56
|
+
at: number
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface RunRecord {
|
|
60
|
+
id: string
|
|
61
|
+
workflowId: string
|
|
62
|
+
workflowVersion: string
|
|
63
|
+
status: OrchestratorRunStatus
|
|
64
|
+
input: unknown
|
|
65
|
+
/** Output on "completed" runs. */
|
|
66
|
+
output?: unknown
|
|
67
|
+
/** SerializedError for failed / compensation_failed. */
|
|
68
|
+
error?: { category: string; code: string; message: string }
|
|
69
|
+
/** Journal accumulated across every tenant invocation. */
|
|
70
|
+
journal: JournalSlice
|
|
71
|
+
/** Number of tenant invocations performed so far. */
|
|
72
|
+
invocationCount: number
|
|
73
|
+
/**
|
|
74
|
+
* Positional dedup cursor for `metadataUpdates`. Each executor
|
|
75
|
+
* response re-emits every metadata mutation the body made (including
|
|
76
|
+
* those from prior invocations, since the body replays from the
|
|
77
|
+
* start). The orchestrator applies only the delta beyond what it's
|
|
78
|
+
* seen to avoid double-counting increments / duplicate appends.
|
|
79
|
+
*/
|
|
80
|
+
metadataAppliedCount: number
|
|
81
|
+
/**
|
|
82
|
+
* Cumulative ms spent inside tenant invocations, excluding parked
|
|
83
|
+
* time. Used to enforce workflow-level timeouts — a run that
|
|
84
|
+
* parks for a week on a waitpoint should not count that week
|
|
85
|
+
* against its compute budget.
|
|
86
|
+
*/
|
|
87
|
+
computeTimeMs: number
|
|
88
|
+
/** ms budget from WorkflowConfig.timeout. Zero / undefined = no limit. */
|
|
89
|
+
timeoutMs?: number
|
|
90
|
+
/**
|
|
91
|
+
* Trigger-time scheduling priority. Higher numbers are claimed first
|
|
92
|
+
* by store-backed time wheels when multiple runs are due.
|
|
93
|
+
*/
|
|
94
|
+
priority?: number
|
|
95
|
+
/**
|
|
96
|
+
* Cross-run lineage. Present on child runs created by
|
|
97
|
+
* `ctx.invoke`; set by the orchestrator when the child parks so
|
|
98
|
+
* its eventual terminal transition can cascade-resume the parent.
|
|
99
|
+
*/
|
|
100
|
+
parent?: {
|
|
101
|
+
runId: string
|
|
102
|
+
waitpointId: string
|
|
103
|
+
}
|
|
104
|
+
/** Pending waitpoints, only populated when status === "waiting". */
|
|
105
|
+
pendingWaitpoints: PendingWaitpoint[]
|
|
106
|
+
/** Stream chunks accumulated across every tenant invocation, keyed by streamId. */
|
|
107
|
+
streams: Record<string, StreamChunk[]>
|
|
108
|
+
/** Wall-clock fields, all ms-since-epoch. */
|
|
109
|
+
startedAt: number
|
|
110
|
+
completedAt?: number
|
|
111
|
+
/** Trigger metadata. */
|
|
112
|
+
triggeredBy: RunTrigger
|
|
113
|
+
tags: string[]
|
|
114
|
+
/** Optional environment metadata. */
|
|
115
|
+
environment: "production" | "preview" | "development"
|
|
116
|
+
/** Tenant identity flows through every step request. */
|
|
117
|
+
tenantMeta: {
|
|
118
|
+
tenantId: string
|
|
119
|
+
projectId: string
|
|
120
|
+
organizationId: string
|
|
121
|
+
projectSlug?: string
|
|
122
|
+
organizationSlug?: string
|
|
123
|
+
/**
|
|
124
|
+
* Identifier the runtime adapter uses to locate the tenant's
|
|
125
|
+
* code. On Cloudflare this is the dispatch-namespace script name;
|
|
126
|
+
* on other targets it may be a container image tag or Node script
|
|
127
|
+
* path. Optional so local/in-process drivers aren't forced to set it.
|
|
128
|
+
*/
|
|
129
|
+
tenantScript?: string
|
|
130
|
+
}
|
|
131
|
+
runMeta: {
|
|
132
|
+
number: number
|
|
133
|
+
attempt: number
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Caller-supplied idempotency token, mirrored from `TriggerArgs.idempotencyKey`.
|
|
137
|
+
* Persistent stores use this column to enforce dedup natively (e.g. unique
|
|
138
|
+
* partial index in `voyant_snapshot_runs`); in-process stores ignore it.
|
|
139
|
+
*/
|
|
140
|
+
idempotencyKey?: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface RunRecordStore {
|
|
144
|
+
get(id: string): Promise<RunRecord | undefined>
|
|
145
|
+
save(record: RunRecord): Promise<RunRecord>
|
|
146
|
+
/**
|
|
147
|
+
* Atomically insert a new run record, OR return the existing one if
|
|
148
|
+
* a record with the same `id` already exists. Used by `trigger()` to
|
|
149
|
+
* close the get-then-save race window when an idempotency-derived
|
|
150
|
+
* runId could collide across concurrent callers.
|
|
151
|
+
*
|
|
152
|
+
* Stores must implement this with a single atomic operation:
|
|
153
|
+
* - Postgres: `INSERT … ON CONFLICT (id) DO NOTHING RETURNING …`,
|
|
154
|
+
* with a fallback SELECT when no row is returned.
|
|
155
|
+
* - InMemory / FS: check-then-set in a single microtask.
|
|
156
|
+
* - DO storage: get-then-save is naturally atomic per DO instance.
|
|
157
|
+
*
|
|
158
|
+
* The returned `created: true` means this caller's record was the
|
|
159
|
+
* winner — drive it. `created: false` means another caller raced in
|
|
160
|
+
* first; return the existing record without re-driving (per
|
|
161
|
+
* architecture doc §15.2).
|
|
162
|
+
*/
|
|
163
|
+
tryInsert(record: RunRecord): Promise<{ record: RunRecord; created: boolean }>
|
|
164
|
+
list(filter?: {
|
|
165
|
+
workflowId?: string
|
|
166
|
+
status?: OrchestratorRunStatus
|
|
167
|
+
limit?: number
|
|
168
|
+
}): Promise<RunRecord[]>
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* The tenant-side step handler. In-process for tests / local dev via
|
|
173
|
+
* `handleStepRequest` from @voyant-travel/workflows/handler; HTTP in
|
|
174
|
+
* production (via a fetch to the tenant Worker). The optional
|
|
175
|
+
* per-invocation `signal` aborts in-flight step bodies when the run
|
|
176
|
+
* is cancelled mid-execution.
|
|
177
|
+
*/
|
|
178
|
+
export type StepHandler = (
|
|
179
|
+
req: WorkflowStepRequest,
|
|
180
|
+
opts?: {
|
|
181
|
+
signal?: AbortSignal
|
|
182
|
+
/**
|
|
183
|
+
* Fires synchronously from `ctx.stream.*` as each chunk is
|
|
184
|
+
* produced. In-process only; HTTP transport drops it (chunks
|
|
185
|
+
* still arrive in the response body). Used by orchestrators to
|
|
186
|
+
* broadcast chunks to dashboards before the invocation returns.
|
|
187
|
+
*/
|
|
188
|
+
onStreamChunk?: (chunk: StreamChunk) => void
|
|
189
|
+
},
|
|
190
|
+
) => Promise<
|
|
191
|
+
{ status: number; body: WorkflowStepResponse } | { status: number; body: StepHandlerError }
|
|
192
|
+
>
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Injection delivered by an external signal (dashboard, API, inbox).
|
|
196
|
+
* Same shape used by the dashboard inject endpoints.
|
|
197
|
+
*/
|
|
198
|
+
export type WaitpointInjection =
|
|
199
|
+
| { kind: "EVENT"; eventType: string; payload?: unknown }
|
|
200
|
+
| { kind: "SIGNAL"; name: string; payload?: unknown }
|
|
201
|
+
| { kind: "MANUAL"; tokenId: string; payload?: unknown }
|