workerflow 0.1.0 → 0.2.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/README.md +32 -10
- package/package.json +1 -1
- package/src/definition.ts +126 -174
- package/src/migrations/0000_initial.ts +84 -285
- package/src/runtime.ts +609 -950
- package/test/runtime.spec.ts +618 -1074
- package/demo/README.md +0 -73
- package/demo/index.html +0 -13
- package/demo/package.json +0 -33
- package/demo/public/vite.svg +0 -1
- package/demo/src/App.css +0 -0
- package/demo/src/App.tsx +0 -9
- package/demo/src/assets/Cloudflare_Logo.svg +0 -51
- package/demo/src/assets/react.svg +0 -1
- package/demo/src/index.css +0 -1
- package/demo/src/main.tsx +0 -10
- package/demo/tsconfig.app.json +0 -28
- package/demo/tsconfig.json +0 -14
- package/demo/tsconfig.node.json +0 -25
- package/demo/tsconfig.worker.json +0 -13
- package/demo/vite.config.ts +0 -9
- package/demo/worker/index.ts +0 -16
- package/demo/worker-configuration.d.ts +0 -12851
- package/demo/wrangler.jsonc +0 -32
|
@@ -22,7 +22,7 @@ export default `
|
|
|
22
22
|
|
|
23
23
|
CHECK (updated_at >= created_at),
|
|
24
24
|
|
|
25
|
-
--
|
|
25
|
+
-- definition_input must be NULL if definition_version is NULL
|
|
26
26
|
CHECK (definition_version IS NOT NULL OR definition_input IS NULL),
|
|
27
27
|
|
|
28
28
|
-- definition must be pinned before running/paused/completing/failing; cancelled is always allowed
|
|
@@ -32,348 +32,157 @@ export default `
|
|
|
32
32
|
CREATE TABLE steps (
|
|
33
33
|
id TEXT NOT NULL PRIMARY KEY CHECK (length(id) > 0),
|
|
34
34
|
type TEXT NOT NULL CHECK (type IN ('run', 'sleep', 'wait')),
|
|
35
|
-
|
|
36
|
-
'
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
created_at INTEGER NOT NULL
|
|
36
|
+
DEFAULT (CAST(unixepoch('subsecond') * 1000 AS INTEGER))
|
|
37
|
+
CHECK (created_at >= 0),
|
|
38
|
+
|
|
39
|
+
-- sleep / wait only: run rows use run_step_attempts for lifecycle
|
|
40
|
+
state TEXT CHECK (state IN (
|
|
40
41
|
'waiting',
|
|
41
42
|
'elapsed',
|
|
42
43
|
'satisfied',
|
|
43
44
|
'timed_out'
|
|
44
45
|
)),
|
|
45
|
-
created_at INTEGER NOT NULL
|
|
46
|
-
DEFAULT (CAST(unixepoch('subsecond') * 1000 AS INTEGER))
|
|
47
|
-
CHECK (created_at >= 0),
|
|
48
46
|
|
|
49
|
-
-- run-step fields
|
|
50
|
-
attempt_count INTEGER,
|
|
51
47
|
max_attempts INTEGER,
|
|
52
|
-
next_attempt_at INTEGER,
|
|
53
|
-
result TEXT,
|
|
54
|
-
error_message TEXT,
|
|
55
|
-
error_name TEXT,
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
wake_at INTEGER,
|
|
49
|
+
target_wake_at INTEGER,
|
|
59
50
|
|
|
60
|
-
-- wait-step fields
|
|
61
51
|
event_name TEXT,
|
|
62
52
|
timeout_at INTEGER,
|
|
63
|
-
payload TEXT,
|
|
64
53
|
|
|
65
|
-
-- terminal timestamp
|
|
66
54
|
resolved_at INTEGER,
|
|
67
55
|
|
|
68
|
-
-- innermost enclosing run step when this row was created (nested run / sleep / wait under a run callback)
|
|
69
56
|
parent_step_id TEXT REFERENCES steps(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
70
57
|
|
|
71
|
-
CHECK (attempt_count IS NULL OR attempt_count >= 0),
|
|
72
58
|
CHECK (max_attempts IS NULL OR max_attempts >= 1),
|
|
73
|
-
CHECK (
|
|
74
|
-
CHECK (wake_at IS NULL OR wake_at >= 0),
|
|
59
|
+
CHECK (target_wake_at IS NULL OR target_wake_at >= 0),
|
|
75
60
|
CHECK (timeout_at IS NULL OR timeout_at >= 0),
|
|
76
61
|
CHECK (resolved_at IS NULL OR resolved_at >= created_at),
|
|
77
|
-
CHECK (error_name IS NULL OR length(error_name) > 0),
|
|
78
62
|
CHECK (event_name IS NULL OR length(event_name) > 0),
|
|
79
63
|
|
|
80
|
-
-- run steps may never exceed max_attempts
|
|
81
|
-
CHECK (
|
|
82
|
-
attempt_count IS NULL OR
|
|
83
|
-
max_attempts IS NULL OR
|
|
84
|
-
attempt_count <= max_attempts
|
|
85
|
-
),
|
|
86
|
-
|
|
87
64
|
CHECK (
|
|
88
65
|
(
|
|
89
66
|
type = 'run' AND
|
|
90
|
-
state
|
|
91
|
-
attempt_count IS NOT NULL AND attempt_count >= 0 AND
|
|
92
|
-
(max_attempts IS NULL OR max_attempts >= 1) AND
|
|
93
|
-
(max_attempts IS NULL OR attempt_count < max_attempts) AND
|
|
94
|
-
next_attempt_at IS NOT NULL AND
|
|
95
|
-
result IS NULL AND
|
|
96
|
-
error_message IS NULL AND
|
|
97
|
-
error_name IS NULL AND
|
|
98
|
-
wake_at IS NULL AND
|
|
99
|
-
event_name IS NULL AND
|
|
100
|
-
timeout_at IS NULL AND
|
|
101
|
-
payload IS NULL AND
|
|
102
|
-
resolved_at IS NULL
|
|
103
|
-
)
|
|
104
|
-
OR
|
|
105
|
-
(
|
|
106
|
-
type = 'run' AND
|
|
107
|
-
state = 'running' AND
|
|
108
|
-
attempt_count IS NOT NULL AND attempt_count >= 1 AND
|
|
67
|
+
state IS NULL AND
|
|
109
68
|
(max_attempts IS NULL OR max_attempts >= 1) AND
|
|
110
|
-
|
|
111
|
-
next_attempt_at IS NULL AND
|
|
112
|
-
result IS NULL AND
|
|
113
|
-
error_message IS NULL AND
|
|
114
|
-
error_name IS NULL AND
|
|
115
|
-
wake_at IS NULL AND
|
|
69
|
+
target_wake_at IS NULL AND
|
|
116
70
|
event_name IS NULL AND
|
|
117
71
|
timeout_at IS NULL AND
|
|
118
|
-
payload IS NULL AND
|
|
119
72
|
resolved_at IS NULL
|
|
120
73
|
)
|
|
121
74
|
OR
|
|
122
|
-
(
|
|
123
|
-
type = 'run' AND
|
|
124
|
-
state = 'succeeded' AND
|
|
125
|
-
attempt_count IS NOT NULL AND attempt_count >= 1 AND
|
|
126
|
-
(max_attempts IS NULL OR max_attempts >= 1) AND
|
|
127
|
-
(max_attempts IS NULL OR attempt_count <= max_attempts) AND
|
|
128
|
-
next_attempt_at IS NULL AND
|
|
129
|
-
result IS NOT NULL AND
|
|
130
|
-
error_message IS NULL AND
|
|
131
|
-
error_name IS NULL AND
|
|
132
|
-
wake_at IS NULL AND
|
|
133
|
-
event_name IS NULL AND
|
|
134
|
-
timeout_at IS NULL AND
|
|
135
|
-
payload IS NULL AND
|
|
136
|
-
resolved_at IS NOT NULL
|
|
137
|
-
)
|
|
138
|
-
OR
|
|
139
|
-
(
|
|
140
|
-
type = 'run' AND
|
|
141
|
-
state = 'failed' AND
|
|
142
|
-
attempt_count IS NOT NULL AND attempt_count >= 1 AND
|
|
143
|
-
(max_attempts IS NULL OR max_attempts >= 1) AND
|
|
144
|
-
(max_attempts IS NULL OR attempt_count <= max_attempts) AND
|
|
145
|
-
next_attempt_at IS NULL AND
|
|
146
|
-
result IS NULL AND
|
|
147
|
-
error_message IS NOT NULL AND
|
|
148
|
-
wake_at IS NULL AND
|
|
149
|
-
event_name IS NULL AND
|
|
150
|
-
timeout_at IS NULL AND
|
|
151
|
-
payload IS NULL AND
|
|
152
|
-
resolved_at IS NOT NULL
|
|
153
|
-
)
|
|
154
|
-
OR
|
|
155
75
|
(
|
|
156
76
|
type = 'sleep' AND
|
|
157
77
|
state = 'waiting' AND
|
|
158
|
-
attempt_count IS NULL AND
|
|
159
78
|
max_attempts IS NULL AND
|
|
160
|
-
|
|
161
|
-
result IS NULL AND
|
|
162
|
-
error_message IS NULL AND
|
|
163
|
-
error_name IS NULL AND
|
|
164
|
-
wake_at IS NOT NULL AND
|
|
79
|
+
target_wake_at IS NOT NULL AND
|
|
165
80
|
event_name IS NULL AND
|
|
166
81
|
timeout_at IS NULL AND
|
|
167
|
-
payload IS NULL AND
|
|
168
82
|
resolved_at IS NULL
|
|
169
83
|
)
|
|
170
84
|
OR
|
|
171
85
|
(
|
|
172
86
|
type = 'sleep' AND
|
|
173
87
|
state = 'elapsed' AND
|
|
174
|
-
attempt_count IS NULL AND
|
|
175
88
|
max_attempts IS NULL AND
|
|
176
|
-
|
|
177
|
-
result IS NULL AND
|
|
178
|
-
error_message IS NULL AND
|
|
179
|
-
error_name IS NULL AND
|
|
180
|
-
wake_at IS NULL AND
|
|
89
|
+
target_wake_at IS NOT NULL AND
|
|
181
90
|
event_name IS NULL AND
|
|
182
91
|
timeout_at IS NULL AND
|
|
183
|
-
payload IS NULL AND
|
|
184
92
|
resolved_at IS NOT NULL
|
|
185
93
|
)
|
|
186
94
|
OR
|
|
187
95
|
(
|
|
188
96
|
type = 'wait' AND
|
|
189
97
|
state = 'waiting' AND
|
|
190
|
-
attempt_count IS NULL AND
|
|
191
98
|
max_attempts IS NULL AND
|
|
192
|
-
|
|
193
|
-
result IS NULL AND
|
|
194
|
-
error_message IS NULL AND
|
|
195
|
-
error_name IS NULL AND
|
|
196
|
-
wake_at IS NULL AND
|
|
99
|
+
target_wake_at IS NULL AND
|
|
197
100
|
event_name IS NOT NULL AND
|
|
198
|
-
payload IS NULL AND
|
|
199
101
|
resolved_at IS NULL
|
|
200
102
|
)
|
|
201
103
|
OR
|
|
202
104
|
(
|
|
203
105
|
type = 'wait' AND
|
|
204
106
|
state = 'satisfied' AND
|
|
205
|
-
attempt_count IS NULL AND
|
|
206
107
|
max_attempts IS NULL AND
|
|
207
|
-
|
|
208
|
-
result IS NULL AND
|
|
209
|
-
error_message IS NULL AND
|
|
210
|
-
error_name IS NULL AND
|
|
211
|
-
wake_at IS NULL AND
|
|
108
|
+
target_wake_at IS NULL AND
|
|
212
109
|
event_name IS NOT NULL AND
|
|
213
|
-
timeout_at IS NULL AND
|
|
214
|
-
payload IS NOT NULL AND
|
|
215
110
|
resolved_at IS NOT NULL
|
|
216
111
|
)
|
|
217
112
|
OR
|
|
218
113
|
(
|
|
219
114
|
type = 'wait' AND
|
|
220
115
|
state = 'timed_out' AND
|
|
221
|
-
attempt_count IS NULL AND
|
|
222
116
|
max_attempts IS NULL AND
|
|
223
|
-
|
|
224
|
-
result IS NULL AND
|
|
225
|
-
error_message IS NULL AND
|
|
226
|
-
error_name IS NULL AND
|
|
227
|
-
wake_at IS NULL AND
|
|
117
|
+
target_wake_at IS NULL AND
|
|
228
118
|
event_name IS NOT NULL AND
|
|
229
|
-
timeout_at IS NULL AND
|
|
230
|
-
payload IS NULL AND
|
|
119
|
+
timeout_at IS NOT NULL AND
|
|
231
120
|
resolved_at IS NOT NULL
|
|
232
121
|
)
|
|
233
122
|
),
|
|
234
123
|
CHECK (parent_step_id IS NULL OR parent_step_id <> id)
|
|
235
124
|
) STRICT;
|
|
236
125
|
|
|
237
|
-
CREATE TABLE
|
|
126
|
+
CREATE TABLE run_step_attempts (
|
|
238
127
|
id TEXT NOT NULL PRIMARY KEY
|
|
239
128
|
DEFAULT (lower(hex(randomblob(16))))
|
|
240
129
|
CHECK (length(id) > 0),
|
|
241
130
|
|
|
242
|
-
step_id TEXT NOT NULL,
|
|
243
|
-
|
|
131
|
+
step_id TEXT NOT NULL REFERENCES steps(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
132
|
+
|
|
133
|
+
started_at INTEGER NOT NULL
|
|
244
134
|
DEFAULT (CAST(unixepoch('subsecond') * 1000 AS INTEGER))
|
|
245
|
-
CHECK (
|
|
135
|
+
CHECK (started_at >= 0),
|
|
246
136
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
137
|
+
state TEXT NOT NULL CHECK (state IN ('started', 'succeeded', 'failed')),
|
|
138
|
+
|
|
139
|
+
ended_at INTEGER CHECK (ended_at IS NULL OR ended_at >= started_at),
|
|
140
|
+
|
|
141
|
+
-- Discriminator for the shape of a succeeded result.
|
|
142
|
+
-- 'json' → result_json holds the raw JSON value (never NULL)
|
|
143
|
+
-- 'none' → callback returned undefined/void, result_json IS NULL
|
|
144
|
+
result_type TEXT CHECK (result_type IN ('json', 'none')),
|
|
145
|
+
|
|
146
|
+
-- Raw JSON value. No wrapper objects.
|
|
147
|
+
-- NULL when result_type is 'none', or when the attempt hasn't succeeded yet.
|
|
148
|
+
result_json TEXT CHECK (result_json IS NULL OR json_valid(result_json)),
|
|
257
149
|
|
|
258
|
-
attempt_number INTEGER,
|
|
259
|
-
result TEXT,
|
|
260
150
|
error_message TEXT,
|
|
261
151
|
error_name TEXT,
|
|
262
|
-
next_attempt_at INTEGER,
|
|
263
|
-
wake_at INTEGER,
|
|
264
|
-
event_name TEXT,
|
|
265
|
-
timeout_at INTEGER,
|
|
266
|
-
payload TEXT,
|
|
267
|
-
|
|
268
|
-
FOREIGN KEY (step_id) REFERENCES steps(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
152
|
+
next_attempt_at INTEGER CHECK (next_attempt_at IS NULL OR next_attempt_at >= 0),
|
|
269
153
|
|
|
270
|
-
CHECK (attempt_number IS NULL OR attempt_number >= 1),
|
|
271
|
-
CHECK (next_attempt_at IS NULL OR next_attempt_at >= 0),
|
|
272
|
-
CHECK (wake_at IS NULL OR wake_at >= 0),
|
|
273
|
-
CHECK (timeout_at IS NULL OR timeout_at >= 0),
|
|
274
154
|
CHECK (error_name IS NULL OR length(error_name) > 0),
|
|
275
|
-
CHECK (event_name IS NULL OR length(event_name) > 0),
|
|
276
155
|
|
|
277
156
|
CHECK (
|
|
278
157
|
(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
158
|
+
state = 'started' AND
|
|
159
|
+
ended_at IS NULL AND
|
|
160
|
+
result_type IS NULL AND
|
|
161
|
+
result_json IS NULL AND
|
|
282
162
|
error_message IS NULL AND
|
|
283
163
|
error_name IS NULL AND
|
|
284
|
-
next_attempt_at IS NULL
|
|
285
|
-
wake_at IS NULL AND
|
|
286
|
-
event_name IS NULL AND
|
|
287
|
-
timeout_at IS NULL AND
|
|
288
|
-
payload IS NULL
|
|
164
|
+
next_attempt_at IS NULL
|
|
289
165
|
)
|
|
290
166
|
OR
|
|
291
167
|
(
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
168
|
+
state = 'succeeded' AND
|
|
169
|
+
ended_at IS NOT NULL AND
|
|
170
|
+
result_type IS NOT NULL AND
|
|
171
|
+
(
|
|
172
|
+
(result_type = 'none' AND result_json IS NULL) OR
|
|
173
|
+
(result_type = 'json' AND result_json IS NOT NULL)
|
|
174
|
+
) AND
|
|
295
175
|
error_message IS NULL AND
|
|
296
176
|
error_name IS NULL AND
|
|
297
|
-
next_attempt_at IS NULL
|
|
298
|
-
wake_at IS NULL AND
|
|
299
|
-
event_name IS NULL AND
|
|
300
|
-
timeout_at IS NULL AND
|
|
301
|
-
payload IS NULL
|
|
177
|
+
next_attempt_at IS NULL
|
|
302
178
|
)
|
|
303
179
|
OR
|
|
304
180
|
(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
result IS NULL AND
|
|
181
|
+
state = 'failed' AND
|
|
182
|
+
ended_at IS NOT NULL AND
|
|
308
183
|
error_message IS NOT NULL AND
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
timeout_at IS NULL AND
|
|
312
|
-
payload IS NULL
|
|
313
|
-
)
|
|
314
|
-
OR
|
|
315
|
-
(
|
|
316
|
-
type = 'sleep_waiting' AND
|
|
317
|
-
attempt_number IS NULL AND
|
|
318
|
-
result IS NULL AND
|
|
319
|
-
error_message IS NULL AND
|
|
320
|
-
error_name IS NULL AND
|
|
321
|
-
next_attempt_at IS NULL AND
|
|
322
|
-
wake_at IS NOT NULL AND
|
|
323
|
-
event_name IS NULL AND
|
|
324
|
-
timeout_at IS NULL AND
|
|
325
|
-
payload IS NULL
|
|
326
|
-
)
|
|
327
|
-
OR
|
|
328
|
-
(
|
|
329
|
-
type = 'sleep_elapsed' AND
|
|
330
|
-
attempt_number IS NULL AND
|
|
331
|
-
result IS NULL AND
|
|
332
|
-
error_message IS NULL AND
|
|
333
|
-
error_name IS NULL AND
|
|
334
|
-
next_attempt_at IS NULL AND
|
|
335
|
-
wake_at IS NULL AND
|
|
336
|
-
event_name IS NULL AND
|
|
337
|
-
timeout_at IS NULL AND
|
|
338
|
-
payload IS NULL
|
|
339
|
-
)
|
|
340
|
-
OR
|
|
341
|
-
(
|
|
342
|
-
type = 'wait_waiting' AND
|
|
343
|
-
attempt_number IS NULL AND
|
|
344
|
-
result IS NULL AND
|
|
345
|
-
error_message IS NULL AND
|
|
346
|
-
error_name IS NULL AND
|
|
347
|
-
next_attempt_at IS NULL AND
|
|
348
|
-
wake_at IS NULL AND
|
|
349
|
-
event_name IS NOT NULL AND
|
|
350
|
-
payload IS NULL
|
|
351
|
-
)
|
|
352
|
-
OR
|
|
353
|
-
(
|
|
354
|
-
type = 'wait_satisfied' AND
|
|
355
|
-
attempt_number IS NULL AND
|
|
356
|
-
result IS NULL AND
|
|
357
|
-
error_message IS NULL AND
|
|
358
|
-
error_name IS NULL AND
|
|
359
|
-
next_attempt_at IS NULL AND
|
|
360
|
-
wake_at IS NULL AND
|
|
361
|
-
event_name IS NULL AND
|
|
362
|
-
timeout_at IS NULL AND
|
|
363
|
-
payload IS NOT NULL
|
|
364
|
-
)
|
|
365
|
-
OR
|
|
366
|
-
(
|
|
367
|
-
type = 'wait_timed_out' AND
|
|
368
|
-
attempt_number IS NULL AND
|
|
369
|
-
result IS NULL AND
|
|
370
|
-
error_message IS NULL AND
|
|
371
|
-
error_name IS NULL AND
|
|
372
|
-
next_attempt_at IS NULL AND
|
|
373
|
-
wake_at IS NULL AND
|
|
374
|
-
event_name IS NULL AND
|
|
375
|
-
timeout_at IS NULL AND
|
|
376
|
-
payload IS NULL
|
|
184
|
+
result_type IS NULL AND
|
|
185
|
+
result_json IS NULL
|
|
377
186
|
)
|
|
378
187
|
)
|
|
379
188
|
) STRICT;
|
|
@@ -405,6 +214,8 @@ export default `
|
|
|
405
214
|
DEFAULT (lower(hex(randomblob(16))))
|
|
406
215
|
CHECK (length(id) > 0),
|
|
407
216
|
event_name TEXT NOT NULL CHECK (length(event_name) > 0),
|
|
217
|
+
-- Raw JSON value, or SQL NULL when no payload was provided (undefined).
|
|
218
|
+
-- JSON null is stored as the TEXT literal 'null', distinct from SQL NULL.
|
|
408
219
|
payload TEXT CHECK (payload IS NULL OR json_valid(payload)),
|
|
409
220
|
created_at INTEGER NOT NULL
|
|
410
221
|
DEFAULT (CAST(unixepoch('subsecond') * 1000 AS INTEGER))
|
|
@@ -414,20 +225,21 @@ export default `
|
|
|
414
225
|
|
|
415
226
|
FOREIGN KEY (claimed_by) REFERENCES steps(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
416
227
|
|
|
417
|
-
-- claimed_by and claimed_at must be set together or not set at all
|
|
418
228
|
CHECK (
|
|
419
229
|
(claimed_by IS NULL AND claimed_at IS NULL) OR
|
|
420
230
|
(claimed_by IS NOT NULL AND claimed_at IS NOT NULL)
|
|
421
231
|
)
|
|
422
232
|
) STRICT;
|
|
423
233
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
234
|
+
CREATE INDEX run_step_attempts_by_step_time_idx
|
|
235
|
+
ON run_step_attempts(step_id, started_at, id);
|
|
236
|
+
|
|
237
|
+
CREATE INDEX run_step_attempts_started_one_idx
|
|
238
|
+
ON run_step_attempts(step_id)
|
|
239
|
+
WHERE state = 'started';
|
|
428
240
|
|
|
429
241
|
CREATE INDEX steps_sleep_waiting_by_time_idx
|
|
430
|
-
ON steps(
|
|
242
|
+
ON steps(target_wake_at, id)
|
|
431
243
|
WHERE type = 'sleep' AND state = 'waiting';
|
|
432
244
|
|
|
433
245
|
CREATE INDEX steps_wait_waiting_by_event_idx
|
|
@@ -442,20 +254,16 @@ export default `
|
|
|
442
254
|
ON steps(parent_step_id, id)
|
|
443
255
|
WHERE parent_step_id IS NOT NULL;
|
|
444
256
|
|
|
445
|
-
CREATE INDEX step_events_by_step_and_time_idx
|
|
446
|
-
ON step_events(step_id, recorded_at, id);
|
|
447
|
-
|
|
448
257
|
CREATE INDEX workflow_events_by_time_idx
|
|
449
258
|
ON workflow_events(recorded_at, id);
|
|
450
259
|
|
|
451
260
|
CREATE INDEX inbound_events_by_name_and_time_idx
|
|
452
261
|
ON inbound_events(event_name, created_at, id);
|
|
453
262
|
|
|
454
|
-
CREATE INDEX
|
|
455
|
-
ON inbound_events(claimed_by
|
|
263
|
+
CREATE UNIQUE INDEX inbound_events_claimed_by_unique
|
|
264
|
+
ON inbound_events(claimed_by)
|
|
456
265
|
WHERE claimed_by IS NOT NULL;
|
|
457
266
|
|
|
458
|
-
-- immutable identity fields
|
|
459
267
|
CREATE TRIGGER workflow_metadata_immutable_fields
|
|
460
268
|
BEFORE UPDATE ON workflow_metadata
|
|
461
269
|
FOR EACH ROW
|
|
@@ -464,7 +272,6 @@ export default `
|
|
|
464
272
|
SELECT RAISE(ABORT, 'workflow_metadata.id and workflow_metadata.created_at are immutable');
|
|
465
273
|
END;
|
|
466
274
|
|
|
467
|
-
-- valid status transitions
|
|
468
275
|
CREATE TRIGGER workflow_metadata_valid_transition
|
|
469
276
|
BEFORE UPDATE ON workflow_metadata
|
|
470
277
|
FOR EACH ROW
|
|
@@ -507,22 +314,34 @@ export default `
|
|
|
507
314
|
SELECT RAISE(ABORT, 'steps.parent_step_id must reference a run step');
|
|
508
315
|
END;
|
|
509
316
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
317
|
+
CREATE TRIGGER run_step_attempts_step_must_be_run
|
|
318
|
+
BEFORE INSERT ON run_step_attempts
|
|
319
|
+
WHEN (SELECT type FROM steps WHERE id = NEW.step_id) IS NOT 'run'
|
|
320
|
+
BEGIN
|
|
321
|
+
SELECT RAISE(ABORT, 'run_step_attempts.step_id must reference a run step');
|
|
322
|
+
END;
|
|
323
|
+
|
|
324
|
+
CREATE TRIGGER run_step_attempts_at_most_one_started_ins
|
|
325
|
+
BEFORE INSERT ON run_step_attempts
|
|
326
|
+
WHEN NEW.state = 'started'
|
|
327
|
+
AND EXISTS (SELECT 1 FROM run_step_attempts WHERE step_id = NEW.step_id AND state = 'started')
|
|
514
328
|
BEGIN
|
|
515
|
-
SELECT RAISE(ABORT, '
|
|
329
|
+
SELECT RAISE(ABORT, 'run step already has an in-flight attempt');
|
|
516
330
|
END;
|
|
517
331
|
|
|
518
|
-
CREATE TRIGGER
|
|
519
|
-
BEFORE
|
|
332
|
+
CREATE TRIGGER run_step_attempts_valid_transition
|
|
333
|
+
BEFORE UPDATE ON run_step_attempts
|
|
520
334
|
FOR EACH ROW
|
|
335
|
+
WHEN NEW.state <> OLD.state
|
|
521
336
|
BEGIN
|
|
522
|
-
SELECT
|
|
337
|
+
SELECT CASE
|
|
338
|
+
WHEN OLD.state = 'started' AND NEW.state NOT IN ('succeeded', 'failed') THEN
|
|
339
|
+
RAISE(ABORT, 'started can only transition to succeeded or failed')
|
|
340
|
+
WHEN OLD.state IN ('succeeded', 'failed') THEN
|
|
341
|
+
RAISE(ABORT, 'terminal attempt state cannot transition')
|
|
342
|
+
END;
|
|
523
343
|
END;
|
|
524
344
|
|
|
525
|
-
-- append-only workflow events
|
|
526
345
|
CREATE TRIGGER workflow_events_append_only_update
|
|
527
346
|
BEFORE UPDATE ON workflow_events
|
|
528
347
|
FOR EACH ROW
|
|
@@ -536,24 +355,4 @@ export default `
|
|
|
536
355
|
BEGIN
|
|
537
356
|
SELECT RAISE(ABORT, 'workflow_events is append-only');
|
|
538
357
|
END;
|
|
539
|
-
|
|
540
|
-
-- step_events.type must match the referenced row in steps.type
|
|
541
|
-
CREATE TRIGGER step_events_parent_type_match
|
|
542
|
-
BEFORE INSERT ON step_events
|
|
543
|
-
FOR EACH ROW
|
|
544
|
-
BEGIN
|
|
545
|
-
SELECT CASE
|
|
546
|
-
WHEN NOT EXISTS (SELECT 1 FROM steps WHERE id = NEW.step_id) THEN
|
|
547
|
-
RAISE(ABORT, 'step_events.step_id does not reference an existing steps row')
|
|
548
|
-
WHEN NEW.type IN ('attempt_started', 'attempt_succeeded', 'attempt_failed')
|
|
549
|
-
AND (SELECT type FROM steps WHERE id = NEW.step_id) <> 'run' THEN
|
|
550
|
-
RAISE(ABORT, 'run attempt events require a run step')
|
|
551
|
-
WHEN NEW.type IN ('sleep_waiting', 'sleep_elapsed')
|
|
552
|
-
AND (SELECT type FROM steps WHERE id = NEW.step_id) <> 'sleep' THEN
|
|
553
|
-
RAISE(ABORT, 'sleep events require a sleep step')
|
|
554
|
-
WHEN NEW.type IN ('wait_waiting', 'wait_satisfied', 'wait_timed_out')
|
|
555
|
-
AND (SELECT type FROM steps WHERE id = NEW.step_id) <> 'wait' THEN
|
|
556
|
-
RAISE(ABORT, 'wait events require a wait step')
|
|
557
|
-
END;
|
|
558
|
-
END;
|
|
559
358
|
`;
|