effect-mq 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.
Files changed (62) hide show
  1. package/README.md +167 -22
  2. package/dist/Job.d.ts +67 -4
  3. package/dist/Job.d.ts.map +1 -1
  4. package/dist/Job.js +76 -3
  5. package/dist/Job.js.map +1 -1
  6. package/dist/JobStore.d.ts +174 -3
  7. package/dist/JobStore.d.ts.map +1 -1
  8. package/dist/JobStore.js +89 -1
  9. package/dist/JobStore.js.map +1 -1
  10. package/dist/MemoryJobStore.d.ts +37 -6
  11. package/dist/MemoryJobStore.d.ts.map +1 -1
  12. package/dist/MemoryJobStore.js +201 -25
  13. package/dist/MemoryJobStore.js.map +1 -1
  14. package/dist/Worker.d.ts +5 -1
  15. package/dist/Worker.d.ts.map +1 -1
  16. package/dist/Worker.js +116 -10
  17. package/dist/Worker.js.map +1 -1
  18. package/dist/{drizzle → drizzle-postgres}/DrizzleJobStore.d.ts +18 -2
  19. package/dist/drizzle-postgres/DrizzleJobStore.d.ts.map +1 -0
  20. package/dist/{drizzle → drizzle-postgres}/DrizzleJobStore.js +287 -40
  21. package/dist/drizzle-postgres/DrizzleJobStore.js.map +1 -0
  22. package/dist/drizzle-postgres/index.d.ts.map +1 -0
  23. package/dist/drizzle-postgres/index.js.map +1 -0
  24. package/dist/{drizzle → drizzle-postgres}/schema.d.ts +306 -4
  25. package/dist/drizzle-postgres/schema.d.ts.map +1 -0
  26. package/dist/{drizzle → drizzle-postgres}/schema.js +36 -2
  27. package/dist/drizzle-postgres/schema.js.map +1 -0
  28. package/dist/redis/RedisJobStore.d.ts +56 -0
  29. package/dist/redis/RedisJobStore.d.ts.map +1 -0
  30. package/dist/redis/RedisJobStore.js +385 -0
  31. package/dist/redis/RedisJobStore.js.map +1 -0
  32. package/dist/redis/index.d.ts +9 -0
  33. package/dist/redis/index.d.ts.map +1 -0
  34. package/dist/redis/index.js +9 -0
  35. package/dist/redis/index.js.map +1 -0
  36. package/dist/redis/scripts.d.ts +168 -0
  37. package/dist/redis/scripts.d.ts.map +1 -0
  38. package/dist/redis/scripts.js +755 -0
  39. package/dist/redis/scripts.js.map +1 -0
  40. package/dist/testing/conformance.d.ts.map +1 -1
  41. package/dist/testing/conformance.js +332 -3
  42. package/dist/testing/conformance.js.map +1 -1
  43. package/package.json +8 -4
  44. package/src/Job.ts +189 -5
  45. package/src/JobStore.ts +252 -4
  46. package/src/MemoryJobStore.ts +273 -26
  47. package/src/Worker.ts +152 -10
  48. package/src/{drizzle → drizzle-postgres}/DrizzleJobStore.ts +412 -40
  49. package/src/{drizzle → drizzle-postgres}/schema.ts +52 -3
  50. package/src/redis/RedisJobStore.ts +597 -0
  51. package/src/redis/index.ts +8 -0
  52. package/src/redis/scripts.ts +862 -0
  53. package/src/testing/conformance.ts +421 -3
  54. package/dist/drizzle/DrizzleJobStore.d.ts.map +0 -1
  55. package/dist/drizzle/DrizzleJobStore.js.map +0 -1
  56. package/dist/drizzle/index.d.ts.map +0 -1
  57. package/dist/drizzle/index.js.map +0 -1
  58. package/dist/drizzle/schema.d.ts.map +0 -1
  59. package/dist/drizzle/schema.js.map +0 -1
  60. /package/dist/{drizzle → drizzle-postgres}/index.d.ts +0 -0
  61. /package/dist/{drizzle → drizzle-postgres}/index.js +0 -0
  62. /package/src/{drizzle → drizzle-postgres}/index.ts +0 -0
