effect-mq 0.4.2 → 0.6.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 +85 -17
- package/dist/Flow.d.ts +381 -0
- package/dist/Flow.d.ts.map +1 -0
- package/dist/Flow.js +340 -0
- package/dist/Flow.js.map +1 -0
- package/dist/Job.d.ts +37 -6
- package/dist/Job.d.ts.map +1 -1
- package/dist/Job.js +17 -2
- package/dist/Job.js.map +1 -1
- package/dist/JobSchedules.d.ts +112 -0
- package/dist/JobSchedules.d.ts.map +1 -0
- package/dist/JobSchedules.js +106 -0
- package/dist/JobSchedules.js.map +1 -0
- package/dist/JobStore.d.ts +320 -10
- package/dist/JobStore.d.ts.map +1 -1
- package/dist/JobStore.js.map +1 -1
- package/dist/MemoryJobStore.d.ts.map +1 -1
- package/dist/MemoryJobStore.js +336 -8
- package/dist/MemoryJobStore.js.map +1 -1
- package/dist/Metrics.d.ts +31 -0
- package/dist/Metrics.d.ts.map +1 -1
- package/dist/Metrics.js +39 -0
- package/dist/Metrics.js.map +1 -1
- package/dist/Worker.d.ts +120 -11
- package/dist/Worker.d.ts.map +1 -1
- package/dist/Worker.js +452 -26
- package/dist/Worker.js.map +1 -1
- package/dist/drizzle-postgres/DrizzleJobStore.d.ts +19 -1
- package/dist/drizzle-postgres/DrizzleJobStore.d.ts.map +1 -1
- package/dist/drizzle-postgres/DrizzleJobStore.js +662 -81
- package/dist/drizzle-postgres/DrizzleJobStore.js.map +1 -1
- package/dist/drizzle-postgres/schema.d.ts +310 -3
- package/dist/drizzle-postgres/schema.d.ts.map +1 -1
- package/dist/drizzle-postgres/schema.js +68 -1
- package/dist/drizzle-postgres/schema.js.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/redis/RedisJobStore.d.ts.map +1 -1
- package/dist/redis/RedisJobStore.js +221 -19
- package/dist/redis/RedisJobStore.js.map +1 -1
- package/dist/redis/scripts.d.ts +118 -11
- package/dist/redis/scripts.d.ts.map +1 -1
- package/dist/redis/scripts.js +497 -28
- package/dist/redis/scripts.js.map +1 -1
- package/dist/testing/conformance.d.ts +6 -0
- package/dist/testing/conformance.d.ts.map +1 -1
- package/dist/testing/conformance.js +765 -1
- package/dist/testing/conformance.js.map +1 -1
- package/package.json +1 -1
- package/src/Flow.ts +778 -0
- package/src/Job.ts +42 -11
- package/src/JobSchedules.ts +223 -0
- package/src/JobStore.ts +347 -9
- package/src/MemoryJobStore.ts +372 -8
- package/src/Metrics.ts +43 -0
- package/src/Worker.ts +726 -37
- package/src/drizzle-postgres/DrizzleJobStore.ts +827 -82
- package/src/drizzle-postgres/schema.ts +94 -0
- package/src/index.ts +16 -0
- package/src/redis/RedisJobStore.ts +291 -8
- package/src/redis/scripts.ts +529 -26
- package/src/testing/conformance.ts +989 -1
package/dist/redis/scripts.d.ts
CHANGED
|
@@ -28,18 +28,36 @@
|
|
|
28
28
|
* - `p:schedules` / `p:schedule:<key>` ZSET by nextRunAt + HASH per record
|
|
29
29
|
* - `p:dedupe:<name>\0<key>` HASH {jobId, expiresAt} + `p:dedupes` index
|
|
30
30
|
* ZSET (score = window expiry, +inf = pending)
|
|
31
|
+
* - `p:flowchild:<flowId>\0<childKey>` HASH of one flow dependency row
|
|
32
|
+
* - `p:flowchildren:<flowId>` ZSET (score 0, member = childKey; ZRANGEBYLEX
|
|
33
|
+
* gives child-key order + cursor pagination)
|
|
34
|
+
* - `p:flowpending` ZSET, member `<flowId>\0<childKey>`, score =
|
|
35
|
+
* sweep-eligibility timestamp (pendingSince at
|
|
36
|
+
* staging, re-armed on sweep return)
|
|
37
|
+
* - `p:flowcascade` ZSET, score 0, member `<flowId>\0<childKey>`
|
|
38
|
+
* (cancels still owed to child stores)
|
|
39
|
+
* - `p:flowoutbox` ZSET, score = seq from `p:flowoutbox:seq`,
|
|
40
|
+
* member `<seq>\0<report json>` — undelivered
|
|
41
|
+
* child-result reports (see OutboxEntry). The
|
|
42
|
+
* seq prefix makes every member id a peek
|
|
43
|
+
* cursor that survives deletions (see
|
|
44
|
+
* peekOutbox in RedisJobStore)
|
|
45
|
+
*
|
|
46
|
+
* `waiting-children` parents live only in the job hash, `p:all`, and
|
|
47
|
+
* `p:counts` — never in a pending zset, so `claim` can never return them.
|
|
31
48
|
*
|
|
32
49
|
* @since 0.2.0
|
|
33
50
|
*/
|
|
34
51
|
import { Redis } from "effect/unstable/persistence";
|
|
35
52
|
/**
|
|
36
53
|
* enqueue(prefix, idMode, id, name, queue, payloadJson, metadataJson,
|
|
37
|
-
* priority, attemptsMax, backoffJson, keepJson, timeoutMs, delayMs,
|
|
54
|
+
* priority, attemptsMax, backoffJson, keepJson, timeoutMs, delayMs,
|
|
55
|
+
* now, dedupe..., traceJson, parentJson)
|
|
38
56
|
* idMode: "user" (dedup no-op), "generated" (collision -> retry sentinel),
|
|
39
57
|
* "auto" (j-<seq>, in-script collision loop).
|
|
40
58
|
*/
|
|
41
59
|
export declare const enqueue: Redis.Script<{
|
|
42
|
-
params: [prefix: string, idMode: string, id: string, name: string, queue: string, payloadJson: string, metadataJson: string, priority: number, attemptsMax: number, backoffJson: string, keepJson: string, timeoutMs: string, delayMs: number, now: number, dedupeKey: string, dedupeTtlMs: string, dedupeExtend: string, dedupeReplace: string, traceJson: string];
|
|
60
|
+
params: [prefix: string, idMode: string, id: string, name: string, queue: string, payloadJson: string, metadataJson: string, priority: number, attemptsMax: number, backoffJson: string, keepJson: string, timeoutMs: string, delayMs: number, now: number, dedupeKey: string, dedupeTtlMs: string, dedupeExtend: string, dedupeReplace: string, traceJson: string, parentJson: string];
|
|
43
61
|
result: string;
|
|
44
62
|
}>;
|
|
45
63
|
/**
|
|
@@ -103,7 +121,7 @@ export declare const counts: Redis.Script<{
|
|
|
103
121
|
params: [prefix: string];
|
|
104
122
|
result: string;
|
|
105
123
|
}>;
|
|
106
|
-
/** remove(prefix, id) -> removed boolean (active
|
|
124
|
+
/** remove(prefix, id) -> removed boolean (active/waiting-children refused). */
|
|
107
125
|
export declare const remove: Redis.Script<{
|
|
108
126
|
params: [prefix: string, id: string];
|
|
109
127
|
result: string;
|
|
@@ -114,8 +132,10 @@ export declare const retry: Redis.Script<{
|
|
|
114
132
|
result: string;
|
|
115
133
|
}>;
|
|
116
134
|
/**
|
|
117
|
-
* cancel(prefix, id, now) — waiting/delayed become terminal
|
|
118
|
-
*
|
|
135
|
+
* cancel(prefix, id, now) — waiting/delayed/waiting-children become terminal
|
|
136
|
+
* (a parked flow parent also flips its remaining pending rows to cancelled,
|
|
137
|
+
* handing them to the cascade sweep); active gets the cancel-request flag;
|
|
138
|
+
* terminal states are refused.
|
|
119
139
|
*/
|
|
120
140
|
export declare const cancel: Redis.Script<{
|
|
121
141
|
params: [prefix: string, id: string, now: number];
|
|
@@ -136,7 +156,7 @@ export declare const promote: Redis.Script<{
|
|
|
136
156
|
* preserves the stored nextRunAt.
|
|
137
157
|
*/
|
|
138
158
|
export declare const upsertSchedule: Redis.Script<{
|
|
139
|
-
params: [prefix: string, key: string, jobName: string, queue: string, cron: string, tz: string, everyMs: string, payloadJson: string, metadataJson: string, priority: string, attemptsMax: string, backoffJson: string, keepJson: string, timeoutMs: string, nextRunAt: number];
|
|
159
|
+
params: [prefix: string, key: string, jobName: string, queue: string, cron: string, tz: string, everyMs: string, payloadJson: string, metadataJson: string, priority: string, attemptsMax: string, backoffJson: string, keepJson: string, timeoutMs: string, group: string, nextRunAt: number];
|
|
140
160
|
result: string;
|
|
141
161
|
}>;
|
|
142
162
|
/** removeSchedule(prefix, key) -> existed boolean. */
|
|
@@ -162,21 +182,21 @@ export declare const advanceSchedule: Redis.Script<{
|
|
|
162
182
|
/**
|
|
163
183
|
* tickSchedule(prefix, key, expectedRunAt, nextRunAt, id, name, queue,
|
|
164
184
|
* payloadJson, metadataJson, priority, attemptsMax, backoffJson, keepJson,
|
|
165
|
-
* timeoutMs, traceJson, delayMs, now) -> "1" fired | "0"
|
|
185
|
+
* timeoutMs, traceJson, parentJson, delayMs, now) -> "1" fired | "0"
|
|
166
186
|
* Atomic occurrence claim: the nextRunAt CAS and the tick job's insert run
|
|
167
187
|
* in one script, so a stale sweeper can never re-fire a slot — even after
|
|
168
188
|
* retention pruned the previous slot's job row.
|
|
169
189
|
*/
|
|
170
190
|
export declare const tickSchedule: Redis.Script<{
|
|
171
|
-
params: [prefix: string, key: string, expectedRunAt: number, nextRunAt: number, id: string, name: string, queue: string, payloadJson: string, metadataJson: string, priority: number, attemptsMax: number, backoffJson: string, keepJson: string, timeoutMs: string, traceJson: string, delayMs: number, now: number];
|
|
191
|
+
params: [prefix: string, key: string, expectedRunAt: number, nextRunAt: number, id: string, name: string, queue: string, payloadJson: string, metadataJson: string, priority: number, attemptsMax: number, backoffJson: string, keepJson: string, timeoutMs: string, traceJson: string, parentJson: string, delayMs: number, now: number];
|
|
172
192
|
result: string;
|
|
173
193
|
}>;
|
|
174
194
|
/**
|
|
175
195
|
* enqueueMany(prefix, now, count, ...items) -> JSON array of per-item results
|
|
176
|
-
* ({id, duplicate} | {collision} | {error}). Items are
|
|
196
|
+
* ({id, duplicate} | {collision} | {error}). Items are 14-ARGV strides:
|
|
177
197
|
* idMode, id, name, queue, payloadJson, metadataJson, priority, attemptsMax,
|
|
178
|
-
* backoffJson, keepJson, timeoutMs, traceJson, delayMs. Plain
|
|
179
|
-
* items only — the caller routes dedup items through \`enqueue\`.
|
|
198
|
+
* backoffJson, keepJson, timeoutMs, traceJson, parentJson, delayMs. Plain
|
|
199
|
+
* (non-dedup) items only — the caller routes dedup items through \`enqueue\`.
|
|
180
200
|
*/
|
|
181
201
|
export declare const enqueueMany: Redis.Script<{
|
|
182
202
|
params: [prefix: string, now: number, count: number, items: readonly string[]];
|
|
@@ -201,4 +221,91 @@ export declare const sweepDedupes: Redis.Script<{
|
|
|
201
221
|
params: [prefix: string, limit: number, now: number];
|
|
202
222
|
result: string;
|
|
203
223
|
}>;
|
|
224
|
+
/**
|
|
225
|
+
* fanOut(prefix, id, token, final, clearStaged, failFast, total, now, count,
|
|
226
|
+
* ...items) — the FanOut ack, chunked like enqueueMany. Items are 5-ARGV
|
|
227
|
+
* strides: childKey, storeKey, childJobId, name, specJson.
|
|
228
|
+
*
|
|
229
|
+
* Every chunk is lock-token-guarded. Non-final chunks ONLY stage dependency
|
|
230
|
+
* rows; the final chunk stages its rows, appends the "fanned-out" ledger
|
|
231
|
+
* entry (no attempt consumed), persists the manifest (flowFailFast,
|
|
232
|
+
* flowPending = total, zeroed outcome counters), and transitions the parent:
|
|
233
|
+
* pending > 0 parks it in
|
|
234
|
+
* waiting-children (no pending zset — never claimable), pending == 0 settles
|
|
235
|
+
* it straight to runnable collect. A parent whose manifest already landed
|
|
236
|
+
* keeps it untouched (rows are not re-created; the transition follows the
|
|
237
|
+
* persisted pending count), so a double fan-out cannot duplicate children.
|
|
238
|
+
* When staging starts with no manifest, the FIRST chunk clears previously
|
|
239
|
+
* staged rows — a crashed earlier attempt may have staged different keys. A
|
|
240
|
+
* raced cancelRequested wins: the parent settles cancelled and its pending
|
|
241
|
+
* rows flip to cancelled (cascade work for the flow sweeper).
|
|
242
|
+
*/
|
|
243
|
+
export declare const fanOut: Redis.Script<{
|
|
244
|
+
params: [prefix: string, id: string, token: string, final: string, clearStaged: string, failFast: string, total: number, now: number, count: number, items: readonly string[]];
|
|
245
|
+
result: string;
|
|
246
|
+
}>;
|
|
247
|
+
/**
|
|
248
|
+
* recordChildResults(prefix, now, count, ...items) -> {results, wakes}.
|
|
249
|
+
* Items are 5-ARGV strides: flowId, childKey, outcome, exitJson,
|
|
250
|
+
* failedReason; results are positional {applied, parentSettled}; wakes names
|
|
251
|
+
* the queues of parents that resumed runnable. One atomic batch; reports may
|
|
252
|
+
* span flows.
|
|
253
|
+
*
|
|
254
|
+
* Phase 1 applies EVERY row update — idempotent, only while the row is
|
|
255
|
+
* still pending; an applied report moves the child from the parent's `pending`
|
|
256
|
+
* counter to its outcome counter and marks the row cascaded (the outcome
|
|
257
|
+
* came FROM the child's store). Phase 2 settles each touched flow at most
|
|
258
|
+
* once: the FIRST applied failed report in batch order under fail-fast
|
|
259
|
+
* (terminal store-side failure; remaining rows flip to cancelled; wins the
|
|
260
|
+
* tie over pending==0 — and this settle IS a nested parent's terminal
|
|
261
|
+
* transition, so its own report goes to the outbox here), else pending==0
|
|
262
|
+
* resumes the parent runnable at the flow's LAST applied report's index.
|
|
263
|
+
*/
|
|
264
|
+
export declare const recordChildResults: Redis.Script<{
|
|
265
|
+
params: [prefix: string, now: number, count: number, items: readonly string[]];
|
|
266
|
+
result: string;
|
|
267
|
+
}>;
|
|
268
|
+
/**
|
|
269
|
+
* listChildResults(prefix, flowId, cursor, limit) — child-key order via
|
|
270
|
+
* ZRANGEBYLEX over the per-flow index; cursor = last childKey (exclusive).
|
|
271
|
+
* Items are positional HMGET tuples (the field list must stay in lockstep
|
|
272
|
+
* with the driver's `toChildRecord`) — the full spec JSON stays server-side.
|
|
273
|
+
*/
|
|
274
|
+
export declare const listChildResults: Redis.Script<{
|
|
275
|
+
params: [prefix: string, flowId: string, cursor: string, limit: number];
|
|
276
|
+
result: string;
|
|
277
|
+
}>;
|
|
278
|
+
/**
|
|
279
|
+
* flowSweepWork(prefix, pendingAgeMs, limit, now) -> {reconcile, cascade}
|
|
280
|
+
* grouped by flowId. Reconcile scans the flowpending zset (score = the row's
|
|
281
|
+
* sweep-eligibility timestamp) and yields rows whose parent is still parked
|
|
282
|
+
* in waiting-children. Every scanned member is re-armed or purged so no
|
|
283
|
+
* member can pin the head of the page:
|
|
284
|
+
*
|
|
285
|
+
* - parent missing, or terminal with NO manifest: a crashed fan-out's
|
|
286
|
+
* staged orphan — purge the row, its index member, and the flowpending
|
|
287
|
+
* member (left alone their old scores would head-pin every page forever);
|
|
288
|
+
* - parent alive but not waiting-children (mid-staging): re-arm to now so
|
|
289
|
+
* it rotates behind fresher work;
|
|
290
|
+
* - returned rows: re-arm to now (defer-on-return, per the contract) so a
|
|
291
|
+
* full page rotates across sweeps;
|
|
292
|
+
* - a non-pending row's membership is stale (rows never return to pending):
|
|
293
|
+
* self-heal by removing the member.
|
|
294
|
+
*
|
|
295
|
+
* Cascade lists flowcascade members (cancels still owed to child stores).
|
|
296
|
+
* Spec JSON strings pass through untouched — the script never cjson-decodes
|
|
297
|
+
* stored payloads (precision, lone surrogates).
|
|
298
|
+
*/
|
|
299
|
+
export declare const flowSweepWork: Redis.Script<{
|
|
300
|
+
params: [prefix: string, pendingAgeMs: number, limit: number, now: number];
|
|
301
|
+
result: string;
|
|
302
|
+
}>;
|
|
303
|
+
/**
|
|
304
|
+
* markChildrenCascaded(prefix, flowId, childKeysJson) — idempotent; unknown
|
|
305
|
+
* keys are ignored (their index members are still cleared).
|
|
306
|
+
*/
|
|
307
|
+
export declare const markChildrenCascaded: Redis.Script<{
|
|
308
|
+
params: [prefix: string, flowId: string, childKeysJson: string];
|
|
309
|
+
result: string;
|
|
310
|
+
}>;
|
|
204
311
|
//# sourceMappingURL=scripts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/redis/scripts.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/redis/scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AAkPnD;;;;;;GAMG;AACH,eAAO,MAAM,OAAO;;;EAkIM,CAAA;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;EAsEQ,CAAA;AAE1B;;;;GAIG;AACH,eAAO,MAAM,GAAG;;;EA0EU,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,OAAO;;;EA4BM,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,WAAW;;;EAuBE,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,cAAc;;;EAiDD,CAAA;AAE1B,sEAAsE;AACtE,eAAO,MAAM,MAAM;;;EAUO,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,IAAI;;;EAsES,CAAA;AAE1B,mDAAmD;AACnD,eAAO,MAAM,MAAM;;;EAUO,CAAA;AAE1B,+EAA+E;AAC/E,eAAO,MAAM,MAAM;;;EAeO,CAAA;AAE1B,sEAAsE;AACtE,eAAO,MAAM,KAAK;;;EA2BQ,CAAA;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,MAAM;;;EAqCO,CAAA;AAE1B,yDAAyD;AACzD,eAAO,MAAM,OAAO;;;EAqBM,CAAA;AAE1B;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;;EA8DD,CAAA;AAE1B,sDAAsD;AACtD,eAAO,MAAM,cAAc;;;EAUD,CAAA;AAE1B,yEAAyE;AACzE,eAAO,MAAM,aAAa;;;EAsBA,CAAA;AAE1B,gEAAgE;AAChE,eAAO,MAAM,YAAY;;;EAcC,CAAA;AAE1B,gFAAgF;AAChF,eAAO,MAAM,eAAe;;;EAcF,CAAA;AAE1B;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY;;;EA0DC,CAAA;AAE1B;;;;;;GAMG;AACH,eAAO,MAAM,WAAW;;;EA+CE,CAAA;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,UAAU;;;EA4DG,CAAA;AAE1B;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;EAyCC,CAAA;AAE1B;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,MAAM;;;EA+FO,CAAA;AAE1B;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,kBAAkB;;;EAmGL,CAAA;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB;;;EAkBH,CAAA;AAE1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa;;;EA0EA,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;EAgBP,CAAA"}
|