@zmdb/jobs-postgres 1.0.0-beta.1
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 +674 -0
- package/README.md +52 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +444 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
- package/src/index.ts +564 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @zmdb/jobs-postgres
|
|
2
|
+
|
|
3
|
+
`@zmdb/jobs-postgres` adapts a caller-owned node-postgres `Pool`, `PoolClient`, or `Client` to the `JobStore` port from `@zmdb/jobs`.
|
|
4
|
+
|
|
5
|
+
The caller retains ownership of the supplied PostgreSQL pool or client. Apply `jobsPostgresMigrations` explicitly before use. `store.close({ graceMs })` stops admission and drains or cancels
|
|
6
|
+
operations under a bounded deadline; only internally acquired pool connections are released.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
yarn add @zmdb/jobs@1.0.0-beta.1 @zmdb/jobs-postgres@1.0.0-beta.1 pg@^8.23.0
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
> **Prerelease** (`1.0.0-beta.1`). Requires **Node.js 26+** and is **ESM-only**. Ships built ESM `.js` + `.d.ts` under `./dist`.
|
|
15
|
+
|
|
16
|
+
The required peers are `@zmdb/jobs@1.0.0-beta.1` and `pg@^8.23.0`. Neither jobs, pg nor this adapter is installed by `yarn add zmdb@1.0.0-beta.1`. Portable jobs owns queues, workers, retries and
|
|
17
|
+
scheduling; the provider owns its fresh schema.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { Pool } from 'pg';
|
|
23
|
+
import { createPgJobStore } from '@zmdb/jobs-postgres';
|
|
24
|
+
|
|
25
|
+
const connectionString = process.env.DATABASE_URL;
|
|
26
|
+
if (connectionString === undefined) throw new Error('DATABASE_URL is required');
|
|
27
|
+
|
|
28
|
+
const pool = new Pool({ connectionString });
|
|
29
|
+
const store = createPgJobStore(pool, {
|
|
30
|
+
prepared: true,
|
|
31
|
+
maxCacheSize: 128,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Pass store to createQueue/createWorker. The application still owns pool.
|
|
35
|
+
void store;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`prepared` and `maxCacheSize` preserve the bounded prepared-statement behavior of the zmdb PostgreSQL driver. `cancelVia` may name a caller-owned client that can cancel work through a second
|
|
39
|
+
connection. For the borrowed pool or client, the adapter never calls `end()` or `release()`; the caller performs that shutdown after workers have drained. Internally acquired pool clients are released
|
|
40
|
+
after their operations finish or are cancelled.
|
|
41
|
+
|
|
42
|
+
## Entry points
|
|
43
|
+
|
|
44
|
+
- `@zmdb/jobs-postgres` — `createPgJobStore`, `pgJobEnqueuer`, `jobsPostgresMigrations`, `PgJobClient`, `PgJobTransactionClient`, `PgJobStore`, and `PgJobStoreOptions`.
|
|
45
|
+
|
|
46
|
+
## Documentation
|
|
47
|
+
|
|
48
|
+
Full docs: **https://ambasta.github.io/zmdb/**
|
|
49
|
+
|
|
50
|
+
## License
|
|
51
|
+
|
|
52
|
+
GNU General Public License v3.0 or later (GPL-3.0-or-later) — see [LICENSE](./LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JobEnqueuer, JobStore, JobStoreMigration, JobStoreResource, LeaseStore } from '@zmdb/jobs';
|
|
2
|
+
import type { Client, Pool, PoolClient } from 'pg';
|
|
3
|
+
export type PgJobClient = Pool | PoolClient | Client;
|
|
4
|
+
export type PgJobTransactionClient = PoolClient | Client;
|
|
5
|
+
export interface PgJobStore extends JobStore, LeaseStore, JobStoreResource {
|
|
6
|
+
}
|
|
7
|
+
export interface PgJobStoreOptions {
|
|
8
|
+
readonly prepared?: boolean;
|
|
9
|
+
readonly maxCacheSize?: number;
|
|
10
|
+
readonly cancelVia?: PgJobClient;
|
|
11
|
+
readonly signal?: AbortSignal;
|
|
12
|
+
readonly operationTimeoutMs?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare const jobsPostgresMigrations: readonly JobStoreMigration[];
|
|
15
|
+
export declare function createPgJobStore(client: PgJobClient, options?: PgJobStoreOptions): PgJobStore;
|
|
16
|
+
export declare function pgJobEnqueuer(client: PgJobTransactionClient, options?: PgJobStoreOptions): JobEnqueuer;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAMV,WAAW,EAGX,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEnD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,MAAM,CAAC;AACzD,MAAM,WAAW,UAAW,SAAQ,QAAQ,EAAE,UAAU,EAAE,gBAAgB;CAAG;AAC7E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,eAAO,MAAM,sBAAsB,EAAE,SAAS,iBAAiB,EA0B7D,CAAC;AAifH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAE7F;AACD,wBAAgB,aAAa,CAAC,MAAM,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,WAAW,CAStG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import { postgresDriver } from '@zmdb/postgres';
|
|
2
|
+
export const jobsPostgresMigrations = Object.freeze([
|
|
3
|
+
Object.freeze({
|
|
4
|
+
version: 20260906000100,
|
|
5
|
+
name: 'jobs_queue',
|
|
6
|
+
up: `CREATE TABLE zmdb_job (
|
|
7
|
+
id TEXT PRIMARY KEY NOT NULL, name TEXT NOT NULL, payload TEXT NOT NULL,
|
|
8
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'done', 'dead')),
|
|
9
|
+
attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts BETWEEN 0 AND 2147483647),
|
|
10
|
+
enqueued_at TIMESTAMPTZ NOT NULL, dedupe_key TEXT UNIQUE,
|
|
11
|
+
lease_owner TEXT NOT NULL DEFAULT '', lease_until TIMESTAMPTZ NOT NULL DEFAULT '1970-01-01T00:00:00.000Z',
|
|
12
|
+
last_error TEXT, dead_reason TEXT CHECK (dead_reason IN ('invalid-payload', 'unknown-name', 'attempts-exhausted')),
|
|
13
|
+
dead_detail TEXT, dead_at TIMESTAMPTZ
|
|
14
|
+
);
|
|
15
|
+
CREATE TABLE zmdb_job_done (key TEXT PRIMARY KEY NOT NULL, completed_at TIMESTAMPTZ NOT NULL);
|
|
16
|
+
CREATE INDEX zmdb_job_pending ON zmdb_job(status, lease_until, enqueued_at) WHERE status = 'pending';
|
|
17
|
+
CREATE INDEX zmdb_job_lease_expiry ON zmdb_job(lease_until) WHERE status = 'pending';
|
|
18
|
+
CREATE INDEX zmdb_job_dead ON zmdb_job(dead_at) WHERE status = 'dead';`,
|
|
19
|
+
down: 'DROP INDEX zmdb_job_dead; DROP INDEX zmdb_job_lease_expiry; DROP INDEX zmdb_job_pending; DROP TABLE zmdb_job_done; DROP TABLE zmdb_job;',
|
|
20
|
+
}),
|
|
21
|
+
Object.freeze({
|
|
22
|
+
version: 20260906000200,
|
|
23
|
+
name: 'jobs_schedule_lease',
|
|
24
|
+
up: `CREATE TABLE zmdb_job_lease (key TEXT PRIMARY KEY NOT NULL, holder TEXT NOT NULL CHECK (holder <> ''), expires_at TIMESTAMPTZ NOT NULL);
|
|
25
|
+
CREATE INDEX zmdb_job_schedule_expiry ON zmdb_job_lease(expires_at);`,
|
|
26
|
+
down: 'DROP INDEX zmdb_job_schedule_expiry; DROP TABLE zmdb_job_lease;',
|
|
27
|
+
}),
|
|
28
|
+
]);
|
|
29
|
+
const MAX_INTEGER = 2_147_483_647;
|
|
30
|
+
function integer(name, value, minimum, maximum = MAX_INTEGER) {
|
|
31
|
+
if (!Number.isSafeInteger(value) || value < minimum || value > maximum)
|
|
32
|
+
throw new RangeError(`${name} must be an integer in [${minimum}, ${maximum}]`);
|
|
33
|
+
}
|
|
34
|
+
function string(name, value, empty = false) {
|
|
35
|
+
if (typeof value !== 'string' || (!empty && value.length === 0) || value.includes('\0') || !value.isWellFormed()) {
|
|
36
|
+
throw new TypeError(`${name} must be ${empty ? '' : 'nonempty '}Unicode text without NUL`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function timestamp(value) {
|
|
40
|
+
if (!(value instanceof Date) ||
|
|
41
|
+
!Number.isFinite(value.getTime()) ||
|
|
42
|
+
value.getTime() < -62_135_596_800_000 ||
|
|
43
|
+
value.getTime() > 253_402_300_799_999)
|
|
44
|
+
throw new RangeError('timestamp must be a finite Date between years 0001 and 9999');
|
|
45
|
+
return value.toISOString();
|
|
46
|
+
}
|
|
47
|
+
function reason(value) {
|
|
48
|
+
if (value === 'invalid-payload' || value === 'unknown-name' || value === 'attempts-exhausted')
|
|
49
|
+
return value;
|
|
50
|
+
throw new TypeError('unknown dead-letter reason');
|
|
51
|
+
}
|
|
52
|
+
function text(row, key) {
|
|
53
|
+
const value = row[key];
|
|
54
|
+
if (typeof value !== 'string')
|
|
55
|
+
throw new TypeError(`zmdb_job.${key} must be text`);
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
function count(row) {
|
|
59
|
+
const value = row['attempts'];
|
|
60
|
+
if (typeof value !== 'number')
|
|
61
|
+
throw new TypeError('zmdb_job.attempts must be a number');
|
|
62
|
+
integer('attempts', value, 0);
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
function candidate(row) {
|
|
66
|
+
return { id: text(row, 'id'), name: text(row, 'name'), enqueuedAt: date(row, 'enqueued_at') };
|
|
67
|
+
}
|
|
68
|
+
function claimed(row) {
|
|
69
|
+
return {
|
|
70
|
+
...candidate(row),
|
|
71
|
+
payload: text(row, 'payload'),
|
|
72
|
+
attempts: count(row),
|
|
73
|
+
holder: text(row, 'lease_owner'),
|
|
74
|
+
...(row['dedupe_key'] === null ? {} : { dedupeKey: text(row, 'dedupe_key') }),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function date(row, key) {
|
|
78
|
+
const value = row[key];
|
|
79
|
+
return value instanceof Date ? value : new Date(text(row, key));
|
|
80
|
+
}
|
|
81
|
+
async function enqueue(rows, job) {
|
|
82
|
+
string('id', job.id);
|
|
83
|
+
string('name', job.name);
|
|
84
|
+
string('payload', job.payload, true);
|
|
85
|
+
if (job.dedupeKey !== undefined)
|
|
86
|
+
string('dedupeKey', job.dedupeKey);
|
|
87
|
+
const enqueuedAt = timestamp(job.enqueuedAt), availableAt = timestamp(job.availableAt);
|
|
88
|
+
const inserted = await rows(`INSERT INTO zmdb_job (id, name, payload, enqueued_at, dedupe_key, lease_until)
|
|
89
|
+
VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT(dedupe_key) DO NOTHING RETURNING id`, [job.id, job.name, job.payload, enqueuedAt, job.dedupeKey ?? null, availableAt]);
|
|
90
|
+
if (inserted.length > 0)
|
|
91
|
+
return { kind: 'inserted', jobId: job.id };
|
|
92
|
+
const existing = (await rows('SELECT id FROM zmdb_job WHERE dedupe_key = $1', [job.dedupeKey]))[0];
|
|
93
|
+
if (existing === undefined)
|
|
94
|
+
throw new Error('@zmdb/jobs-postgres: dedupe row is missing');
|
|
95
|
+
return { kind: 'duplicate', jobId: text(existing, 'id') };
|
|
96
|
+
}
|
|
97
|
+
function isPool(client) {
|
|
98
|
+
return 'totalCount' in client && 'idleCount' in client;
|
|
99
|
+
}
|
|
100
|
+
const connectionTails = new WeakMap();
|
|
101
|
+
const preparedStates = new WeakMap();
|
|
102
|
+
function preparedConnection(connection, options, signal) {
|
|
103
|
+
return {
|
|
104
|
+
async query(query, parameters) {
|
|
105
|
+
signal.throwIfAborted();
|
|
106
|
+
if (typeof query !== 'string')
|
|
107
|
+
return connection.query({ ...query, values: [...(query.values ?? [])] });
|
|
108
|
+
if (!options.prepared || query === 'SELECT pg_backend_pid() AS pid')
|
|
109
|
+
return connection.query(query, [...(parameters ?? [])]);
|
|
110
|
+
let state = preparedStates.get(connection);
|
|
111
|
+
if (state === undefined) {
|
|
112
|
+
state = {
|
|
113
|
+
names: new Map(),
|
|
114
|
+
sequence: 0,
|
|
115
|
+
namespace: `zmdb_jobs_${globalThis.crypto.randomUUID().replaceAll('-', '')}`,
|
|
116
|
+
};
|
|
117
|
+
preparedStates.set(connection, state);
|
|
118
|
+
}
|
|
119
|
+
const maximum = options.maxCacheSize ?? 1000;
|
|
120
|
+
let name = state.names.get(query);
|
|
121
|
+
const desired = maximum - (maximum > 0 && name === undefined ? 1 : 0);
|
|
122
|
+
while (state.names.size > desired) {
|
|
123
|
+
const oldest = [...state.names.entries()].find(([sql]) => maximum === 0 || sql !== query);
|
|
124
|
+
if (oldest === undefined)
|
|
125
|
+
break;
|
|
126
|
+
const present = await connection.query('SELECT name FROM pg_prepared_statements WHERE name = $1', [oldest[1]]);
|
|
127
|
+
signal.throwIfAborted();
|
|
128
|
+
if (present.rows.length > 0)
|
|
129
|
+
await connection.query(`DEALLOCATE ${oldest[1]}`);
|
|
130
|
+
state.names.delete(oldest[0]);
|
|
131
|
+
signal.throwIfAborted();
|
|
132
|
+
}
|
|
133
|
+
if (maximum === 0) {
|
|
134
|
+
signal.throwIfAborted();
|
|
135
|
+
const unnamed = { queryMode: 'extended', text: query, values: [...(parameters ?? [])] };
|
|
136
|
+
return connection.query(unnamed);
|
|
137
|
+
}
|
|
138
|
+
name ??= `${state.namespace}_${(state.sequence++).toString(36)}`;
|
|
139
|
+
state.names.delete(query);
|
|
140
|
+
state.names.set(query, name);
|
|
141
|
+
return connection.query({ name, text: query, values: [...(parameters ?? [])] });
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
class Operations {
|
|
146
|
+
#client;
|
|
147
|
+
#options;
|
|
148
|
+
#timeoutMs;
|
|
149
|
+
#shutdown = new AbortController();
|
|
150
|
+
#active = new Set();
|
|
151
|
+
#cleanupErrors = [];
|
|
152
|
+
#closed = false;
|
|
153
|
+
#closing;
|
|
154
|
+
constructor(client, options) {
|
|
155
|
+
this.#client = client;
|
|
156
|
+
this.#options = options ?? {};
|
|
157
|
+
this.#timeoutMs = options?.operationTimeoutMs ?? 30_000;
|
|
158
|
+
integer('operationTimeoutMs', this.#timeoutMs, 1);
|
|
159
|
+
if (options?.maxCacheSize !== undefined)
|
|
160
|
+
integer('maxCacheSize', options.maxCacheSize, 0, Number.MAX_SAFE_INTEGER);
|
|
161
|
+
}
|
|
162
|
+
run(transaction, body) {
|
|
163
|
+
if (this.#closed)
|
|
164
|
+
return Promise.reject(new Error('@zmdb/jobs-postgres: store is closed'));
|
|
165
|
+
if (this.#options.signal?.aborted)
|
|
166
|
+
return Promise.reject(this.#options.signal.reason);
|
|
167
|
+
const deadline = new AbortController();
|
|
168
|
+
const signal = AbortSignal.any([
|
|
169
|
+
deadline.signal,
|
|
170
|
+
this.#shutdown.signal,
|
|
171
|
+
...(this.#options.signal === undefined ? [] : [this.#options.signal]),
|
|
172
|
+
]);
|
|
173
|
+
const timer = setTimeout(() => deadline.abort(new DOMException('@zmdb/jobs-postgres: operation deadline exceeded; database outcome may be incomplete', 'TimeoutError')), this.#timeoutMs);
|
|
174
|
+
const client = this.#client;
|
|
175
|
+
const previous = isPool(client) ? undefined : connectionTails.get(client);
|
|
176
|
+
const actual = Promise.resolve().then(async () => {
|
|
177
|
+
if (previous !== undefined)
|
|
178
|
+
await previous;
|
|
179
|
+
signal.throwIfAborted();
|
|
180
|
+
let connection;
|
|
181
|
+
let acquired = false, began = false, failed = false;
|
|
182
|
+
let rollbackError;
|
|
183
|
+
let failure;
|
|
184
|
+
let result;
|
|
185
|
+
try {
|
|
186
|
+
if (isPool(client)) {
|
|
187
|
+
connection = await client.connect();
|
|
188
|
+
acquired = true;
|
|
189
|
+
}
|
|
190
|
+
else
|
|
191
|
+
connection = client;
|
|
192
|
+
signal.throwIfAborted();
|
|
193
|
+
const selected = postgresDriver(preparedConnection(connection, this.#options, signal), this.#options.cancelVia === undefined ? {} : { cancelVia: this.#options.cancelVia });
|
|
194
|
+
const rows = (sql, parameters = []) => selected.execute({ text: sql, parameters }, { signal });
|
|
195
|
+
if (transaction) {
|
|
196
|
+
await connection.query('BEGIN');
|
|
197
|
+
began = true;
|
|
198
|
+
}
|
|
199
|
+
signal.throwIfAborted();
|
|
200
|
+
result = { value: await body(rows) };
|
|
201
|
+
signal.throwIfAborted();
|
|
202
|
+
if (began) {
|
|
203
|
+
await connection.query('COMMIT');
|
|
204
|
+
began = false;
|
|
205
|
+
}
|
|
206
|
+
signal.throwIfAborted();
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
failed = true;
|
|
210
|
+
failure = error;
|
|
211
|
+
if (began && connection !== undefined) {
|
|
212
|
+
try {
|
|
213
|
+
await connection.query('ROLLBACK');
|
|
214
|
+
}
|
|
215
|
+
catch (rollback) {
|
|
216
|
+
failure = new AggregateError([error, rollback], '@zmdb/jobs-postgres: rollback failed');
|
|
217
|
+
rollbackError =
|
|
218
|
+
rollback instanceof Error
|
|
219
|
+
? rollback
|
|
220
|
+
: new Error('@zmdb/jobs-postgres: rollback failed', { cause: rollback });
|
|
221
|
+
if (signal.aborted)
|
|
222
|
+
this.#cleanupErrors.push(rollback);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
if (acquired && connection !== undefined && 'release' in connection) {
|
|
228
|
+
try {
|
|
229
|
+
connection.release(rollbackError);
|
|
230
|
+
}
|
|
231
|
+
catch (release) {
|
|
232
|
+
failure = failed ? new AggregateError([failure, release], '@zmdb/jobs-postgres: release failed') : release;
|
|
233
|
+
failed = true;
|
|
234
|
+
this.#cleanupErrors.push(release);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (failed)
|
|
239
|
+
throw failure;
|
|
240
|
+
if (result === undefined)
|
|
241
|
+
throw new Error('@zmdb/jobs-postgres: operation did not produce a result');
|
|
242
|
+
return result.value;
|
|
243
|
+
});
|
|
244
|
+
// The serial slot belongs to actual SQL and cleanup, even after the caller's deadline expires.
|
|
245
|
+
if (!isPool(client))
|
|
246
|
+
connectionTails.set(client, actual.then(() => undefined, () => undefined));
|
|
247
|
+
this.#active.add(actual);
|
|
248
|
+
let onAbort = () => undefined;
|
|
249
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
250
|
+
onAbort = () => reject(signal.reason);
|
|
251
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
252
|
+
if (signal.aborted)
|
|
253
|
+
onAbort();
|
|
254
|
+
});
|
|
255
|
+
void actual.then(() => this.#finished(actual, timer, signal, onAbort), () => this.#finished(actual, timer, signal, onAbort));
|
|
256
|
+
return Promise.race([actual, aborted]);
|
|
257
|
+
}
|
|
258
|
+
#finished(actual, timer, signal, onAbort) {
|
|
259
|
+
clearTimeout(timer);
|
|
260
|
+
signal.removeEventListener('abort', onAbort);
|
|
261
|
+
this.#active.delete(actual);
|
|
262
|
+
}
|
|
263
|
+
close(options) {
|
|
264
|
+
if (options !== undefined)
|
|
265
|
+
integer('graceMs', options.graceMs, 0);
|
|
266
|
+
if (this.#closing !== undefined)
|
|
267
|
+
return this.#closing;
|
|
268
|
+
this.#closed = true;
|
|
269
|
+
this.#shutdown.abort(new DOMException('@zmdb/jobs-postgres: store is closed', 'AbortError'));
|
|
270
|
+
const graceMs = Math.min(options?.graceMs ?? this.#timeoutMs, this.#timeoutMs);
|
|
271
|
+
this.#closing = this.#drain(graceMs);
|
|
272
|
+
return this.#closing;
|
|
273
|
+
}
|
|
274
|
+
async #drain(graceMs) {
|
|
275
|
+
let timer;
|
|
276
|
+
try {
|
|
277
|
+
await Promise.race([
|
|
278
|
+
Promise.allSettled(this.#active),
|
|
279
|
+
new Promise((_resolve, reject) => {
|
|
280
|
+
timer = setTimeout(() => reject(new DOMException('@zmdb/jobs-postgres: shutdown deadline exceeded; cleanup incomplete', 'TimeoutError')), graceMs);
|
|
281
|
+
}),
|
|
282
|
+
]);
|
|
283
|
+
if (this.#cleanupErrors.length === 1)
|
|
284
|
+
throw this.#cleanupErrors[0];
|
|
285
|
+
if (this.#cleanupErrors.length > 1)
|
|
286
|
+
throw new AggregateError(this.#cleanupErrors, '@zmdb/jobs-postgres: cleanup failed');
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
clearTimeout(timer);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function validateEnqueue(job) {
|
|
294
|
+
string('id', job.id);
|
|
295
|
+
string('name', job.name);
|
|
296
|
+
string('payload', job.payload, true);
|
|
297
|
+
if (job.dedupeKey !== undefined)
|
|
298
|
+
string('dedupeKey', job.dedupeKey);
|
|
299
|
+
timestamp(job.enqueuedAt);
|
|
300
|
+
timestamp(job.availableAt);
|
|
301
|
+
}
|
|
302
|
+
class PgStore {
|
|
303
|
+
#operations;
|
|
304
|
+
constructor(client, options) {
|
|
305
|
+
this.#operations = new Operations(client, options);
|
|
306
|
+
}
|
|
307
|
+
async enqueue(job) {
|
|
308
|
+
validateEnqueue(job);
|
|
309
|
+
return this.#operations.run(true, rows => enqueue(rows, job));
|
|
310
|
+
}
|
|
311
|
+
async candidates(options) {
|
|
312
|
+
integer('limit', options.limit, 1);
|
|
313
|
+
const now = timestamp(options.now);
|
|
314
|
+
return this.#operations.run(true, async (rows) => (await rows('SELECT id, name, enqueued_at FROM zmdb_job WHERE status = \'pending\' AND lease_until <= $1 ORDER BY enqueued_at, id COLLATE "C" LIMIT $2', [now, options.limit])).map(candidate));
|
|
315
|
+
}
|
|
316
|
+
async claim(options) {
|
|
317
|
+
string('holder', options.holder);
|
|
318
|
+
const now = timestamp(options.now), until = timestamp(options.leaseUntil);
|
|
319
|
+
if (options.leaseUntil.getTime() <= options.now.getTime())
|
|
320
|
+
throw new RangeError('leaseUntil must be later than now');
|
|
321
|
+
for (const id of options.ids)
|
|
322
|
+
string('id', id);
|
|
323
|
+
const ids = [...new Set(options.ids)];
|
|
324
|
+
return this.#operations.run(true, async (rows) => {
|
|
325
|
+
if (ids.length === 0)
|
|
326
|
+
return [];
|
|
327
|
+
return (await rows(`WITH claimed AS (
|
|
328
|
+
UPDATE zmdb_job SET lease_owner = $1, lease_until = $2
|
|
329
|
+
WHERE id = ANY($3::text[]) AND status = 'pending' AND lease_until <= $4 RETURNING *
|
|
330
|
+
) SELECT * FROM claimed ORDER BY enqueued_at, id COLLATE "C"`, [options.holder, until, ids, now])).map(claimed);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
async completed(key) {
|
|
334
|
+
string('key', key);
|
|
335
|
+
return this.#operations.run(true, async (rows) => (await rows('SELECT key FROM zmdb_job_done WHERE key = $1', [key])).length > 0);
|
|
336
|
+
}
|
|
337
|
+
async settle(settlement) {
|
|
338
|
+
string('jobId', settlement.jobId);
|
|
339
|
+
string('holder', settlement.holder);
|
|
340
|
+
let sql, parameters;
|
|
341
|
+
switch (settlement.kind) {
|
|
342
|
+
case 'done':
|
|
343
|
+
string('idempotencyKey', settlement.idempotencyKey);
|
|
344
|
+
sql =
|
|
345
|
+
"UPDATE zmdb_job SET status = 'done', attempts = attempts + 1, lease_owner = '', lease_until = $1, last_error = NULL, dead_reason = NULL, dead_detail = NULL, dead_at = NULL";
|
|
346
|
+
parameters = [timestamp(settlement.completedAt)];
|
|
347
|
+
break;
|
|
348
|
+
case 'retry':
|
|
349
|
+
integer('attempts', settlement.attempts, 0);
|
|
350
|
+
string('detail', settlement.detail, true);
|
|
351
|
+
sql =
|
|
352
|
+
"UPDATE zmdb_job SET attempts = $1, lease_owner = '', lease_until = $2, last_error = $3, dead_reason = NULL, dead_detail = NULL, dead_at = NULL";
|
|
353
|
+
parameters = [settlement.attempts, timestamp(settlement.availableAt), settlement.detail];
|
|
354
|
+
break;
|
|
355
|
+
case 'dead':
|
|
356
|
+
integer('attempts', settlement.attempts, 0);
|
|
357
|
+
string('detail', settlement.detail, true);
|
|
358
|
+
reason(settlement.reason);
|
|
359
|
+
sql =
|
|
360
|
+
"UPDATE zmdb_job SET status = 'dead', attempts = $1, lease_owner = '', lease_until = $2, last_error = $3, dead_reason = $4, dead_detail = $5, dead_at = $6";
|
|
361
|
+
parameters = [
|
|
362
|
+
settlement.attempts,
|
|
363
|
+
timestamp(settlement.deadAt),
|
|
364
|
+
settlement.detail,
|
|
365
|
+
settlement.reason,
|
|
366
|
+
settlement.detail,
|
|
367
|
+
timestamp(settlement.deadAt),
|
|
368
|
+
];
|
|
369
|
+
break;
|
|
370
|
+
case 'release':
|
|
371
|
+
sql = "UPDATE zmdb_job SET lease_owner = '', lease_until = $1";
|
|
372
|
+
parameters = [timestamp(settlement.availableAt)];
|
|
373
|
+
break;
|
|
374
|
+
default:
|
|
375
|
+
throw new TypeError('unknown job settlement');
|
|
376
|
+
}
|
|
377
|
+
const fence = ` WHERE id = $${parameters.length + 1} AND lease_owner = $${parameters.length + 2} AND lease_owner <> '' AND status = 'pending' RETURNING id`;
|
|
378
|
+
return this.#operations.run(true, async (rows) => {
|
|
379
|
+
const changed = (await rows(sql + fence, [...parameters, settlement.jobId, settlement.holder])).length > 0;
|
|
380
|
+
if (changed && settlement.kind === 'done')
|
|
381
|
+
await rows('INSERT INTO zmdb_job_done (key, completed_at) VALUES ($1, $2) ON CONFLICT(key) DO NOTHING RETURNING key', [settlement.idempotencyKey, timestamp(settlement.completedAt)]);
|
|
382
|
+
return changed;
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
async listDead(options) {
|
|
386
|
+
integer('limit', options.limit, 1);
|
|
387
|
+
if (options.reason !== undefined)
|
|
388
|
+
reason(options.reason);
|
|
389
|
+
return this.#operations.run(true, async (rows) => (await rows(`SELECT * FROM zmdb_job WHERE status = 'dead'${options.reason === undefined ? '' : ' AND dead_reason = $2'} ORDER BY dead_at DESC, id COLLATE "C" LIMIT $1`, options.reason === undefined ? [options.limit] : [options.limit, options.reason])).map(row => ({
|
|
390
|
+
jobId: text(row, 'id'),
|
|
391
|
+
name: text(row, 'name'),
|
|
392
|
+
payload: text(row, 'payload'),
|
|
393
|
+
attempts: count(row),
|
|
394
|
+
reason: reason(row['dead_reason']),
|
|
395
|
+
detail: text(row, 'dead_detail'),
|
|
396
|
+
enqueuedAt: date(row, 'enqueued_at'),
|
|
397
|
+
deadAt: date(row, 'dead_at'),
|
|
398
|
+
})));
|
|
399
|
+
}
|
|
400
|
+
async replay(jobId, availableAt) {
|
|
401
|
+
string('jobId', jobId);
|
|
402
|
+
const available = timestamp(availableAt);
|
|
403
|
+
return this.#operations.run(true, async (rows) => (await rows("UPDATE zmdb_job SET status = 'pending', attempts = 0, lease_owner = '', lease_until = $1, last_error = NULL, dead_reason = NULL, dead_detail = NULL, dead_at = NULL WHERE id = $2 AND status = 'dead' RETURNING id", [available, jobId])).length > 0);
|
|
404
|
+
}
|
|
405
|
+
async acquire(key, holder, ttlMs) {
|
|
406
|
+
string('key', key);
|
|
407
|
+
string('holder', holder);
|
|
408
|
+
integer('ttlMs', ttlMs, 1);
|
|
409
|
+
const now = Date.now();
|
|
410
|
+
return this.#operations.run(true, async (rows) => (await rows(`INSERT INTO zmdb_job_lease (key, holder, expires_at) VALUES ($1, $2, $3)
|
|
411
|
+
ON CONFLICT(key) DO UPDATE SET holder = excluded.holder, expires_at = excluded.expires_at
|
|
412
|
+
WHERE zmdb_job_lease.holder = excluded.holder OR zmdb_job_lease.expires_at <= $4 RETURNING key`, [key, holder, timestamp(new Date(now + ttlMs)), timestamp(new Date(now))])).length > 0);
|
|
413
|
+
}
|
|
414
|
+
async renew(key, holder, ttlMs) {
|
|
415
|
+
string('key', key);
|
|
416
|
+
string('holder', holder);
|
|
417
|
+
integer('ttlMs', ttlMs, 1);
|
|
418
|
+
const now = Date.now();
|
|
419
|
+
return this.#operations.run(true, async (rows) => (await rows('UPDATE zmdb_job_lease SET expires_at = $1 WHERE key = $2 AND holder = $3 AND expires_at > $4 RETURNING key', [timestamp(new Date(now + ttlMs)), key, holder, timestamp(new Date(now))])).length > 0);
|
|
420
|
+
}
|
|
421
|
+
async release(key, holder) {
|
|
422
|
+
string('key', key);
|
|
423
|
+
string('holder', holder);
|
|
424
|
+
await this.#operations.run(true, rows => rows('DELETE FROM zmdb_job_lease WHERE key = $1 AND holder = $2 RETURNING key', [key, holder]));
|
|
425
|
+
}
|
|
426
|
+
close(options) {
|
|
427
|
+
return this.#operations.close(options);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
export function createPgJobStore(client, options) {
|
|
431
|
+
return new PgStore(client, options);
|
|
432
|
+
}
|
|
433
|
+
export function pgJobEnqueuer(client, options) {
|
|
434
|
+
if (isPool(client))
|
|
435
|
+
throw new TypeError('@zmdb/jobs-postgres: transaction enqueue requires a pinned client');
|
|
436
|
+
const operations = new Operations(client, options);
|
|
437
|
+
return {
|
|
438
|
+
async enqueue(job) {
|
|
439
|
+
validateEnqueue(job);
|
|
440
|
+
return operations.run(false, rows => enqueue(rows, job));
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zmdb/jobs-postgres",
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
|
+
"description": "node-postgres JobStore adapter for caller-owned PostgreSQL pools and clients.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"adapter",
|
|
7
|
+
"jobs",
|
|
8
|
+
"pg",
|
|
9
|
+
"postgres",
|
|
10
|
+
"queue",
|
|
11
|
+
"typescript",
|
|
12
|
+
"zmdb"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/ambasta/zmdb#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/ambasta/zmdb/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "GPL-3.0-or-later",
|
|
19
|
+
"author": "zmdb contributors",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/ambasta/zmdb.git",
|
|
23
|
+
"directory": "packages/jobs-postgres"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public",
|
|
35
|
+
"tag": "beta"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "node ../../scripts/build-package.mjs",
|
|
39
|
+
"test": "vitest run"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@zmdb/postgres": "1.0.0-beta.1"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@zmdb/jobs": "1.0.0-beta.1",
|
|
46
|
+
"pg": "^8.23.0"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=26"
|
|
50
|
+
},
|
|
51
|
+
"main": "./dist/index.js",
|
|
52
|
+
"types": "./dist/index.d.ts"
|
|
53
|
+
}
|