@@ -0,0 +1,385 @@
1
+ /**
2
+ * A Redis-backed `JobStore` built on `effect/unstable/persistence`'s `Redis`
3
+ * service. Every mutation is a single Lua script (see `scripts.ts`), so all
4
+ * `JobStore` operations are atomic on the server and safe across processes.
5
+ *
6
+ * Provide the `Redis` service from your platform package — `NodeRedis.layer`
7
+ * (`@effect/platform-node`, node-redis), `BunRedis.layer`
8
+ * (`@effect/platform-bun`, `Bun.redis`) — or `Redis.make` over any client.
9
+ *
10
+ * Wake-ups ride the client's pub/sub channel, so workers in other processes
11
+ * pick jobs up promptly; the worker's `pollInterval` is the fallback.
12
+ *
13
+ * @since 0.2.0
14
+ */
15
+ import { Clock, Deferred, Duration, Effect, Exit, Layer, Option, Queue, Schedule } from "effect";
16
+ import { Redis } from "effect/unstable/persistence";
17
+ import * as JobStore from "../JobStore.js";
18
+ import * as scripts from "./scripts.js";
19
+ const storeError = (message) => (cause) => new JobStore.JobStoreError({ message, cause });
20
+ /** Fold a Lua `HGETALL` reply (flat `[field, value, ...]`) into a map. */
21
+ const foldPairs = (flat) => {
22
+ const out = new Map();
23
+ for (let i = 0; i + 1 < flat.length; i += 2) {
24
+ const field = flat[i];
25
+ const value = flat[i + 1];
26
+ if (field !== undefined && value !== undefined) {
27
+ out.set(field, value);
28
+ }
29
+ }
30
+ return out;
31
+ };
32
+ // Hash fields use "" for absent optional values.
33
+ const optionalString = (value) => value === undefined || value === "" ? undefined : value;
34
+ const optionalNumber = (value) => value === undefined || value === "" ? undefined : Number(value);
35
+ const optionalJson = (value) => {
36
+ if (value === undefined || value === "")
37
+ return undefined;
38
+ // SAFETY: the value round-trips JSON this driver itself wrote for the field.
39
+ return JSON.parse(value);
40
+ };
41
+ const toRecord = (hash) => ({
42
+ id: JobStore.JobId(hash.get("id") ?? ""),
43
+ name: hash.get("name") ?? "",
44
+ queue: JobStore.QueueName(hash.get("queue") ?? ""),
45
+ payload: optionalJson(hash.get("payload")) ?? null,
46
+ metadata: optionalJson(hash.get("metadata")) ?? {},
47
+ // SAFETY: the state field is only ever written with JobState members.
48
+ state: (hash.get("state") ?? "waiting"),
49
+ priority: Number(hash.get("priority") ?? 0),
50
+ attemptsMax: Number(hash.get("attemptsMax") ?? 1),
51
+ attemptsMade: Number(hash.get("attemptsMade") ?? 0),
52
+ stalledCount: Number(hash.get("stalledCount") ?? 0),
53
+ backoff: optionalJson(hash.get("backoff")),
54
+ keep: optionalJson(hash.get("keep")),
55
+ timeoutMs: optionalNumber(hash.get("timeoutMs")),
56
+ cancelRequested: hash.get("cancelRequested") === "1",
57
+ runAt: Number(hash.get("runAt") ?? 0),
58
+ enqueuedAt: Number(hash.get("enqueuedAt") ?? 0),
59
+ processedAt: optionalNumber(hash.get("processedAt")),
60
+ finishedAt: optionalNumber(hash.get("finishedAt")),
61
+ exit: optionalJson(hash.get("exit")),
62
+ failedReason: optionalString(hash.get("failedReason"))
63
+ });
64
+ const toSchedule = (hash) => ({
65
+ key: JobStore.ScheduleKey(hash.get("key") ?? ""),
66
+ jobName: hash.get("jobName") ?? "",
67
+ queue: JobStore.QueueName(hash.get("queue") ?? ""),
68
+ cron: optionalString(hash.get("cron")),
69
+ tz: optionalString(hash.get("tz")),
70
+ everyMs: optionalNumber(hash.get("everyMs")),
71
+ payload: optionalJson(hash.get("payload")),
72
+ metadata: optionalJson(hash.get("metadata")) ?? {},
73
+ priority: Number(hash.get("priority") ?? 0),
74
+ attemptsMax: Number(hash.get("attemptsMax") ?? 1),
75
+ backoff: optionalJson(hash.get("backoff")),
76
+ keep: optionalJson(hash.get("keep")),
77
+ timeoutMs: optionalNumber(hash.get("timeoutMs")),
78
+ nextRunAt: Number(hash.get("nextRunAt") ?? 0)
79
+ });
80
+ // cjson encodes an empty Lua table as {}, not [] — normalize.
81
+ const asArray = (value) => Array.isArray(value) ? value : [];
82
+ const JOB_STATES = [
83
+ "waiting",
84
+ "delayed",
85
+ "active",
86
+ "completed",
87
+ "failed",
88
+ "cancelled"
89
+ ];
90
+ /**
91
+ * Build a `RedisJobStore` service. Needs the `Redis` service and a `Scope`
92
+ * (the wake-up subscription and the optional history sweeper live in it).
93
+ *
94
+ * @since 0.2.0
95
+ */
96
+ export const make = (options) => Effect.gen(function* () {
97
+ const redis = yield* Redis.Redis;
98
+ const prefix = options?.prefix ?? "effect-mq";
99
+ const wakeChannel = `${prefix}:wake`;
100
+ const evalEnqueue = redis.eval(scripts.enqueue);
101
+ const evalClaim = redis.eval(scripts.claim);
102
+ const evalAck = redis.eval(scripts.ack);
103
+ const evalRelease = redis.eval(scripts.release);
104
+ const evalExtendLocks = redis.eval(scripts.extendLocks);
105
+ const evalRecoverStalled = redis.eval(scripts.recoverStalled);
106
+ const evalGetJob = redis.eval(scripts.getJob);
107
+ const evalList = redis.eval(scripts.list);
108
+ const evalCounts = redis.eval(scripts.counts);
109
+ const evalRemove = redis.eval(scripts.remove);
110
+ const evalRetry = redis.eval(scripts.retry);
111
+ const evalCancel = redis.eval(scripts.cancel);
112
+ const evalPromote = redis.eval(scripts.promote);
113
+ const evalUpsertSchedule = redis.eval(scripts.upsertSchedule);
114
+ const evalRemoveSchedule = redis.eval(scripts.removeSchedule);
115
+ const evalListSchedules = redis.eval(scripts.listSchedules);
116
+ const evalDueSchedules = redis.eval(scripts.dueSchedules);
117
+ const evalAdvanceSchedule = redis.eval(scripts.advanceSchedule);
118
+ const evalSweepHistory = redis.eval(scripts.sweepHistory);
119
+ // Wake protocol: a local version + Deferred chain (same-process wake-ups
120
+ // never depend on the pub/sub round trip), with the channel carrying
121
+ // cross-process wake-ups. Same shape as the Postgres driver's NOTIFY.
122
+ let wakeVersion = 0;
123
+ let wake = Deferred.makeUnsafe();
124
+ const signalWakeLocal = () => {
125
+ wakeVersion += 1;
126
+ const current = wake;
127
+ wake = Deferred.makeUnsafe();
128
+ Deferred.doneUnsafe(current, Exit.succeed(void 0));
129
+ };
130
+ const wakeUp = Effect.suspend(() => {
131
+ signalWakeLocal();
132
+ return redis.send("PUBLISH", wakeChannel, "1").pipe(Effect.ignore);
133
+ });
134
+ // Cross-process wake-ups. The pump resubscribes on connection loss (Bun
135
+ // subscribers do not auto-reconnect); the retry delay only ever runs
136
+ // after a real failure, so TestClock runs are unaffected.
137
+ yield* Effect.scoped(Effect.gen(function* () {
138
+ const messages = yield* redis.subscribe(wakeChannel);
139
+ while (true) {
140
+ yield* Queue.take(messages);
141
+ signalWakeLocal();
142
+ }
143
+ })).pipe(Effect.retry(Schedule.spaced("1 second")), Effect.catchCause((cause) => Effect.logWarning("effect-mq: redis wake subscription failed", cause)), Effect.forkScoped);
144
+ if (options?.historyTtl !== undefined) {
145
+ const ttlMs = Duration.toMillis(options.historyTtl);
146
+ const intervalMs = Duration.toMillis(options.historySweepInterval ?? "1 minute");
147
+ yield* Effect.gen(function* () {
148
+ yield* Effect.sleep(intervalMs);
149
+ const now = yield* Clock.currentTimeMillis;
150
+ while ((yield* evalSweepHistory(prefix, now - ttlMs, 500)) !== "0") {
151
+ // bounded batches until the window is clean
152
+ }
153
+ }).pipe(Effect.catchCause((cause) => Effect.logError("effect-mq: redis history sweep failed", cause)), Effect.forever, Effect.forkScoped);
154
+ }
155
+ const generateCandidate = (request, generate) => Effect.suspend(() => {
156
+ const raw = generate(request);
157
+ return Effect.isEffect(raw) ? raw : Effect.succeed(raw);
158
+ });
159
+ const enqueueOnce = (request, idMode, id, now) => evalEnqueue(prefix, idMode, id, request.name, request.queue, JSON.stringify(request.payload ?? null), JSON.stringify(request.metadata), request.priority, request.attemptsMax, request.backoff === undefined ? "" : JSON.stringify(request.backoff), request.keep === undefined ? "" : JSON.stringify(request.keep), request.timeoutMs === undefined ? "" : String(request.timeoutMs), Math.max(0, request.delayMs), now);
160
+ const store = {
161
+ enqueue: (request) => Effect.gen(function* () {
162
+ const now = yield* Clock.currentTimeMillis;
163
+ const generate = options?.idGenerator;
164
+ for (let i = 0; i < 5; i++) {
165
+ const mode = request.id !== undefined
166
+ ? "user"
167
+ : generate !== undefined
168
+ ? "generated"
169
+ : "auto";
170
+ const candidate = mode === "user"
171
+ ? request.id ?? ""
172
+ : mode === "generated" && generate !== undefined
173
+ ? yield* generateCandidate(request, generate)
174
+ : "";
175
+ const reply = JSON.parse(yield* enqueueOnce(request, mode, candidate, now));
176
+ if (reply.collision === true)
177
+ continue;
178
+ if (reply.error !== undefined || reply.id === undefined) {
179
+ return yield* new JobStore.JobStoreError({
180
+ message: "enqueue failed: could not generate a unique job id"
181
+ });
182
+ }
183
+ if (reply.wake === true) {
184
+ yield* wakeUp;
185
+ }
186
+ return { id: JobStore.JobId(reply.id), duplicate: reply.duplicate === true };
187
+ }
188
+ return yield* new JobStore.JobStoreError({
189
+ message: "enqueue failed: could not generate a unique job id"
190
+ });
191
+ }).pipe(Effect.mapError((error) => error instanceof JobStore.JobStoreError ? error : storeError("enqueue failed")(error))),
192
+ claim: (claimOptions) =>
193
+ // Snapshot BEFORE the script runs: a wake that fires while the claim
194
+ // executes must make awaitWake(token) return immediately.
195
+ Effect.suspend(() => {
196
+ const observedWake = wakeVersion;
197
+ return Effect.gen(function* () {
198
+ const now = yield* Clock.currentTimeMillis;
199
+ const reply = JSON.parse(yield* evalClaim(prefix, claimOptions.queue, JSON.stringify(claimOptions.names), claimOptions.token, claimOptions.lockDurationMs, now));
200
+ if (reply.job !== undefined) {
201
+ const claimed = { _tag: "Claimed", job: toRecord(foldPairs(reply.job)) };
202
+ return claimed;
203
+ }
204
+ const empty = {
205
+ _tag: "Empty",
206
+ nextRunAt: reply.nextRunAt,
207
+ wakeToken: observedWake
208
+ };
209
+ return empty;
210
+ });
211
+ }).pipe(Effect.mapError(storeError("claim failed"))),
212
+ ack: (id, token, outcome) => Effect.gen(function* () {
213
+ const now = yield* Clock.currentTimeMillis;
214
+ const exitJson = outcome._tag === "Cancelled" || outcome.exit === undefined
215
+ ? ""
216
+ : JSON.stringify(outcome.exit);
217
+ const delayMs = outcome._tag === "Retry" ? Math.max(0, outcome.delayMs) : 0;
218
+ const reply = JSON.parse(yield* evalAck(prefix, id, token, outcome._tag, exitJson, delayMs, now).pipe(Effect.mapError(storeError("ack failed"))));
219
+ if (reply.error === "notfound")
220
+ return yield* new JobStore.JobNotFoundError({ jobId: id });
221
+ if (reply.error === "locklost")
222
+ return yield* new JobStore.LockLostError({ jobId: id });
223
+ if (reply.wake === true) {
224
+ yield* wakeUp;
225
+ }
226
+ }),
227
+ release: (id, token) => Effect.gen(function* () {
228
+ const now = yield* Clock.currentTimeMillis;
229
+ const reply = JSON.parse(yield* evalRelease(prefix, id, token, now).pipe(Effect.mapError(storeError("release failed"))));
230
+ if (reply.error === "notfound")
231
+ return yield* new JobStore.JobNotFoundError({ jobId: id });
232
+ if (reply.error === "locklost")
233
+ return yield* new JobStore.LockLostError({ jobId: id });
234
+ if (reply.wake === true) {
235
+ yield* wakeUp;
236
+ }
237
+ }),
238
+ extendLocks: (locks, durationMs) => Effect.gen(function* () {
239
+ if (locks.length === 0) {
240
+ const empty = { lost: [], cancelRequested: [] };
241
+ return empty;
242
+ }
243
+ const now = yield* Clock.currentTimeMillis;
244
+ const reply = JSON.parse(yield* evalExtendLocks(prefix, JSON.stringify(locks), durationMs, now));
245
+ const result = {
246
+ lost: asArray(reply.lost).map(JobStore.JobId),
247
+ cancelRequested: asArray(reply.cancel).map(JobStore.JobId)
248
+ };
249
+ return result;
250
+ }).pipe(Effect.mapError(storeError("extendLocks failed"))),
251
+ recoverStalled: (recoverOptions) => Effect.gen(function* () {
252
+ const now = yield* Clock.currentTimeMillis;
253
+ const recovered = JSON.parse(yield* evalRecoverStalled(prefix, recoverOptions.maxStalledCount, now));
254
+ const result = recovered.map((entry) => ({ id: JobStore.JobId(entry.id), failed: entry.failed }));
255
+ if (result.some((entry) => !entry.failed)) {
256
+ yield* wakeUp;
257
+ }
258
+ return result;
259
+ }).pipe(Effect.mapError(storeError("recoverStalled failed"))),
260
+ awaitWake: (_queues, wakeToken) => Effect.suspend(() => {
261
+ if (wakeVersion > wakeToken)
262
+ return Effect.void;
263
+ return Deferred.await(wake);
264
+ }),
265
+ getJob: (id) => evalGetJob(prefix, id).pipe(Effect.mapError(storeError("getJob failed")), Effect.map((raw) => {
266
+ const flat = JSON.parse(raw);
267
+ return flat.length === 0 ? Option.none() : Option.some(toRecord(foldPairs(flat)));
268
+ })),
269
+ getAttempts: (id) => redis.send("LRANGE", `${prefix}:attempts:${id}`, "0", "-1").pipe(Effect.mapError(storeError("getAttempts failed")), Effect.map((raw) => {
270
+ // SAFETY: LRANGE always replies with an array of bulk strings.
271
+ const entries = raw;
272
+ return entries.map((entry) => {
273
+ const parsed = JSON.parse(entry);
274
+ const record = {
275
+ attempt: parsed.attempt,
276
+ startedAt: parsed.startedAt ?? undefined,
277
+ finishedAt: parsed.finishedAt,
278
+ outcome: parsed.outcome,
279
+ // The ledger omits the key entirely for absent exits, so a
280
+ // legitimate encoded null exit survives the round trip.
281
+ exit: Object.hasOwn(parsed, "exit") ? parsed.exit : undefined
282
+ };
283
+ return record;
284
+ });
285
+ })),
286
+ list: (listOptions) => Effect.gen(function* () {
287
+ const limit = Math.max(1, listOptions.limit ?? 50);
288
+ const filters = {
289
+ queue: listOptions.queue,
290
+ name: listOptions.name,
291
+ states: listOptions.states,
292
+ metadata: listOptions.metadata
293
+ };
294
+ const reply = JSON
295
+ .parse(yield* evalList(prefix, JSON.stringify(filters), listOptions.cursor ?? "", limit));
296
+ const items = asArray(reply.items).map((flat) => toRecord(foldPairs(flat)));
297
+ const last = items[items.length - 1];
298
+ const result = {
299
+ items,
300
+ cursor: reply.more && last !== undefined ? `${last.enqueuedAt}:${last.id}` : undefined
301
+ };
302
+ return result;
303
+ }).pipe(Effect.mapError(storeError("list failed"))),
304
+ retry: (id) => Effect.gen(function* () {
305
+ const now = yield* Clock.currentTimeMillis;
306
+ const reply = JSON.parse(yield* evalRetry(prefix, id, now).pipe(Effect.mapError(storeError("retry failed"))));
307
+ if (reply.error === "notfound")
308
+ return yield* new JobStore.JobNotFoundError({ jobId: id });
309
+ if (reply.error === "state") {
310
+ return yield* new JobStore.JobNotRetryableError({ jobId: id, state: reply.state ?? "failed" });
311
+ }
312
+ yield* wakeUp;
313
+ }),
314
+ counts: (queue) => evalCounts(prefix).pipe(Effect.mapError(storeError("counts failed")), Effect.map((raw) => {
315
+ const flat = JSON.parse(raw);
316
+ const byField = foldPairs(flat);
317
+ // SAFETY: fromEntries over the exhaustive JOB_STATES list yields
318
+ // exactly one zeroed entry per JobState member.
319
+ const totals = Object.fromEntries(JOB_STATES.map((state) => [state, 0]));
320
+ for (const [field, count] of byField) {
321
+ const split = field.lastIndexOf("|");
322
+ const fieldQueue = field.slice(0, split);
323
+ // SAFETY: counts fields are written as `<queue>|<JobState>`.
324
+ const state = field.slice(split + 1);
325
+ if (queue === undefined || fieldQueue === queue) {
326
+ totals[state] += Number(count);
327
+ }
328
+ }
329
+ return totals;
330
+ })),
331
+ remove: (id) => evalRemove(prefix, id).pipe(Effect.mapError(storeError("remove failed")), Effect.map((raw) => raw !== "0")),
332
+ cancel: (id) => Effect.gen(function* () {
333
+ const now = yield* Clock.currentTimeMillis;
334
+ const reply = JSON.parse(yield* evalCancel(prefix, id, now).pipe(Effect.mapError(storeError("cancel failed"))));
335
+ if (reply.error === "notfound")
336
+ return yield* new JobStore.JobNotFoundError({ jobId: id });
337
+ if (reply.error === "state") {
338
+ return yield* new JobStore.JobNotCancellableError({ jobId: id, state: reply.state ?? "completed" });
339
+ }
340
+ }),
341
+ promote: (id) => Effect.gen(function* () {
342
+ const now = yield* Clock.currentTimeMillis;
343
+ const reply = JSON.parse(yield* evalPromote(prefix, id, now).pipe(Effect.mapError(storeError("promote failed"))));
344
+ if (reply.error === "notfound")
345
+ return yield* new JobStore.JobNotFoundError({ jobId: id });
346
+ if (reply.error === "state") {
347
+ return yield* new JobStore.JobNotPromotableError({ jobId: id, state: reply.state ?? "completed" });
348
+ }
349
+ yield* wakeUp;
350
+ }),
351
+ pause: (queue) => redis.send("SADD", `${prefix}:paused`, queue).pipe(Effect.mapError(storeError("pause failed")), Effect.asVoid),
352
+ resume: (queue) => redis.send("SREM", `${prefix}:paused`, queue).pipe(Effect.mapError(storeError("resume failed")), Effect.flatMap((removed) => Number(removed) > 0 ? wakeUp : Effect.void)),
353
+ pausedQueues: () => redis.send("SMEMBERS", `${prefix}:paused`).pipe(Effect.mapError(storeError("pausedQueues failed")), Effect.map((raw) => {
354
+ // SAFETY: SMEMBERS always replies with an array of bulk strings.
355
+ const members = raw;
356
+ return members.map(JobStore.QueueName);
357
+ })),
358
+ upsertSchedule: (schedule) => evalUpsertSchedule(prefix, schedule.key, schedule.jobName, schedule.queue, schedule.cron ?? "", schedule.tz ?? "", schedule.everyMs === undefined ? "" : String(schedule.everyMs), schedule.payload === undefined ? "" : JSON.stringify(schedule.payload), JSON.stringify(schedule.metadata), String(schedule.priority), String(schedule.attemptsMax), schedule.backoff === undefined ? "" : JSON.stringify(schedule.backoff), schedule.keep === undefined ? "" : JSON.stringify(schedule.keep), schedule.timeoutMs === undefined ? "" : String(schedule.timeoutMs), schedule.nextRunAt).pipe(Effect.mapError(storeError("upsertSchedule failed")), Effect.andThen(wakeUp)),
359
+ removeSchedule: (key) => evalRemoveSchedule(prefix, key).pipe(Effect.mapError(storeError("removeSchedule failed")), Effect.map((raw) => raw !== "0")),
360
+ listSchedules: (listOptions) => evalListSchedules(prefix, JSON.stringify(listOptions ?? {})).pipe(Effect.mapError(storeError("listSchedules failed")), Effect.map((raw) => {
361
+ const flat = JSON.parse(raw);
362
+ return flat.map((pairs) => toSchedule(foldPairs(pairs)));
363
+ })),
364
+ dueSchedules: () => Effect.gen(function* () {
365
+ const now = yield* Clock.currentTimeMillis;
366
+ const flat = JSON.parse(yield* evalDueSchedules(prefix, now));
367
+ return flat.map((pairs) => toSchedule(foldPairs(pairs)));
368
+ }).pipe(Effect.mapError(storeError("dueSchedules failed"))),
369
+ advanceSchedule: (key, expectedRunAt, nextRunAt) => evalAdvanceSchedule(prefix, key, expectedRunAt, nextRunAt).pipe(Effect.mapError(storeError("advanceSchedule failed")), Effect.asVoid)
370
+ };
371
+ return store;
372
+ });
373
+ /**
374
+ * A Redis-backed layer for the default `JobStore`.
375
+ *
376
+ * @since 0.2.0
377
+ */
378
+ export const layer = (options) => Layer.effect(JobStore.JobStore, make(options));
379
+ /**
380
+ * A Redis-backed layer for a specific named store key.
381
+ *
382
+ * @since 0.2.0
383
+ */
384
+ export const layerFor = (store, options) => Layer.effect(store, make(options));
385
+ //# sourceMappingURL=RedisJobStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedisJobStore.js","sourceRoot":"","sources":["../../src/redis/RedisJobStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The Redis-backed `JobStore`, built on `effect/unstable/persistence`'s
3
+ * `Redis` service (provide it via `NodeRedis.layer`, `BunRedis.layer`, or
4
+ * `Redis.make` over any client).
5
+ *
6
+ * @since 0.2.0
7
+ */
8
+ export * as RedisJobStore from "./RedisJobStore.ts";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/redis/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The Redis-backed `JobStore`, built on `effect/unstable/persistence`'s
3
+ * `Redis` service (provide it via `NodeRedis.layer`, `BunRedis.layer`, or
4
+ * `Redis.make` over any client).
5
+ *
6
+ * @since 0.2.0
7
+ */
8
+ export * as RedisJobStore from "./RedisJobStore.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/redis/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Lua scripts backing `RedisJobStore`.
3
+ *
4
+ * Every mutation is one script, so every `JobStore` method is atomic on the
5
+ * server. Two disciplines apply throughout:
6
+ *
7
+ * - **All time comes in via ARGV** (from the Effect `Clock`) — never Redis
8
+ * `TIME` — so the conformance suite drives this driver under `TestClock`
9
+ * against a real server.
10
+ * - **Numbers that become strings are formatted with `%.0f`** — Lua 5.1's
11
+ * `tostring` renders large integers as `1.7e+12`, which would corrupt ids
12
+ * and stored timestamps.
13
+ *
14
+ * Key layout (all under a configurable prefix, non-cluster):
15
+ *
16
+ * - `p:seq` counter for seq + default job ids
17
+ * - `p:job:<id>` HASH of the job record
18
+ * - `p:attempts:<id>` LIST of JSON attempt-ledger entries
19
+ * - `p:waiting:<queue>` ZSET, score `-priority`, member `<seq %016d>:<id>`
20
+ * (score = priority desc; member lex = FIFO)
21
+ * - `p:delayed:<queue>` ZSET, score `runAt`
22
+ * - `p:active` ZSET, score `lockExpiresAt`
23
+ * - `p:all` ZSET, score `enqueuedAt` (list pagination)
24
+ * - `p:finished` ZSET, score `finishedAt` (history TTL)
25
+ * - `p:terminal:<name>:<state>` ZSET, score `finishedAt` (keep pruning)
26
+ * - `p:counts` HASH `<queue>|<state>` -> integer
27
+ * - `p:paused` SET of paused queues
28
+ * - `p:schedules` / `p:schedule:<key>` ZSET by nextRunAt + HASH per record
29
+ *
30
+ * @since 0.2.0
31
+ */
32
+ import { Redis } from "effect/unstable/persistence";
33
+ /**
34
+ * enqueue(prefix, idMode, id, name, queue, payloadJson, metadataJson,
35
+ * priority, attemptsMax, backoffJson, keepJson, timeoutMs, delayMs, now)
36
+ * idMode: "user" (dedup no-op), "generated" (collision -> retry sentinel),
37
+ * "auto" (j-<seq>, in-script collision loop).
38
+ */
39
+ export declare const enqueue: Redis.Script<{
40
+ 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];
41
+ result: string;
42
+ }>;
43
+ /**
44
+ * claim(prefix, queue, namesJson, token, lockDurationMs, now)
45
+ * Promotes due delayed jobs first (also while paused), then claims the best
46
+ * waiting job whose name matches. Returns the claimed record (HGETALL pairs)
47
+ * or an Empty result with the earliest matching delayed runAt.
48
+ */
49
+ export declare const claim: Redis.Script<{
50
+ params: [prefix: string, queue: string, namesJson: string, token: string, lockDurationMs: number, now: number];
51
+ result: string;
52
+ }>;
53
+ /**
54
+ * ack(prefix, id, token, outcomeTag, exitJson, delayMs, now)
55
+ * Token-guarded. Retry on a cancel-requested job finishes it as cancelled
56
+ * (cancellation wins over revival, mirroring release/recoverStalled).
57
+ */
58
+ export declare const ack: Redis.Script<{
59
+ params: [prefix: string, id: string, token: string, outcomeTag: string, exitJson: string, delayMs: number, now: number];
60
+ result: string;
61
+ }>;
62
+ /**
63
+ * release(prefix, id, token, now) — hand the job back without consuming an
64
+ * attempt; a pending cancel wins and finishes the job instead.
65
+ */
66
+ export declare const release: Redis.Script<{
67
+ params: [prefix: string, id: string, token: string, now: number];
68
+ result: string;
69
+ }>;
70
+ /**
71
+ * extendLocks(prefix, locksJson, durationMs, now) -> { lost, cancel }
72
+ * Cancel-requested locks are reported, not extended.
73
+ */
74
+ export declare const extendLocks: Redis.Script<{
75
+ params: [prefix: string, locksJson: string, durationMs: number, now: number];
76
+ result: string;
77
+ }>;
78
+ /**
79
+ * recoverStalled(prefix, maxStalledCount, now) -> recovered [{id, failed}]
80
+ * A pending cancel finishes the job as cancelled (not reported as recovered).
81
+ */
82
+ export declare const recoverStalled: Redis.Script<{
83
+ params: [prefix: string, maxStalledCount: number, now: number];
84
+ result: string;
85
+ }>;
86
+ /** getJob(prefix, id) -> HGETALL pairs (empty array when missing). */
87
+ export declare const getJob: Redis.Script<{
88
+ params: [prefix: string, id: string];
89
+ result: string;
90
+ }>;
91
+ /**
92
+ * list(prefix, filtersJson, cursor, limit)
93
+ * Keyset pagination over p:all, newest first (enqueuedAt DESC, id DESC).
94
+ */
95
+ export declare const list: Redis.Script<{
96
+ params: [prefix: string, filtersJson: string, cursor: string, limit: number];
97
+ result: string;
98
+ }>;
99
+ /** counts(prefix) -> HGETALL pairs of p:counts. */
100
+ export declare const counts: Redis.Script<{
101
+ params: [prefix: string];
102
+ result: string;
103
+ }>;
104
+ /** remove(prefix, id) -> removed boolean (active jobs are refused). */
105
+ export declare const remove: Redis.Script<{
106
+ params: [prefix: string, id: string];
107
+ result: string;
108
+ }>;
109
+ /** retry(prefix, id, now) — failed -> waiting with a fresh budget. */
110
+ export declare const retry: Redis.Script<{
111
+ params: [prefix: string, id: string, now: number];
112
+ result: string;
113
+ }>;
114
+ /**
115
+ * cancel(prefix, id, now) — waiting/delayed become terminal; active gets the
116
+ * cancel-request flag; terminal states are refused.
117
+ */
118
+ export declare const cancel: Redis.Script<{
119
+ params: [prefix: string, id: string, now: number];
120
+ result: string;
121
+ }>;
122
+ /** promote(prefix, id, now) — delayed -> waiting now. */
123
+ export declare const promote: Redis.Script<{
124
+ params: [prefix: string, id: string, now: number];
125
+ result: string;
126
+ }>;
127
+ /**
128
+ * upsertSchedule(prefix, key, jobName, queue, cron, tz, everyMs, payloadJson,
129
+ * metadataJson, priority, attemptsMax, backoffJson, keepJson,
130
+ * timeoutMs, nextRunAt)
131
+ * Every field arrives pre-encoded from TS and is stored VERBATIM — routing a
132
+ * record through cjson would corrupt high-precision numbers (14 significant
133
+ * digits) and empty arrays ({}). An unchanged cadence (cron/tz/everyMs)
134
+ * preserves the stored nextRunAt.
135
+ */
136
+ export declare const upsertSchedule: Redis.Script<{
137
+ 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];
138
+ result: string;
139
+ }>;
140
+ /** removeSchedule(prefix, key) -> existed boolean. */
141
+ export declare const removeSchedule: Redis.Script<{
142
+ params: [prefix: string, key: string];
143
+ result: string;
144
+ }>;
145
+ /** listSchedules(prefix, filtersJson) ordered by nextRunAt ascending. */
146
+ export declare const listSchedules: Redis.Script<{
147
+ params: [prefix: string, filtersJson: string];
148
+ result: string;
149
+ }>;
150
+ /** dueSchedules(prefix, now) ordered by nextRunAt ascending. */
151
+ export declare const dueSchedules: Redis.Script<{
152
+ params: [prefix: string, now: number];
153
+ result: string;
154
+ }>;
155
+ /** advanceSchedule(prefix, key, expectedRunAt, nextRunAt) — conditional CAS. */
156
+ export declare const advanceSchedule: Redis.Script<{
157
+ params: [prefix: string, key: string, expectedRunAt: number, nextRunAt: number];
158
+ result: string;
159
+ }>;
160
+ /**
161
+ * sweepHistory(prefix, cutoff, limit) -> number swept (bounded batch; the
162
+ * caller loops until 0).
163
+ */
164
+ export declare const sweepHistory: Redis.Script<{
165
+ params: [prefix: string, cutoff: number, limit: number];
166
+ result: string;
167
+ }>;
168
+ //# sourceMappingURL=scripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/redis/scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AAuGnD;;;;;GAKG;AACH,eAAO,MAAM,OAAO;;;EA+EM,CAAA;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;EAsEQ,CAAA;AAE1B;;;;GAIG;AACH,eAAO,MAAM,GAAG;;;EAwEU,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,OAAO;;;EA4BM,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,WAAW;;;EAuBE,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,cAAc;;;EA+CD,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,uEAAuE;AACvE,eAAO,MAAM,MAAM;;;EAcO,CAAA;AAE1B,sEAAsE;AACtE,eAAO,MAAM,KAAK;;;EA2BQ,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,MAAM;;;EAgCO,CAAA;AAE1B,yDAAyD;AACzD,eAAO,MAAM,OAAO;;;EAqBM,CAAA;AAE1B;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;;EA4DD,CAAA;AAE1B,sDAAsD;AACtD,eAAO,MAAM,cAAc;;;EAUD,CAAA;AAE1B,yEAAyE;AACzE,eAAO,MAAM,aAAa;;;EAqBA,CAAA;AAE1B,gEAAgE;AAChE,eAAO,MAAM,YAAY;;;EAcC,CAAA;AAE1B,gFAAgF;AAChF,eAAO,MAAM,eAAe;;;EAcF,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,YAAY;;;EAUC,CAAA"}