@cogitator-ai/workflows 0.8.0 → 0.10.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 +106 -9
- package/dist/builder.d.ts +2 -2
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js.map +1 -1
- package/dist/checkpoint-stores.d.ts.map +1 -1
- package/dist/checkpoint-stores.js +4 -5
- package/dist/checkpoint-stores.js.map +1 -1
- package/dist/executor.d.ts +8 -8
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +83 -8
- package/dist/executor.js.map +1 -1
- package/dist/human/approval-outcomes.d.ts +26 -0
- package/dist/human/approval-outcomes.d.ts.map +1 -0
- package/dist/human/approval-outcomes.js +61 -0
- package/dist/human/approval-outcomes.js.map +1 -0
- package/dist/human/approval-store.d.ts +12 -0
- package/dist/human/approval-store.d.ts.map +1 -1
- package/dist/human/approval-store.js +52 -9
- package/dist/human/approval-store.js.map +1 -1
- package/dist/human/durable-approval-stores.d.ts +118 -0
- package/dist/human/durable-approval-stores.d.ts.map +1 -0
- package/dist/human/durable-approval-stores.js +383 -0
- package/dist/human/durable-approval-stores.js.map +1 -0
- package/dist/human/human-node.d.ts +16 -8
- package/dist/human/human-node.d.ts.map +1 -1
- package/dist/human/human-node.js +48 -26
- package/dist/human/human-node.js.map +1 -1
- package/dist/human/index.d.ts +2 -1
- package/dist/human/index.d.ts.map +1 -1
- package/dist/human/index.js +1 -0
- package/dist/human/index.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/manager/durable-run-stores.d.ts +88 -0
- package/dist/manager/durable-run-stores.d.ts.map +1 -0
- package/dist/manager/durable-run-stores.js +492 -0
- package/dist/manager/durable-run-stores.js.map +1 -0
- package/dist/manager/run-store.d.ts +1 -0
- package/dist/manager/run-store.d.ts.map +1 -1
- package/dist/manager/run-store.js +21 -10
- package/dist/manager/run-store.js.map +1 -1
- package/dist/manager/workflow-manager.d.ts +59 -8
- package/dist/manager/workflow-manager.d.ts.map +1 -1
- package/dist/manager/workflow-manager.js +272 -192
- package/dist/manager/workflow-manager.js.map +1 -1
- package/dist/nodes/adapters.d.ts +3 -2
- package/dist/nodes/adapters.d.ts.map +1 -1
- package/dist/nodes/adapters.js +15 -3
- package/dist/nodes/adapters.js.map +1 -1
- package/dist/nodes/base.d.ts +4 -1
- package/dist/nodes/base.d.ts.map +1 -1
- package/dist/observability/exporters.js +1 -1
- package/dist/observability/exporters.js.map +1 -1
- package/dist/observability/metrics.d.ts +2 -0
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/metrics.js +4 -0
- package/dist/observability/metrics.js.map +1 -1
- package/dist/observability/tracer.d.ts +1 -0
- package/dist/observability/tracer.d.ts.map +1 -1
- package/dist/observability/tracer.js +2 -1
- package/dist/observability/tracer.js.map +1 -1
- package/dist/postgres-schema.d.ts +18 -0
- package/dist/postgres-schema.d.ts.map +1 -0
- package/dist/postgres-schema.js +35 -0
- package/dist/postgres-schema.js.map +1 -0
- package/dist/saga/compensation.d.ts +8 -1
- package/dist/saga/compensation.d.ts.map +1 -1
- package/dist/saga/compensation.js +6 -3
- package/dist/saga/compensation.js.map +1 -1
- package/dist/saga/index.d.ts +1 -1
- package/dist/saga/index.d.ts.map +1 -1
- package/dist/saga/index.js.map +1 -1
- package/dist/subworkflows/parallel-subworkflows.d.ts +15 -11
- package/dist/subworkflows/parallel-subworkflows.d.ts.map +1 -1
- package/dist/subworkflows/parallel-subworkflows.js +21 -31
- package/dist/subworkflows/parallel-subworkflows.js.map +1 -1
- package/dist/timers/durable-timer-stores.d.ts +174 -0
- package/dist/timers/durable-timer-stores.d.ts.map +1 -0
- package/dist/timers/durable-timer-stores.js +501 -0
- package/dist/timers/durable-timer-stores.js.map +1 -0
- package/dist/timers/timer-manager.d.ts +28 -1
- package/dist/timers/timer-manager.d.ts.map +1 -1
- package/dist/timers/timer-manager.js +87 -3
- package/dist/timers/timer-manager.js.map +1 -1
- package/dist/timers/timer-node.d.ts +2 -0
- package/dist/timers/timer-node.d.ts.map +1 -1
- package/dist/timers/timer-node.js +6 -0
- package/dist/timers/timer-node.js.map +1 -1
- package/dist/triggers/cron-trigger.d.ts +6 -0
- package/dist/triggers/cron-trigger.d.ts.map +1 -1
- package/dist/triggers/cron-trigger.js +23 -2
- package/dist/triggers/cron-trigger.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable workflow timer stores: Redis and Postgres.
|
|
3
|
+
*
|
|
4
|
+
* Several workers may run a `TimerManager` against one durable store, so
|
|
5
|
+
* `getOverdue()` claims what it returns: each overdue timer is leased to the
|
|
6
|
+
* store instance that returned it for `claimTtl` ms and skipped by every
|
|
7
|
+
* other `getOverdue()` until `markFired`/`cancel` ends the claim, the owner
|
|
8
|
+
* gives it up with `release`, or the lease runs out (a crashed worker's
|
|
9
|
+
* timers come back after that). The owner keeps a long-running timer with
|
|
10
|
+
* `renew`; a timer whose handler failed stays claimed, so it is retried once
|
|
11
|
+
* its lease expires.
|
|
12
|
+
*/
|
|
13
|
+
import { nanoid } from 'nanoid';
|
|
14
|
+
import { createIfMissing, fromJson, TABLE_NAME } from '../postgres-schema.js';
|
|
15
|
+
const DEFAULT_CLAIM_TTL = 60_000;
|
|
16
|
+
function createTimer(entry) {
|
|
17
|
+
return {
|
|
18
|
+
...entry,
|
|
19
|
+
id: `timer_${nanoid(12)}`,
|
|
20
|
+
cancelled: false,
|
|
21
|
+
fired: false,
|
|
22
|
+
createdAt: Date.now(),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function isPending(timer) {
|
|
26
|
+
return !timer.cancelled && !timer.fired;
|
|
27
|
+
}
|
|
28
|
+
function byFiresAt(a, b) {
|
|
29
|
+
return a.firesAt - b.firesAt;
|
|
30
|
+
}
|
|
31
|
+
function matchesFilter(timer, filter) {
|
|
32
|
+
if (filter?.enabled !== undefined && (timer.enabled ?? true) !== filter.enabled)
|
|
33
|
+
return false;
|
|
34
|
+
return !filter?.type || timer.type === filter.type;
|
|
35
|
+
}
|
|
36
|
+
function claimTtlOf(claimTtl) {
|
|
37
|
+
const ttl = claimTtl ?? DEFAULT_CLAIM_TTL;
|
|
38
|
+
if (!Number.isFinite(ttl) || ttl <= 0) {
|
|
39
|
+
throw new Error(`Invalid timer claimTtl: ${ttl}`);
|
|
40
|
+
}
|
|
41
|
+
return ttl;
|
|
42
|
+
}
|
|
43
|
+
class FireListeners {
|
|
44
|
+
callbacks = [];
|
|
45
|
+
add(callback) {
|
|
46
|
+
this.callbacks.push(callback);
|
|
47
|
+
return () => {
|
|
48
|
+
const idx = this.callbacks.indexOf(callback);
|
|
49
|
+
if (idx !== -1)
|
|
50
|
+
this.callbacks.splice(idx, 1);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
emit(entry) {
|
|
54
|
+
for (const callback of this.callbacks) {
|
|
55
|
+
try {
|
|
56
|
+
callback(entry);
|
|
57
|
+
}
|
|
58
|
+
catch { }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Timers in Redis: each as JSON under its id, indexed by sorted sets scored
|
|
64
|
+
* by `firesAt` (all timers, pending timers, per workflow, per run) and a
|
|
65
|
+
* sorted set of finished timers scored by `createdAt` for `cleanup`.
|
|
66
|
+
*
|
|
67
|
+
* A claim is a per-timer sorted set of lease generations scored by their
|
|
68
|
+
* expiry. Claiming adds the next generation; only the caller whose `ZADD`
|
|
69
|
+
* creates it owns the lease, and it backs off if another generation is still
|
|
70
|
+
* live afterwards, so concurrent workers never share one. Each store
|
|
71
|
+
* instance remembers the generations it holds, which is what `renew` and
|
|
72
|
+
* `release` act on. Leases are measured on the workers' clocks, so keep
|
|
73
|
+
* them in sync.
|
|
74
|
+
*
|
|
75
|
+
* `cancel`, `markFired` and `update` read, change and write a timer, so
|
|
76
|
+
* concurrent writes to one timer are last-writer-wins. `onFire` callbacks run
|
|
77
|
+
* in the process that calls `markFired`.
|
|
78
|
+
*/
|
|
79
|
+
export class RedisTimerStore {
|
|
80
|
+
claimTtl;
|
|
81
|
+
client;
|
|
82
|
+
prefix;
|
|
83
|
+
listeners = new FireListeners();
|
|
84
|
+
held = new Map();
|
|
85
|
+
constructor(options) {
|
|
86
|
+
this.client = options.client;
|
|
87
|
+
this.prefix = options.keyPrefix ?? 'cogitator:workflow-timers';
|
|
88
|
+
this.claimTtl = claimTtlOf(options.claimTtl);
|
|
89
|
+
}
|
|
90
|
+
async schedule(entry) {
|
|
91
|
+
const timer = createTimer(entry);
|
|
92
|
+
await this.write(timer, null);
|
|
93
|
+
return timer.id;
|
|
94
|
+
}
|
|
95
|
+
async get(id) {
|
|
96
|
+
const raw = await this.client.get(this.timerKey(id));
|
|
97
|
+
return raw ? JSON.parse(raw) : null;
|
|
98
|
+
}
|
|
99
|
+
async cancel(id) {
|
|
100
|
+
const timer = await this.get(id);
|
|
101
|
+
if (!timer || !isPending(timer))
|
|
102
|
+
return;
|
|
103
|
+
await this.write({ ...timer, cancelled: true }, timer);
|
|
104
|
+
}
|
|
105
|
+
/** Extends this instance's live claim on a timer; `false` when it no longer holds one. */
|
|
106
|
+
async renew(id) {
|
|
107
|
+
const generation = this.held.get(id);
|
|
108
|
+
if (generation === undefined)
|
|
109
|
+
return false;
|
|
110
|
+
const key = this.claimKey(id);
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
const live = await this.client.zrangebyscore(key, `(${now}`, '+inf');
|
|
113
|
+
if (!live.includes(generation)) {
|
|
114
|
+
this.held.delete(id);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
await this.client.zadd(key, now + this.claimTtl, generation);
|
|
118
|
+
const contenders = await this.client.zrangebyscore(key, `(${now}`, '+inf');
|
|
119
|
+
if (contenders.some((other) => other !== generation)) {
|
|
120
|
+
await this.client.zadd(key, 0, generation);
|
|
121
|
+
this.held.delete(id);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
/** Expires this instance's claim on a timer so any worker can take it now. */
|
|
127
|
+
async release(id) {
|
|
128
|
+
const generation = this.held.get(id);
|
|
129
|
+
if (generation === undefined)
|
|
130
|
+
return;
|
|
131
|
+
this.held.delete(id);
|
|
132
|
+
const key = this.claimKey(id);
|
|
133
|
+
const live = await this.client.zrangebyscore(key, `(${Date.now()}`, '+inf');
|
|
134
|
+
if (live.includes(generation))
|
|
135
|
+
await this.client.zadd(key, 0, generation);
|
|
136
|
+
}
|
|
137
|
+
async getByWorkflow(workflowId) {
|
|
138
|
+
const timers = await this.loadIndex(this.workflowKey(workflowId));
|
|
139
|
+
return timers.filter((timer) => timer.workflowId === workflowId);
|
|
140
|
+
}
|
|
141
|
+
async getByRun(runId) {
|
|
142
|
+
const timers = await this.loadIndex(this.runKey(runId));
|
|
143
|
+
return timers.filter((timer) => timer.runId === runId);
|
|
144
|
+
}
|
|
145
|
+
async getPending() {
|
|
146
|
+
const timers = await this.loadIndex(this.pendingKey());
|
|
147
|
+
return timers.filter(isPending);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Overdue pending timers, oldest first, each claimed for `claimTtl` ms:
|
|
151
|
+
* timers claimed by another caller are left out until their lease expires.
|
|
152
|
+
*/
|
|
153
|
+
async getOverdue() {
|
|
154
|
+
const now = Date.now();
|
|
155
|
+
const ids = await this.client.zrangebyscore(this.pendingKey(), '-inf', now);
|
|
156
|
+
const claimed = await Promise.all(ids.map((id) => this.claimIfDue(id, now)));
|
|
157
|
+
return claimed.filter((timer) => timer !== null).sort(byFiresAt);
|
|
158
|
+
}
|
|
159
|
+
async markFired(id) {
|
|
160
|
+
const timer = await this.get(id);
|
|
161
|
+
if (!timer || !isPending(timer))
|
|
162
|
+
return;
|
|
163
|
+
const fired = { ...timer, fired: true };
|
|
164
|
+
await this.write(fired, timer);
|
|
165
|
+
this.listeners.emit(fired);
|
|
166
|
+
}
|
|
167
|
+
async cleanup(olderThan) {
|
|
168
|
+
const cutoff = Date.now() - olderThan;
|
|
169
|
+
const ids = await this.client.zrangebyscore(this.doneKey(), '-inf', `(${cutoff}`);
|
|
170
|
+
let count = 0;
|
|
171
|
+
for (const id of ids) {
|
|
172
|
+
const timer = await this.get(id);
|
|
173
|
+
if (!timer) {
|
|
174
|
+
await this.client.zrem(this.doneKey(), id);
|
|
175
|
+
await this.client.zrem(this.allKey(), id);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (isPending(timer)) {
|
|
179
|
+
await this.client.zrem(this.doneKey(), id);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (timer.createdAt >= cutoff)
|
|
183
|
+
continue;
|
|
184
|
+
await this.client.del(this.timerKey(id));
|
|
185
|
+
await this.unindex(timer);
|
|
186
|
+
count++;
|
|
187
|
+
}
|
|
188
|
+
return count;
|
|
189
|
+
}
|
|
190
|
+
onFire(callback) {
|
|
191
|
+
return this.listeners.add(callback);
|
|
192
|
+
}
|
|
193
|
+
/** Patches a timer; it keeps its id, and a patch that finishes it ends its claim. */
|
|
194
|
+
async update(id, patch) {
|
|
195
|
+
const timer = await this.get(id);
|
|
196
|
+
if (!timer)
|
|
197
|
+
return;
|
|
198
|
+
await this.write({ ...timer, ...patch, id }, timer);
|
|
199
|
+
}
|
|
200
|
+
async list(filter) {
|
|
201
|
+
const timers = await this.loadIndex(this.allKey());
|
|
202
|
+
return timers.filter((timer) => matchesFilter(timer, filter));
|
|
203
|
+
}
|
|
204
|
+
async claimIfDue(id, now) {
|
|
205
|
+
const generation = await this.claim(id, now);
|
|
206
|
+
if (generation === null)
|
|
207
|
+
return null;
|
|
208
|
+
const timer = await this.get(id);
|
|
209
|
+
if (timer && isPending(timer)) {
|
|
210
|
+
if (timer.firesAt <= now) {
|
|
211
|
+
this.held.set(id, generation);
|
|
212
|
+
return timer;
|
|
213
|
+
}
|
|
214
|
+
await this.client.zadd(this.claimKey(id), 0, generation);
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
await this.client.zrem(this.pendingKey(), id);
|
|
218
|
+
await this.client.del(this.claimKey(id));
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Takes the lease on a timer unless a live one exists, returning the lease
|
|
223
|
+
* generation it now owns. Generations only grow while the claim key lives,
|
|
224
|
+
* and releasing a lease expires its generation in place, so two callers can
|
|
225
|
+
* only contend for the same generation and `ZADD` picks one of them; a
|
|
226
|
+
* winner that finds an older generation renewed meanwhile backs off.
|
|
227
|
+
*/
|
|
228
|
+
async claim(id, now) {
|
|
229
|
+
const key = this.claimKey(id);
|
|
230
|
+
const generations = await this.client.zrange(key, 0, -1);
|
|
231
|
+
const live = await this.client.zrangebyscore(key, `(${now}`, '+inf');
|
|
232
|
+
if (live.length > 0)
|
|
233
|
+
return null;
|
|
234
|
+
const latest = generations.reduce((max, generation) => Math.max(max, Number(generation)), -1);
|
|
235
|
+
const next = String(latest + 1);
|
|
236
|
+
const added = await this.client.zadd(key, now + this.claimTtl, next);
|
|
237
|
+
if (added !== 1)
|
|
238
|
+
return null;
|
|
239
|
+
const contenders = await this.client.zrangebyscore(key, `(${now}`, '+inf');
|
|
240
|
+
if (contenders.some((other) => other !== next)) {
|
|
241
|
+
await this.client.zadd(key, 0, next);
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return next;
|
|
245
|
+
}
|
|
246
|
+
async write(timer, previous) {
|
|
247
|
+
await this.client.set(this.timerKey(timer.id), JSON.stringify(timer));
|
|
248
|
+
if (previous && previous.workflowId !== timer.workflowId) {
|
|
249
|
+
await this.client.zrem(this.workflowKey(previous.workflowId), timer.id);
|
|
250
|
+
}
|
|
251
|
+
if (previous && previous.runId !== timer.runId) {
|
|
252
|
+
await this.client.zrem(this.runKey(previous.runId), timer.id);
|
|
253
|
+
}
|
|
254
|
+
await this.client.zadd(this.allKey(), timer.firesAt, timer.id);
|
|
255
|
+
await this.client.zadd(this.workflowKey(timer.workflowId), timer.firesAt, timer.id);
|
|
256
|
+
await this.client.zadd(this.runKey(timer.runId), timer.firesAt, timer.id);
|
|
257
|
+
if (isPending(timer)) {
|
|
258
|
+
await this.client.zadd(this.pendingKey(), timer.firesAt, timer.id);
|
|
259
|
+
await this.client.zrem(this.doneKey(), timer.id);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
await this.client.zadd(this.doneKey(), timer.createdAt, timer.id);
|
|
263
|
+
await this.client.zrem(this.pendingKey(), timer.id);
|
|
264
|
+
await this.client.del(this.claimKey(timer.id));
|
|
265
|
+
this.held.delete(timer.id);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
async unindex(timer) {
|
|
269
|
+
await this.client.zrem(this.allKey(), timer.id);
|
|
270
|
+
await this.client.zrem(this.pendingKey(), timer.id);
|
|
271
|
+
await this.client.zrem(this.doneKey(), timer.id);
|
|
272
|
+
await this.client.zrem(this.workflowKey(timer.workflowId), timer.id);
|
|
273
|
+
await this.client.zrem(this.runKey(timer.runId), timer.id);
|
|
274
|
+
await this.client.del(this.claimKey(timer.id));
|
|
275
|
+
}
|
|
276
|
+
async loadIndex(key) {
|
|
277
|
+
const ids = await this.client.zrange(key, 0, -1);
|
|
278
|
+
const loaded = await Promise.all(ids.map((id) => this.get(id)));
|
|
279
|
+
const missing = ids.filter((_, i) => loaded[i] === null);
|
|
280
|
+
if (missing.length > 0)
|
|
281
|
+
await this.client.zrem(key, ...missing);
|
|
282
|
+
return loaded.filter((timer) => timer !== null).sort(byFiresAt);
|
|
283
|
+
}
|
|
284
|
+
timerKey(id) {
|
|
285
|
+
return `${this.prefix}:timer:${id}`;
|
|
286
|
+
}
|
|
287
|
+
claimKey(id) {
|
|
288
|
+
return `${this.prefix}:claim:${id}`;
|
|
289
|
+
}
|
|
290
|
+
allKey() {
|
|
291
|
+
return `${this.prefix}:all`;
|
|
292
|
+
}
|
|
293
|
+
pendingKey() {
|
|
294
|
+
return `${this.prefix}:pending`;
|
|
295
|
+
}
|
|
296
|
+
doneKey() {
|
|
297
|
+
return `${this.prefix}:done`;
|
|
298
|
+
}
|
|
299
|
+
workflowKey(workflowId) {
|
|
300
|
+
return `${this.prefix}:workflow:${workflowId}`;
|
|
301
|
+
}
|
|
302
|
+
runKey(runId) {
|
|
303
|
+
return `${this.prefix}:run:${runId}`;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const statusOf = (data) => `CASE WHEN (${data}->>'fired')::boolean THEN 'fired'
|
|
307
|
+
WHEN (${data}->>'cancelled')::boolean THEN 'cancelled'
|
|
308
|
+
ELSE 'pending' END`;
|
|
309
|
+
/**
|
|
310
|
+
* Timers in a Postgres table, as JSONB rows with indexed `status`,
|
|
311
|
+
* `fires_at`, `workflow_id` and `run_id` columns.
|
|
312
|
+
*
|
|
313
|
+
* `getOverdue()` claims rows with `UPDATE … SET claimed_until, claimed_by`
|
|
314
|
+
* over a `SELECT … FOR UPDATE SKIP LOCKED`, so concurrent workers split the
|
|
315
|
+
* overdue timers between them; `claimed_by` is a random id per store
|
|
316
|
+
* instance, which `renew` and `release` check. Leases are measured on the
|
|
317
|
+
* database clock. `cancel`,
|
|
318
|
+
* `markFired` and `update` are single statements, so concurrent writers never
|
|
319
|
+
* lose each other's changes and `onFire` callbacks run once, in the process
|
|
320
|
+
* whose `markFired` fired the timer.
|
|
321
|
+
*/
|
|
322
|
+
export class PostgresTimerStore {
|
|
323
|
+
claimTtl;
|
|
324
|
+
client;
|
|
325
|
+
table;
|
|
326
|
+
owner = nanoid();
|
|
327
|
+
listeners = new FireListeners();
|
|
328
|
+
ready;
|
|
329
|
+
constructor(options) {
|
|
330
|
+
const table = options.table ?? 'cogitator_workflow_timers';
|
|
331
|
+
if (!TABLE_NAME.test(table)) {
|
|
332
|
+
throw new Error(`Invalid timer table name: ${table}`);
|
|
333
|
+
}
|
|
334
|
+
this.client = options.client;
|
|
335
|
+
this.table = table;
|
|
336
|
+
this.claimTtl = claimTtlOf(options.claimTtl);
|
|
337
|
+
}
|
|
338
|
+
async schedule(entry) {
|
|
339
|
+
await this.ensureTable();
|
|
340
|
+
const timer = createTimer(entry);
|
|
341
|
+
await this.client.query(`INSERT INTO ${this.table} (id, workflow_id, run_id, status, fires_at, created_at, data)
|
|
342
|
+
VALUES ($1, $2, $3, 'pending', $4, $5, $6)`, [
|
|
343
|
+
timer.id,
|
|
344
|
+
timer.workflowId,
|
|
345
|
+
timer.runId,
|
|
346
|
+
timer.firesAt,
|
|
347
|
+
timer.createdAt,
|
|
348
|
+
JSON.stringify(timer),
|
|
349
|
+
]);
|
|
350
|
+
return timer.id;
|
|
351
|
+
}
|
|
352
|
+
async get(id) {
|
|
353
|
+
await this.ensureTable();
|
|
354
|
+
const { rows } = await this.client.query(`SELECT data FROM ${this.table} WHERE id = $1`, [id]);
|
|
355
|
+
return rows[0] ? toTimer(rows[0].data) : null;
|
|
356
|
+
}
|
|
357
|
+
async cancel(id) {
|
|
358
|
+
await this.finish(id, 'cancelled');
|
|
359
|
+
}
|
|
360
|
+
/** Extends this instance's live claim on a timer; `false` when it no longer holds one. */
|
|
361
|
+
async renew(id) {
|
|
362
|
+
await this.ensureTable();
|
|
363
|
+
const { rows } = await this.client.query(`UPDATE ${this.table}
|
|
364
|
+
SET claimed_until = now() + $3::double precision * interval '1 millisecond'
|
|
365
|
+
WHERE id = $1 AND claimed_by = $2 AND status = 'pending' AND claimed_until > now()
|
|
366
|
+
RETURNING id`, [id, this.owner, this.claimTtl]);
|
|
367
|
+
return rows.length > 0;
|
|
368
|
+
}
|
|
369
|
+
/** Clears this instance's claim on a timer so any worker can take it now. */
|
|
370
|
+
async release(id) {
|
|
371
|
+
await this.ensureTable();
|
|
372
|
+
await this.client.query(`UPDATE ${this.table} SET claimed_until = NULL, claimed_by = NULL
|
|
373
|
+
WHERE id = $1 AND claimed_by = $2 AND status = 'pending'`, [id, this.owner]);
|
|
374
|
+
}
|
|
375
|
+
async getByWorkflow(workflowId) {
|
|
376
|
+
return this.select('workflow_id = $1', [workflowId]);
|
|
377
|
+
}
|
|
378
|
+
async getByRun(runId) {
|
|
379
|
+
return this.select('run_id = $1', [runId]);
|
|
380
|
+
}
|
|
381
|
+
async getPending() {
|
|
382
|
+
return this.select(`status = 'pending'`, []);
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Overdue pending timers, oldest first, each claimed for `claimTtl` ms:
|
|
386
|
+
* timers claimed by another caller are left out until their lease expires.
|
|
387
|
+
*/
|
|
388
|
+
async getOverdue() {
|
|
389
|
+
await this.ensureTable();
|
|
390
|
+
const { rows } = await this.client.query(`UPDATE ${this.table}
|
|
391
|
+
SET claimed_until = now() + $2::double precision * interval '1 millisecond',
|
|
392
|
+
claimed_by = $3
|
|
393
|
+
WHERE id IN (
|
|
394
|
+
SELECT id FROM ${this.table}
|
|
395
|
+
WHERE status = 'pending' AND fires_at <= $1::double precision
|
|
396
|
+
AND (claimed_until IS NULL OR claimed_until <= now())
|
|
397
|
+
ORDER BY fires_at
|
|
398
|
+
FOR UPDATE SKIP LOCKED
|
|
399
|
+
)
|
|
400
|
+
RETURNING data`, [Date.now(), this.claimTtl, this.owner]);
|
|
401
|
+
return rows.map((row) => toTimer(row.data)).sort(byFiresAt);
|
|
402
|
+
}
|
|
403
|
+
async markFired(id) {
|
|
404
|
+
const fired = await this.finish(id, 'fired');
|
|
405
|
+
if (fired)
|
|
406
|
+
this.listeners.emit(fired);
|
|
407
|
+
}
|
|
408
|
+
async cleanup(olderThan) {
|
|
409
|
+
await this.ensureTable();
|
|
410
|
+
const { rows } = await this.client.query(`DELETE FROM ${this.table} WHERE status <> 'pending' AND created_at < $1 RETURNING id`, [Date.now() - olderThan]);
|
|
411
|
+
return rows.length;
|
|
412
|
+
}
|
|
413
|
+
onFire(callback) {
|
|
414
|
+
return this.listeners.add(callback);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Patches a timer in one statement (top-level keys, like `Object.assign`;
|
|
418
|
+
* `undefined` removes a key); it keeps its id, and a patch that finishes it
|
|
419
|
+
* ends its claim.
|
|
420
|
+
*/
|
|
421
|
+
async update(id, patch) {
|
|
422
|
+
await this.ensureTable();
|
|
423
|
+
const set = {};
|
|
424
|
+
const removed = [];
|
|
425
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
426
|
+
if (key === 'id')
|
|
427
|
+
continue;
|
|
428
|
+
if (value === undefined)
|
|
429
|
+
removed.push(key);
|
|
430
|
+
else
|
|
431
|
+
set[key] = value;
|
|
432
|
+
}
|
|
433
|
+
const next = `((data || $2::jsonb) - $3::text[])`;
|
|
434
|
+
await this.client.query(`UPDATE ${this.table}
|
|
435
|
+
SET data = ${next},
|
|
436
|
+
workflow_id = COALESCE(${next}->>'workflowId', workflow_id),
|
|
437
|
+
run_id = COALESCE(${next}->>'runId', run_id),
|
|
438
|
+
fires_at = COALESCE((${next}->>'firesAt')::double precision, fires_at),
|
|
439
|
+
created_at = COALESCE((${next}->>'createdAt')::double precision, created_at),
|
|
440
|
+
status = ${statusOf(next)},
|
|
441
|
+
claimed_until = CASE WHEN ${statusOf(next)} = 'pending' THEN claimed_until END,
|
|
442
|
+
claimed_by = CASE WHEN ${statusOf(next)} = 'pending' THEN claimed_by END
|
|
443
|
+
WHERE id = $1`, [id, JSON.stringify(set), removed]);
|
|
444
|
+
}
|
|
445
|
+
async list(filter) {
|
|
446
|
+
const conditions = [];
|
|
447
|
+
const values = [];
|
|
448
|
+
if (filter?.enabled !== undefined) {
|
|
449
|
+
values.push(filter.enabled);
|
|
450
|
+
conditions.push(`COALESCE((data->>'enabled')::boolean, true) = $${values.length}`);
|
|
451
|
+
}
|
|
452
|
+
if (filter?.type) {
|
|
453
|
+
values.push(filter.type);
|
|
454
|
+
conditions.push(`data->>'type' = $${values.length}`);
|
|
455
|
+
}
|
|
456
|
+
return this.select(conditions.join(' AND ') || 'TRUE', values);
|
|
457
|
+
}
|
|
458
|
+
async finish(id, status) {
|
|
459
|
+
await this.ensureTable();
|
|
460
|
+
const { rows } = await this.client.query(`UPDATE ${this.table}
|
|
461
|
+
SET status = $2::text, claimed_until = NULL, claimed_by = NULL,
|
|
462
|
+
data = jsonb_set(data, ARRAY[$2::text], 'true')
|
|
463
|
+
WHERE id = $1 AND status = 'pending'
|
|
464
|
+
RETURNING data`, [id, status]);
|
|
465
|
+
return rows[0] ? toTimer(rows[0].data) : null;
|
|
466
|
+
}
|
|
467
|
+
async select(where, values) {
|
|
468
|
+
await this.ensureTable();
|
|
469
|
+
const { rows } = await this.client.query(`SELECT data FROM ${this.table} WHERE ${where} ORDER BY fires_at, created_at`, values);
|
|
470
|
+
return rows.map((row) => toTimer(row.data));
|
|
471
|
+
}
|
|
472
|
+
ensureTable() {
|
|
473
|
+
this.ready ??= this.createTable().catch((error) => {
|
|
474
|
+
this.ready = undefined;
|
|
475
|
+
throw error;
|
|
476
|
+
});
|
|
477
|
+
return this.ready;
|
|
478
|
+
}
|
|
479
|
+
async createTable() {
|
|
480
|
+
const base = this.table.replace('.', '_');
|
|
481
|
+
await createIfMissing(this.client, `CREATE TABLE IF NOT EXISTS ${this.table} (
|
|
482
|
+
id TEXT PRIMARY KEY,
|
|
483
|
+
workflow_id TEXT NOT NULL,
|
|
484
|
+
run_id TEXT NOT NULL,
|
|
485
|
+
status TEXT NOT NULL,
|
|
486
|
+
fires_at DOUBLE PRECISION NOT NULL,
|
|
487
|
+
created_at DOUBLE PRECISION NOT NULL,
|
|
488
|
+
claimed_until TIMESTAMPTZ,
|
|
489
|
+
claimed_by TEXT,
|
|
490
|
+
data JSONB NOT NULL
|
|
491
|
+
)`);
|
|
492
|
+
await createIfMissing(this.client, `ALTER TABLE ${this.table} ADD COLUMN IF NOT EXISTS claimed_by TEXT`);
|
|
493
|
+
await createIfMissing(this.client, `CREATE INDEX IF NOT EXISTS ${base}_due_idx ON ${this.table} (status, fires_at)`);
|
|
494
|
+
await createIfMissing(this.client, `CREATE INDEX IF NOT EXISTS ${base}_workflow_idx ON ${this.table} (workflow_id, fires_at)`);
|
|
495
|
+
await createIfMissing(this.client, `CREATE INDEX IF NOT EXISTS ${base}_run_idx ON ${this.table} (run_id, fires_at)`);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
function toTimer(data) {
|
|
499
|
+
return fromJson(data);
|
|
500
|
+
}
|
|
501
|
+
//# sourceMappingURL=durable-timer-stores.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-timer-stores.js","sourceRoot":"","sources":["../../src/timers/durable-timer-stores.ts"],"names":[],"mappings":"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"}
|
|
@@ -69,6 +69,13 @@ export interface TimerManagerConfig {
|
|
|
69
69
|
* Called when a timer is dead-lettered after exceeding maxRetries
|
|
70
70
|
*/
|
|
71
71
|
onDeadLetter?: (entry: TimerEntry, error: Error) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Called when the store says this manager no longer holds the claim on a
|
|
74
|
+
* timer: before its handler starts (the handler is then skipped) or while
|
|
75
|
+
* it runs (its lease ran out before a renewal got through, so another
|
|
76
|
+
* worker may run the same timer)
|
|
77
|
+
*/
|
|
78
|
+
onClaimLost?: (entry: TimerEntry) => void;
|
|
72
79
|
}
|
|
73
80
|
/**
|
|
74
81
|
* Timer manager stats
|
|
@@ -127,9 +134,29 @@ export declare class TimerManager {
|
|
|
127
134
|
*/
|
|
128
135
|
private processOverdueTimers;
|
|
129
136
|
/**
|
|
130
|
-
* Process a single timer
|
|
137
|
+
* Process a single timer. With a store that claims timers, the claim is
|
|
138
|
+
* renewed right before the handler starts (a timer whose claim ran out
|
|
139
|
+
* while it waited in the batch is left to the worker that took it) and
|
|
140
|
+
* every `claimTtl / 3` while the handler runs, and released when no
|
|
141
|
+
* handler is registered, so another worker can take the timer at once. A
|
|
142
|
+
* failed handler keeps the claim until its lease runs out, which spaces out
|
|
143
|
+
* the retries.
|
|
131
144
|
*/
|
|
132
145
|
private processTimer;
|
|
146
|
+
/**
|
|
147
|
+
* Renews the store's claim on a timer before its handler runs; `false`
|
|
148
|
+
* when the claim is gone or could not be renewed
|
|
149
|
+
*/
|
|
150
|
+
private confirmClaim;
|
|
151
|
+
/**
|
|
152
|
+
* Renews the store's claim on a timer every `claimTtl / 3` until the
|
|
153
|
+
* returned function is called; it resolves once no renewal is in flight.
|
|
154
|
+
*/
|
|
155
|
+
private keepClaim;
|
|
156
|
+
/**
|
|
157
|
+
* Gives up the store's claim on a timer this manager will not run now
|
|
158
|
+
*/
|
|
159
|
+
private releaseClaim;
|
|
133
160
|
/**
|
|
134
161
|
* Run cleanup
|
|
135
162
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timer-manager.d.ts","sourceRoot":"","sources":["../../src/timers/timer-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAErD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAE7D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"timer-manager.d.ts","sourceRoot":"","sources":["../../src/timers/timer-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAErD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAE7D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEzD;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CAC3C;AAeD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,MAAM,CACmC;IACjD,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,cAAc,CAAC,CAAe;IACtC,OAAO,CAAC,SAAS,CAAC,CAAiC;IACnD,OAAO,CAAC,YAAY,CAAC,CAAiC;IACtD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAC,CAAS;gBAEnB,KAAK,EAAE,UAAU,EAAE,MAAM,GAAE,kBAAuB;IAkB9D;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,IAAI;IAKtE;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAI9C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B;;OAEG;YACW,IAAI;IAsBlB;;OAEG;YACW,oBAAoB;IAalC;;;;;;;;OAQG;YACW,YAAY;IAyC1B;;;OAGG;YACW,YAAY;IAY1B;;;OAGG;IACH,OAAO,CAAC,SAAS;IA4BjB;;OAEG;YACW,YAAY;IAQ1B;;OAEG;YACW,OAAO;IAMrB;;OAEG;IACG,QAAQ,CACZ,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC,GAClE,OAAO,CAAC,MAAM,CAAC;IAIlB;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc/C;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAczD;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI3D;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAI/C;;OAEG;IACG,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIlE;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIxD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAe5C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAYnC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAMnC;;OAEG;IACH,SAAS,IAAI,OAAO;CAGrB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,kBAAkB,GAAG,YAAY,CAE/F;AAED;;GAEG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,SAAS,CASb;gBAEQ,OAAO,EAAE,YAAY;IAIjC;;OAEG;IACG,iBAAiB,CACrB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,GACA,OAAO,CAAC,IAAI,CAAC;IAwBhB;;OAEG;IACG,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhD;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiBrE;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIjC;;OAEG;IACH,eAAe,IAAI,MAAM,EAAE;CAG5B;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,YAAY,GAAG,uBAAuB,CAEvF"}
|