effect-mq 0.1.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/LICENSE +21 -0
- package/README.md +235 -0
- package/dist/Job.d.ts +222 -0
- package/dist/Job.d.ts.map +1 -0
- package/dist/Job.js +218 -0
- package/dist/Job.js.map +1 -0
- package/dist/JobStore.d.ts +401 -0
- package/dist/JobStore.d.ts.map +1 -0
- package/dist/JobStore.js +89 -0
- package/dist/JobStore.js.map +1 -0
- package/dist/MemoryJobStore.d.ts +34 -0
- package/dist/MemoryJobStore.d.ts.map +1 -0
- package/dist/MemoryJobStore.js +381 -0
- package/dist/MemoryJobStore.js.map +1 -0
- package/dist/Worker.d.ts +127 -0
- package/dist/Worker.d.ts.map +1 -0
- package/dist/Worker.js +274 -0
- package/dist/Worker.js.map +1 -0
- package/dist/drizzle/DrizzleJobStore.d.ts +59 -0
- package/dist/drizzle/DrizzleJobStore.d.ts.map +1 -0
- package/dist/drizzle/DrizzleJobStore.js +426 -0
- package/dist/drizzle/DrizzleJobStore.js.map +1 -0
- package/dist/drizzle/index.d.ts +19 -0
- package/dist/drizzle/index.d.ts.map +1 -0
- package/dist/drizzle/index.js +19 -0
- package/dist/drizzle/index.js.map +1 -0
- package/dist/drizzle/schema.d.ts +464 -0
- package/dist/drizzle/schema.d.ts.map +1 -0
- package/dist/drizzle/schema.js +68 -0
- package/dist/drizzle/schema.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/testing/conformance.d.ts +27 -0
- package/dist/testing/conformance.d.ts.map +1 -0
- package/dist/testing/conformance.js +451 -0
- package/dist/testing/conformance.js.map +1 -0
- package/dist/testing/index.d.ts +8 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +71 -0
- package/src/Job.ts +606 -0
- package/src/JobStore.ts +446 -0
- package/src/MemoryJobStore.ts +467 -0
- package/src/Worker.ts +514 -0
- package/src/drizzle/DrizzleJobStore.ts +599 -0
- package/src/drizzle/index.ts +20 -0
- package/src/drizzle/schema.ts +116 -0
- package/src/index.ts +33 -0
- package/src/testing/conformance.ts +654 -0
- package/src/testing/index.ts +7 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Postgres `JobStore` running through drizzle's Effect driver
|
|
3
|
+
* (`drizzle-orm/effect-postgres`, which is built on `@effect/sql-pg` —
|
|
4
|
+
* Node and Bun compatible).
|
|
5
|
+
*
|
|
6
|
+
* - Claims use `FOR UPDATE SKIP LOCKED`; acks are lock-token guarded.
|
|
7
|
+
* - ALL time comes from the Effect `Clock` as bind parameters (never SQL
|
|
8
|
+
* `now()`), so the conformance suite runs against real Postgres under
|
|
9
|
+
* `TestClock`.
|
|
10
|
+
* - Wake-ups use LISTEN/NOTIFY through the shared `PgClient` (with the
|
|
11
|
+
* worker's `pollInterval` as the fallback), so cross-process workers wake
|
|
12
|
+
* promptly.
|
|
13
|
+
*
|
|
14
|
+
* TODO: a standalone non-drizzle Postgres driver on plain `@effect/sql-pg`
|
|
15
|
+
* (same table layout), and an adapter for promise-based drizzle databases.
|
|
16
|
+
*
|
|
17
|
+
* @since 0.1.0
|
|
18
|
+
*/
|
|
19
|
+
import * as JobStore from "../JobStore.js";
|
|
20
|
+
import { asc, eq, sql } from "drizzle-orm";
|
|
21
|
+
import * as PgDrizzle from "drizzle-orm/effect-postgres";
|
|
22
|
+
import { getTableConfig } from "drizzle-orm/pg-core";
|
|
23
|
+
import { Clock, Deferred, Effect, Layer, Option, Stream } from "effect";
|
|
24
|
+
const { JobId } = JobStore;
|
|
25
|
+
const storeError = (message) => (cause) => new JobStore.JobStoreError({ message, cause });
|
|
26
|
+
const rowsOf = (result) => "rows" in result ? result.rows : result;
|
|
27
|
+
const toRecord = (row) => ({
|
|
28
|
+
id: JobId(row.id),
|
|
29
|
+
name: row.name,
|
|
30
|
+
queue: JobStore.QueueName(row.queue),
|
|
31
|
+
payload: row.payload,
|
|
32
|
+
metadata: row.metadata ?? {},
|
|
33
|
+
state: row.state,
|
|
34
|
+
priority: row.priority,
|
|
35
|
+
attemptsMax: row.attemptsMax,
|
|
36
|
+
attemptsMade: row.attemptsMade,
|
|
37
|
+
stalledCount: row.stalledCount,
|
|
38
|
+
backoff: row.backoff ?? undefined,
|
|
39
|
+
keep: row.keep ?? undefined,
|
|
40
|
+
runAt: row.runAt.getTime(),
|
|
41
|
+
enqueuedAt: row.enqueuedAt.getTime(),
|
|
42
|
+
processedAt: row.processedAt?.getTime(),
|
|
43
|
+
finishedAt: row.finishedAt?.getTime(),
|
|
44
|
+
exit: row.exit ?? undefined,
|
|
45
|
+
failedReason: row.failedReason ?? undefined
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Build the store implementation. Requires `PgClient` and a `Scope` (for the
|
|
49
|
+
* LISTEN subscription).
|
|
50
|
+
*
|
|
51
|
+
* @since 0.1.0
|
|
52
|
+
*/
|
|
53
|
+
export const make = (options) => Effect.gen(function* () {
|
|
54
|
+
const db = yield* PgDrizzle.makeWithDefaults();
|
|
55
|
+
const client = db.$client;
|
|
56
|
+
const jobs = options.jobs;
|
|
57
|
+
const attempts = options.attempts;
|
|
58
|
+
const jobsName = getTableConfig(jobs).name;
|
|
59
|
+
const attemptsName = getTableConfig(attempts).name;
|
|
60
|
+
const wakeChannel = `effect_mq_wake_${jobsName}`;
|
|
61
|
+
if (options.validate ?? true) {
|
|
62
|
+
yield* Effect.all([
|
|
63
|
+
db.select({ id: jobs.id }).from(jobs).limit(0),
|
|
64
|
+
db.select({ jobId: attempts.jobId }).from(attempts).limit(0)
|
|
65
|
+
]).pipe(Effect.mapError(storeError(`effect-mq: tables "${jobsName}"/"${attemptsName}" are missing or mismatched — ` +
|
|
66
|
+
`re-export the effect-mq/drizzle schema factories from your drizzle schema and run your migrations (drizzle-kit generate)`)));
|
|
67
|
+
}
|
|
68
|
+
// Wake plumbing: a local version + deferred chain (same protocol as the
|
|
69
|
+
// memory driver), fed by (a) local store operations and (b) cross-process
|
|
70
|
+
// LISTEN notifications.
|
|
71
|
+
let wakeVersion = 0;
|
|
72
|
+
let wake = Deferred.makeUnsafe();
|
|
73
|
+
const signalWake = () => {
|
|
74
|
+
wakeVersion += 1;
|
|
75
|
+
const current = wake;
|
|
76
|
+
wake = Deferred.makeUnsafe();
|
|
77
|
+
Deferred.doneUnsafe(current, Effect.void);
|
|
78
|
+
};
|
|
79
|
+
// Resubscribe forever: if the LISTEN stream ends or fails, wake-ups
|
|
80
|
+
// degrade to the worker's pollInterval until the next attempt succeeds.
|
|
81
|
+
yield* client.listen(wakeChannel).pipe(Stream.runForEach(() => Effect.sync(signalWake)), Effect.catchCause((cause) => Effect.logWarning("effect-mq: LISTEN subscription failed; wake-ups degraded to polling until resubscribe", cause)), Effect.andThen(Effect.sleep("1 second")), Effect.forever, Effect.forkScoped);
|
|
82
|
+
// Local mutation wake-up: bump synchronously, then best-effort NOTIFY so
|
|
83
|
+
// workers in other processes wake promptly too.
|
|
84
|
+
const wakeUp = Effect.suspend(() => {
|
|
85
|
+
signalWake();
|
|
86
|
+
// The payload must be non-empty: @effect/sql-pg drops falsy payloads.
|
|
87
|
+
return client.notify(wakeChannel, "1").pipe(Effect.ignore);
|
|
88
|
+
});
|
|
89
|
+
const nowDate = Effect.map(Clock.currentTimeMillis, (ms) => new Date(ms));
|
|
90
|
+
// quote_ident handles quoted/mixed-case table names safely.
|
|
91
|
+
const seqExpr = sql `nextval(pg_get_serial_sequence(quote_ident(${jobsName}), 'seq'))`;
|
|
92
|
+
const insertAttempt = (tx, jobId, outcome, startedAt, finishedAt, exit) => tx.execute(sql `
|
|
93
|
+
INSERT INTO ${attempts} (job_id, attempt, outcome, started_at, finished_at, exit)
|
|
94
|
+
SELECT ${jobId}, COALESCE(MAX(${attempts.attempt}), 0) + 1, ${outcome}, ${startedAt}, ${finishedAt},
|
|
95
|
+
${exit === undefined ? null : JSON.stringify(exit)}::jsonb
|
|
96
|
+
FROM ${attempts} WHERE ${attempts.jobId} = ${jobId}
|
|
97
|
+
`);
|
|
98
|
+
// Retention: drop terminal peers (same name + state) beyond count/age.
|
|
99
|
+
const applyKeep = (tx, row, now) => Effect.gen(function* () {
|
|
100
|
+
const keep = row.keep;
|
|
101
|
+
if (keep === null || keep === undefined)
|
|
102
|
+
return;
|
|
103
|
+
if (keep.ageMs !== undefined) {
|
|
104
|
+
yield* tx.execute(sql `
|
|
105
|
+
DELETE FROM ${jobs}
|
|
106
|
+
WHERE ${jobs.name} = ${row.name} AND ${jobs.state} = ${row.state}
|
|
107
|
+
AND ${jobs.finishedAt} <= ${new Date(now.getTime() - keep.ageMs)}
|
|
108
|
+
`);
|
|
109
|
+
}
|
|
110
|
+
if (keep.count !== undefined) {
|
|
111
|
+
yield* tx.execute(sql `
|
|
112
|
+
DELETE FROM ${jobs}
|
|
113
|
+
WHERE ${jobs.name} = ${row.name} AND ${jobs.state} = ${row.state}
|
|
114
|
+
AND ${jobs.id} NOT IN (
|
|
115
|
+
SELECT ${jobs.id} FROM ${jobs}
|
|
116
|
+
WHERE ${jobs.name} = ${row.name} AND ${jobs.state} = ${row.state}
|
|
117
|
+
ORDER BY ${jobs.finishedAt} DESC, ${jobs.seq} DESC
|
|
118
|
+
LIMIT ${keep.count}
|
|
119
|
+
)
|
|
120
|
+
`);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// Distinguish JobNotFound vs LockLost after a guarded UPDATE hit 0 rows.
|
|
124
|
+
const explainMiss = (id) => db.select({ id: jobs.id }).from(jobs).where(eq(jobs.id, id)).pipe(Effect.mapError(storeError("failed to inspect job")), Effect.flatMap((rows) => Effect.fail(rows.length === 0
|
|
125
|
+
? new JobStore.JobNotFoundError({ jobId: id })
|
|
126
|
+
: new JobStore.LockLostError({ jobId: id }))));
|
|
127
|
+
const store = {
|
|
128
|
+
enqueue: (request) => Effect.gen(function* () {
|
|
129
|
+
const now = yield* nowDate;
|
|
130
|
+
const runAt = new Date(now.getTime() + Math.max(0, request.delayMs));
|
|
131
|
+
const state = request.delayMs > 0 ? "delayed" : "waiting";
|
|
132
|
+
// Store-assigned ids come from the seq sequence; loop on the
|
|
133
|
+
// (unlikely) collision with a user-supplied id.
|
|
134
|
+
for (let i = 0; i < 5; i++) {
|
|
135
|
+
const idExpr = request.id !== undefined
|
|
136
|
+
? sql `${request.id}`
|
|
137
|
+
: sql `'j-' || ${seqExpr}::text`;
|
|
138
|
+
const rows = rowsOf(yield* db.execute(sql `
|
|
139
|
+
INSERT INTO ${jobs} (id, name, queue, state, priority, payload, metadata,
|
|
140
|
+
attempts_max, backoff, keep, run_at, enqueued_at)
|
|
141
|
+
VALUES (${idExpr}, ${request.name}, ${request.queue}, ${state}, ${request.priority},
|
|
142
|
+
${JSON.stringify(request.payload ?? null)}::jsonb, ${JSON.stringify(request.metadata)}::jsonb,
|
|
143
|
+
${request.attemptsMax},
|
|
144
|
+
${request.backoff === undefined ? null : JSON.stringify(request.backoff)}::jsonb,
|
|
145
|
+
${request.keep === undefined ? null : JSON.stringify(request.keep)}::jsonb,
|
|
146
|
+
${runAt}, ${now})
|
|
147
|
+
ON CONFLICT (id) DO NOTHING
|
|
148
|
+
RETURNING ${jobs.id} AS id
|
|
149
|
+
`).pipe(Effect.mapError(storeError("enqueue failed"))));
|
|
150
|
+
const inserted = rows[0];
|
|
151
|
+
if (inserted !== undefined) {
|
|
152
|
+
yield* wakeUp;
|
|
153
|
+
return { id: JobId(inserted.id), duplicate: false };
|
|
154
|
+
}
|
|
155
|
+
if (request.id !== undefined) {
|
|
156
|
+
return { id: request.id, duplicate: true };
|
|
157
|
+
}
|
|
158
|
+
// generated id collided with an existing user id; try again
|
|
159
|
+
}
|
|
160
|
+
return yield* new JobStore.JobStoreError({
|
|
161
|
+
message: "enqueue failed: could not generate a unique job id"
|
|
162
|
+
});
|
|
163
|
+
}),
|
|
164
|
+
claim: (claimOptions) => Effect.suspend(() => {
|
|
165
|
+
// Snapshot BEFORE the transaction: any wake that fires while the
|
|
166
|
+
// claim's statements run must make awaitWake(token) return
|
|
167
|
+
// immediately (spurious wake-ups are allowed; lost ones are not).
|
|
168
|
+
const observedWake = wakeVersion;
|
|
169
|
+
return db.transaction((tx) => Effect.gen(function* () {
|
|
170
|
+
const now = yield* nowDate;
|
|
171
|
+
// Promote due delayed jobs first (separate statement: CTEs share
|
|
172
|
+
// a snapshot, so an UPDATE CTE would be invisible to the claim).
|
|
173
|
+
yield* tx.execute(sql `
|
|
174
|
+
UPDATE ${jobs} SET state = 'waiting'
|
|
175
|
+
WHERE ${jobs.queue} = ${claimOptions.queue} AND ${jobs.state} = 'delayed'
|
|
176
|
+
AND ${jobs.runAt} <= ${now}
|
|
177
|
+
`);
|
|
178
|
+
const claimed = rowsOf(yield* tx.execute(sql `
|
|
179
|
+
WITH candidate AS (
|
|
180
|
+
SELECT ${jobs.id} AS id FROM ${jobs}
|
|
181
|
+
WHERE ${jobs.queue} = ${claimOptions.queue} AND ${jobs.state} = 'waiting'
|
|
182
|
+
AND ${jobs.name} = ANY(${sql.param([...claimOptions.names])})
|
|
183
|
+
ORDER BY ${jobs.priority} DESC, ${jobs.seq} ASC
|
|
184
|
+
FOR UPDATE SKIP LOCKED
|
|
185
|
+
LIMIT 1
|
|
186
|
+
)
|
|
187
|
+
UPDATE ${jobs} SET state = 'active', lock_token = ${claimOptions.token},
|
|
188
|
+
lock_expires_at = ${new Date(now.getTime() + claimOptions.lockDurationMs)},
|
|
189
|
+
processed_at = ${now}
|
|
190
|
+
FROM candidate WHERE ${jobs.id} = candidate.id
|
|
191
|
+
RETURNING ${jobs.id} AS "id", ${jobs.name} AS "name", ${jobs.queue} AS "queue",
|
|
192
|
+
${jobs.state} AS "state", ${jobs.priority} AS "priority", ${jobs.seq} AS "seq",
|
|
193
|
+
${jobs.payload} AS "payload", ${jobs.metadata} AS "metadata",
|
|
194
|
+
${jobs.attemptsMax} AS "attemptsMax", ${jobs.attemptsMade} AS "attemptsMade",
|
|
195
|
+
${jobs.stalledCount} AS "stalledCount", ${jobs.backoff} AS "backoff",
|
|
196
|
+
${jobs.keep} AS "keep", ${jobs.runAt} AS "runAt", ${jobs.enqueuedAt} AS "enqueuedAt",
|
|
197
|
+
${jobs.processedAt} AS "processedAt", ${jobs.finishedAt} AS "finishedAt",
|
|
198
|
+
${jobs.exit} AS "exit", ${jobs.failedReason} AS "failedReason"
|
|
199
|
+
`));
|
|
200
|
+
const row = claimed[0];
|
|
201
|
+
if (row !== undefined) {
|
|
202
|
+
const result = { _tag: "Claimed", job: toRecord(row) };
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
const next = rowsOf(yield* tx.execute(sql `
|
|
206
|
+
SELECT MIN(${jobs.runAt}) AS next FROM ${jobs}
|
|
207
|
+
WHERE ${jobs.queue} = ${claimOptions.queue} AND ${jobs.state} = 'delayed'
|
|
208
|
+
AND ${jobs.name} = ANY(${sql.param([...claimOptions.names])})
|
|
209
|
+
`));
|
|
210
|
+
const empty = {
|
|
211
|
+
_tag: "Empty",
|
|
212
|
+
nextRunAt: next[0]?.next?.getTime(),
|
|
213
|
+
wakeToken: observedWake
|
|
214
|
+
};
|
|
215
|
+
return empty;
|
|
216
|
+
}));
|
|
217
|
+
}).pipe(Effect.mapError((error) => error instanceof JobStore.JobStoreError ? error : storeError("claim failed")(error))),
|
|
218
|
+
ack: (id, token, outcome) => db.transaction((tx) => Effect.gen(function* () {
|
|
219
|
+
const now = yield* nowDate;
|
|
220
|
+
const update = outcome._tag === "Complete"
|
|
221
|
+
? sql `state = 'completed', exit = ${JSON.stringify(outcome.exit ?? null)}::jsonb, finished_at = ${now}`
|
|
222
|
+
: outcome._tag === "Fail"
|
|
223
|
+
? sql `state = 'failed', exit = ${JSON.stringify(outcome.exit ?? null)}::jsonb, finished_at = ${now}`
|
|
224
|
+
: sql `state = ${outcome.delayMs > 0 ? "delayed" : "waiting"},
|
|
225
|
+
run_at = ${new Date(now.getTime() + Math.max(0, outcome.delayMs))},
|
|
226
|
+
seq = ${seqExpr}`;
|
|
227
|
+
const rows = rowsOf(yield* tx.execute(sql `
|
|
228
|
+
UPDATE ${jobs} SET ${update},
|
|
229
|
+
attempts_made = ${jobs.attemptsMade} + 1, lock_token = NULL, lock_expires_at = NULL
|
|
230
|
+
WHERE ${jobs.id} = ${id} AND ${jobs.state} = 'active' AND ${jobs.lockToken} = ${token}
|
|
231
|
+
RETURNING ${jobs.processedAt} AS "processedAt", ${jobs.name} AS "name",
|
|
232
|
+
${jobs.state} AS "state", ${jobs.keep} AS "keep"
|
|
233
|
+
`));
|
|
234
|
+
const row = rows[0];
|
|
235
|
+
if (row === undefined) {
|
|
236
|
+
return yield* explainMiss(id);
|
|
237
|
+
}
|
|
238
|
+
const ledgerOutcome = outcome._tag === "Complete"
|
|
239
|
+
? "completed"
|
|
240
|
+
: outcome._tag === "Fail"
|
|
241
|
+
? "failed"
|
|
242
|
+
: "retried";
|
|
243
|
+
yield* insertAttempt(tx, id, ledgerOutcome, row.processedAt, now, outcome.exit);
|
|
244
|
+
if (outcome._tag !== "Retry") {
|
|
245
|
+
yield* applyKeep(tx, row, now);
|
|
246
|
+
}
|
|
247
|
+
})).pipe(Effect.mapError((error) => error instanceof JobStore.JobNotFoundError || error instanceof JobStore.LockLostError ||
|
|
248
|
+
error instanceof JobStore.JobStoreError
|
|
249
|
+
? error
|
|
250
|
+
: storeError("ack failed")(error)), Effect.tap(() => outcome._tag === "Retry" ? wakeUp : Effect.void)),
|
|
251
|
+
release: (id, token) => Effect.gen(function* () {
|
|
252
|
+
const rows = rowsOf(yield* db.execute(sql `
|
|
253
|
+
UPDATE ${jobs} SET state = 'waiting', lock_token = NULL, lock_expires_at = NULL
|
|
254
|
+
WHERE ${jobs.id} = ${id} AND ${jobs.state} = 'active' AND ${jobs.lockToken} = ${token}
|
|
255
|
+
RETURNING ${jobs.id} AS id
|
|
256
|
+
`).pipe(Effect.mapError(storeError("release failed"))));
|
|
257
|
+
if (rows.length === 0) {
|
|
258
|
+
return yield* explainMiss(id);
|
|
259
|
+
}
|
|
260
|
+
yield* wakeUp;
|
|
261
|
+
}),
|
|
262
|
+
extendLocks: (locks, durationMs) => Effect.gen(function* () {
|
|
263
|
+
if (locks.length === 0)
|
|
264
|
+
return [];
|
|
265
|
+
const now = yield* nowDate;
|
|
266
|
+
const rows = rowsOf(yield* db.execute(sql `
|
|
267
|
+
WITH input AS (
|
|
268
|
+
SELECT ids.job_id, toks.token
|
|
269
|
+
FROM unnest(${sql.param(locks.map((lock) => lock.id))}::text[]) WITH ORDINALITY AS ids(job_id, ord)
|
|
270
|
+
JOIN unnest(${sql.param(locks.map((lock) => lock.token))}::text[]) WITH ORDINALITY AS toks(token, ord) USING (ord)
|
|
271
|
+
),
|
|
272
|
+
updated AS (
|
|
273
|
+
UPDATE ${jobs} SET lock_expires_at = ${new Date(now.getTime() + durationMs)}
|
|
274
|
+
FROM input
|
|
275
|
+
WHERE ${jobs.id} = input.job_id AND ${jobs.state} = 'active' AND ${jobs.lockToken} = input.token
|
|
276
|
+
RETURNING ${jobs.id} AS id
|
|
277
|
+
)
|
|
278
|
+
SELECT input.job_id AS id FROM input
|
|
279
|
+
LEFT JOIN updated ON updated.id = input.job_id
|
|
280
|
+
WHERE updated.id IS NULL
|
|
281
|
+
`).pipe(Effect.mapError(storeError("extendLocks failed"))));
|
|
282
|
+
return rows.map((row) => JobId(row.id));
|
|
283
|
+
}),
|
|
284
|
+
recoverStalled: (recoverOptions) => db.transaction((tx) => Effect.gen(function* () {
|
|
285
|
+
const now = yield* nowDate;
|
|
286
|
+
const rows = rowsOf(yield* tx.execute(sql `
|
|
287
|
+
UPDATE ${jobs} SET
|
|
288
|
+
stalled_count = ${jobs.stalledCount} + 1,
|
|
289
|
+
lock_token = NULL, lock_expires_at = NULL,
|
|
290
|
+
state = CASE WHEN ${jobs.stalledCount} + 1 > ${recoverOptions.maxStalledCount}::int
|
|
291
|
+
THEN 'failed' ELSE 'waiting' END,
|
|
292
|
+
finished_at = CASE WHEN ${jobs.stalledCount} + 1 > ${recoverOptions.maxStalledCount}::int
|
|
293
|
+
THEN ${now}::timestamptz ELSE NULL END,
|
|
294
|
+
failed_reason = CASE WHEN ${jobs.stalledCount} + 1 > ${recoverOptions.maxStalledCount}::int
|
|
295
|
+
THEN 'job stalled more than allowable limit' ELSE NULL END
|
|
296
|
+
WHERE ${jobs.state} = 'active' AND ${jobs.lockExpiresAt} <= ${now}::timestamptz
|
|
297
|
+
RETURNING ${jobs.id} AS "id", ${jobs.state} AS "state", ${jobs.processedAt} AS "processedAt"
|
|
298
|
+
`));
|
|
299
|
+
for (const row of rows) {
|
|
300
|
+
yield* insertAttempt(tx, row.id, "stalled", row.processedAt, now, undefined);
|
|
301
|
+
}
|
|
302
|
+
return rows.map((row) => ({ id: JobId(row.id), failed: row.state === "failed" }));
|
|
303
|
+
})).pipe(Effect.mapError((error) => error instanceof JobStore.JobStoreError ? error : storeError("recoverStalled failed")(error)), Effect.tap((recovered) => recovered.some((entry) => !entry.failed) ? wakeUp : Effect.void)),
|
|
304
|
+
awaitWake: (_queues, wakeToken) => Effect.suspend(() => {
|
|
305
|
+
if (wakeVersion > wakeToken)
|
|
306
|
+
return Effect.void;
|
|
307
|
+
return Deferred.await(wake);
|
|
308
|
+
}),
|
|
309
|
+
getJob: (id) => db.select().from(jobs).where(eq(jobs.id, id)).pipe(Effect.mapError(storeError("getJob failed")), Effect.map((rows) => {
|
|
310
|
+
const row = rows[0];
|
|
311
|
+
return row === undefined ? Option.none() : Option.some(toRecord(row));
|
|
312
|
+
})),
|
|
313
|
+
getAttempts: (id) => db.select().from(attempts).where(eq(attempts.jobId, id)).orderBy(asc(attempts.attempt)).pipe(Effect.mapError(storeError("getAttempts failed")), Effect.map((rows) => rows.map((row) => ({
|
|
314
|
+
attempt: row.attempt,
|
|
315
|
+
startedAt: row.startedAt?.getTime(),
|
|
316
|
+
finishedAt: row.finishedAt.getTime(),
|
|
317
|
+
outcome: row.outcome,
|
|
318
|
+
exit: row.exit ?? undefined
|
|
319
|
+
})))),
|
|
320
|
+
list: (listOptions) => Effect.gen(function* () {
|
|
321
|
+
const limit = Math.max(1, listOptions.limit ?? 50);
|
|
322
|
+
const conditions = [sql `TRUE`];
|
|
323
|
+
if (listOptions.queue !== undefined)
|
|
324
|
+
conditions.push(sql `${jobs.queue} = ${listOptions.queue}`);
|
|
325
|
+
if (listOptions.name !== undefined)
|
|
326
|
+
conditions.push(sql `${jobs.name} = ${listOptions.name}`);
|
|
327
|
+
if (listOptions.states !== undefined) {
|
|
328
|
+
// NB: an empty array matches nothing (ANY('{}') is false), same
|
|
329
|
+
// as the memory driver.
|
|
330
|
+
conditions.push(sql `${jobs.state} = ANY(${sql.param([...listOptions.states])})`);
|
|
331
|
+
}
|
|
332
|
+
if (listOptions.metadata !== undefined && Object.keys(listOptions.metadata).length > 0) {
|
|
333
|
+
conditions.push(sql `${jobs.metadata} @> ${JSON.stringify(listOptions.metadata)}::jsonb`);
|
|
334
|
+
}
|
|
335
|
+
if (listOptions.cursor !== undefined) {
|
|
336
|
+
const split = listOptions.cursor.indexOf(":");
|
|
337
|
+
const cursorAt = new Date(Number(listOptions.cursor.slice(0, split)));
|
|
338
|
+
const cursorId = listOptions.cursor.slice(split + 1);
|
|
339
|
+
conditions.push(sql `(${jobs.enqueuedAt}, ${jobs.id}) < (${cursorAt}, ${cursorId})`);
|
|
340
|
+
}
|
|
341
|
+
const rows = rowsOf(yield* db.execute(sql `
|
|
342
|
+
SELECT ${jobs.id} AS "id", ${jobs.name} AS "name", ${jobs.queue} AS "queue",
|
|
343
|
+
${jobs.state} AS "state", ${jobs.priority} AS "priority", ${jobs.seq} AS "seq",
|
|
344
|
+
${jobs.payload} AS "payload", ${jobs.metadata} AS "metadata",
|
|
345
|
+
${jobs.attemptsMax} AS "attemptsMax", ${jobs.attemptsMade} AS "attemptsMade",
|
|
346
|
+
${jobs.stalledCount} AS "stalledCount", ${jobs.backoff} AS "backoff",
|
|
347
|
+
${jobs.keep} AS "keep", ${jobs.runAt} AS "runAt", ${jobs.enqueuedAt} AS "enqueuedAt",
|
|
348
|
+
${jobs.processedAt} AS "processedAt", ${jobs.finishedAt} AS "finishedAt",
|
|
349
|
+
${jobs.exit} AS "exit", ${jobs.failedReason} AS "failedReason"
|
|
350
|
+
FROM ${jobs}
|
|
351
|
+
WHERE ${sql.join(conditions, sql ` AND `)}
|
|
352
|
+
ORDER BY ${jobs.enqueuedAt} DESC, ${jobs.id} DESC
|
|
353
|
+
LIMIT ${limit + 1}
|
|
354
|
+
`).pipe(Effect.mapError(storeError("list failed"))));
|
|
355
|
+
const items = rows.slice(0, limit).map(toRecord);
|
|
356
|
+
const last = items[items.length - 1];
|
|
357
|
+
return {
|
|
358
|
+
items,
|
|
359
|
+
cursor: rows.length > limit && last !== undefined
|
|
360
|
+
? `${last.enqueuedAt}:${last.id}`
|
|
361
|
+
: undefined
|
|
362
|
+
};
|
|
363
|
+
}),
|
|
364
|
+
retry: (id) => Effect.gen(function* () {
|
|
365
|
+
const now = yield* nowDate;
|
|
366
|
+
const rows = rowsOf(yield* db.execute(sql `
|
|
367
|
+
UPDATE ${jobs} SET state = 'waiting', attempts_made = 0, stalled_count = 0,
|
|
368
|
+
exit = NULL, failed_reason = NULL, finished_at = NULL, processed_at = NULL,
|
|
369
|
+
run_at = ${now}, seq = ${seqExpr}
|
|
370
|
+
WHERE ${jobs.id} = ${id} AND ${jobs.state} = 'failed'
|
|
371
|
+
RETURNING ${jobs.id} AS id
|
|
372
|
+
`).pipe(Effect.mapError(storeError("retry failed"))));
|
|
373
|
+
if (rows.length === 0) {
|
|
374
|
+
const existing = yield* db.select({ state: jobs.state }).from(jobs)
|
|
375
|
+
.where(eq(jobs.id, id)).pipe(Effect.mapError(storeError("retry failed")));
|
|
376
|
+
const found = existing[0];
|
|
377
|
+
if (found === undefined) {
|
|
378
|
+
return yield* new JobStore.JobNotFoundError({ jobId: id });
|
|
379
|
+
}
|
|
380
|
+
return yield* new JobStore.JobNotRetryableError({ jobId: id, state: found.state });
|
|
381
|
+
}
|
|
382
|
+
yield* wakeUp;
|
|
383
|
+
}),
|
|
384
|
+
counts: (queue) => db.execute(sql `
|
|
385
|
+
SELECT ${jobs.state} AS "state", count(*)::int AS "count" FROM ${jobs}
|
|
386
|
+
${queue === undefined ? sql `` : sql `WHERE ${jobs.queue} = ${queue}`}
|
|
387
|
+
GROUP BY ${jobs.state}
|
|
388
|
+
`).pipe(Effect.mapError(storeError("counts failed")), Effect.map((result) => {
|
|
389
|
+
const rows = rowsOf(result);
|
|
390
|
+
const counts = {
|
|
391
|
+
waiting: 0,
|
|
392
|
+
delayed: 0,
|
|
393
|
+
active: 0,
|
|
394
|
+
completed: 0,
|
|
395
|
+
failed: 0
|
|
396
|
+
};
|
|
397
|
+
for (const row of rows)
|
|
398
|
+
counts[row.state] = row.count;
|
|
399
|
+
return counts;
|
|
400
|
+
})),
|
|
401
|
+
remove: (id) => db.execute(sql `
|
|
402
|
+
DELETE FROM ${jobs}
|
|
403
|
+
WHERE ${jobs.id} = ${id} AND ${jobs.state} <> 'active'
|
|
404
|
+
RETURNING ${jobs.id} AS id
|
|
405
|
+
`).pipe(Effect.mapError(storeError("remove failed")), Effect.map((result) => rowsOf(result).length > 0))
|
|
406
|
+
};
|
|
407
|
+
return store;
|
|
408
|
+
});
|
|
409
|
+
/**
|
|
410
|
+
* A Postgres-backed `JobStore` layer over your drizzle tables. Requires
|
|
411
|
+
* `PgClient` (from `@effect/sql-pg`).
|
|
412
|
+
*
|
|
413
|
+
* ```ts
|
|
414
|
+
* const StoreLive = DrizzleJobStore.layer({ jobs, attempts, store: Durable }).pipe(
|
|
415
|
+
* Layer.provide(PgClient.layer({ url: Redacted.make(DATABASE_URL) }))
|
|
416
|
+
* )
|
|
417
|
+
* ```
|
|
418
|
+
*
|
|
419
|
+
* @since 0.1.0
|
|
420
|
+
*/
|
|
421
|
+
export const layer = (options) => Layer.effect(
|
|
422
|
+
// SAFETY: when `options.store` is omitted the public signature fixes
|
|
423
|
+
// `StoreId` to its default `JobStore.JobStore`, so the default key is the
|
|
424
|
+
// right `Context.Key<StoreId>`; when it is present the cast is an identity.
|
|
425
|
+
(options.store ?? JobStore.JobStore), make(options));
|
|
426
|
+
//# sourceMappingURL=DrizzleJobStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DrizzleJobStore.js","sourceRoot":"","sources":["../../src/drizzle/DrizzleJobStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres storage for effect-mq through drizzle.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.1.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The `JobStore` layer over your drizzle tables (via `drizzle-orm/effect-postgres`).
|
|
8
|
+
*
|
|
9
|
+
* @since 0.1.0
|
|
10
|
+
*/
|
|
11
|
+
export * as DrizzleJobStore from "./DrizzleJobStore.ts";
|
|
12
|
+
/**
|
|
13
|
+
* Drizzle table factories — re-export from your schema for drizzle-kit
|
|
14
|
+
* migrations and typed queries.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.1.0
|
|
17
|
+
*/
|
|
18
|
+
export * from "./schema.ts";
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/drizzle/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;;;;GAKG;AACH,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres storage for effect-mq through drizzle.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.1.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The `JobStore` layer over your drizzle tables (via `drizzle-orm/effect-postgres`).
|
|
8
|
+
*
|
|
9
|
+
* @since 0.1.0
|
|
10
|
+
*/
|
|
11
|
+
export * as DrizzleJobStore from "./DrizzleJobStore.js";
|
|
12
|
+
/**
|
|
13
|
+
* Drizzle table factories — re-export from your schema for drizzle-kit
|
|
14
|
+
* migrations and typed queries.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.1.0
|
|
17
|
+
*/
|
|
18
|
+
export * from "./schema.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/drizzle/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;;;;GAKG;AACH,cAAc,aAAa,CAAA"}
|