@workglow/supabase 0.2.37 → 0.3.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/dist/job-queue/SupabaseJobStore.d.ts +14 -1
- package/dist/job-queue/SupabaseJobStore.d.ts.map +1 -1
- package/dist/job-queue/SupabaseQueueStorage.d.ts +37 -0
- package/dist/job-queue/SupabaseQueueStorage.d.ts.map +1 -1
- package/dist/job-queue/browser.js +118 -4
- package/dist/job-queue/browser.js.map +4 -4
- package/dist/job-queue/node.js +118 -4
- package/dist/job-queue/node.js.map +4 -4
- package/package.json +8 -8
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Copyright 2026 Steven Roussey <sroussey@gmail.com>
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import type { IJobStore, JobRecord, JobStatus, MessageId } from "@workglow/job-queue";
|
|
6
|
+
import type { IJobStore, JobRecord, JobStatus, JobStorageFormat, MessageId, SendOptions } from "@workglow/job-queue";
|
|
7
7
|
import type { SupabasePendingWrite } from "./SupabaseMessageQueue";
|
|
8
8
|
import type { SupabaseQueueStorage } from "./SupabaseQueueStorage";
|
|
9
9
|
export declare class SupabaseJobStore<Input, Output> implements IJobStore<Input, Output> {
|
|
@@ -25,5 +25,18 @@ export declare class SupabaseJobStore<Input, Output> implements IJobStore<Input,
|
|
|
25
25
|
deleteAll(): Promise<void>;
|
|
26
26
|
abort(id: MessageId): Promise<void>;
|
|
27
27
|
saveStatus(id: MessageId, status: JobStatus): Promise<void>;
|
|
28
|
+
create(body: JobStorageFormat<Input, Output>, opts: SendOptions): Promise<MessageId>;
|
|
29
|
+
findActiveByFingerprint(fingerprint: string, queueName: string): Promise<JobRecord<Input, Output> | undefined>;
|
|
30
|
+
getMany(ids: readonly MessageId[]): Promise<readonly (JobRecord<Input, Output> | undefined)[]>;
|
|
31
|
+
completeWithResult(id: MessageId, result: Output): Promise<void>;
|
|
32
|
+
failWithError(id: MessageId, opts: {
|
|
33
|
+
readonly error?: string | null;
|
|
34
|
+
readonly errorCode?: string | null;
|
|
35
|
+
readonly abortRequested?: boolean;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
markEnqueueDeferred(id: MessageId, opts: {
|
|
38
|
+
readonly visible_at: Date;
|
|
39
|
+
readonly errorCode: string;
|
|
40
|
+
}): Promise<void>;
|
|
28
41
|
}
|
|
29
42
|
//# sourceMappingURL=SupabaseJobStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SupabaseJobStore.d.ts","sourceRoot":"","sources":["../../src/job-queue/SupabaseJobStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"SupabaseJobStore.d.ts","sourceRoot":"","sources":["../../src/job-queue/SupabaseJobStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -117,6 +117,12 @@ export declare class SupabaseQueueStorage<Input, Output> implements IQueueStorag
|
|
|
117
117
|
* @returns The count of jobs with the specified status
|
|
118
118
|
*/
|
|
119
119
|
size(status?: "PENDING"): Promise<number>;
|
|
120
|
+
/**
|
|
121
|
+
* Gets all jobs from the queue that match the current prefix values.
|
|
122
|
+
* Used internally for polling-based subscriptions.
|
|
123
|
+
*
|
|
124
|
+
* @returns An array of jobs
|
|
125
|
+
*/
|
|
120
126
|
private getAllJobs;
|
|
121
127
|
/**
|
|
122
128
|
* Marks a job as complete with its output or error.
|
|
@@ -145,6 +151,7 @@ export declare class SupabaseQueueStorage<Input, Output> implements IQueueStorag
|
|
|
145
151
|
progress?: number;
|
|
146
152
|
progress_message?: string;
|
|
147
153
|
progress_details?: Record<string, any> | null;
|
|
154
|
+
visible_at?: string | null;
|
|
148
155
|
}): Promise<void>;
|
|
149
156
|
/**
|
|
150
157
|
* Clears all jobs from the queue.
|
|
@@ -179,6 +186,29 @@ export declare class SupabaseQueueStorage<Input, Output> implements IQueueStorag
|
|
|
179
186
|
* Deletes a job by its ID
|
|
180
187
|
*/
|
|
181
188
|
delete(jobId: unknown): Promise<void>;
|
|
189
|
+
/**
|
|
190
|
+
* Finds the most recent active (PENDING or PROCESSING) job with the given fingerprint in this queue.
|
|
191
|
+
* Uses the partial index idx_<table>_fingerprint_active for O(1) lookup.
|
|
192
|
+
*/
|
|
193
|
+
findActiveByFingerprint(fingerprint: string, queueName: string): Promise<JobStorageFormat<Input, Output> | undefined>;
|
|
194
|
+
/**
|
|
195
|
+
* Retrieves multiple jobs by their IDs in a single query.
|
|
196
|
+
* Returns results in the same order as the input ids array, with undefined for missing ids.
|
|
197
|
+
*/
|
|
198
|
+
getMany(ids: readonly unknown[]): Promise<Array<JobStorageFormat<Input, Output> | undefined>>;
|
|
199
|
+
/**
|
|
200
|
+
* Atomically writes output and sets status=COMPLETED.
|
|
201
|
+
*/
|
|
202
|
+
completeWithResult(id: unknown, result: Output): Promise<void>;
|
|
203
|
+
/**
|
|
204
|
+
* Atomically writes error fields and sets status=FAILED.
|
|
205
|
+
* Preserves existing error/error_code when opts fields are absent.
|
|
206
|
+
*/
|
|
207
|
+
failWithError(id: unknown, opts: {
|
|
208
|
+
readonly error?: string | null;
|
|
209
|
+
readonly errorCode?: string | null;
|
|
210
|
+
readonly abortRequested?: boolean;
|
|
211
|
+
}): Promise<void>;
|
|
182
212
|
/**
|
|
183
213
|
* Delete jobs with a specific status older than a cutoff date
|
|
184
214
|
* @param status - Status of jobs to delete
|
|
@@ -195,6 +225,13 @@ export declare class SupabaseQueueStorage<Input, Output> implements IQueueStorag
|
|
|
195
225
|
* Checks if a prefix filter is custom (different from instance's prefixes).
|
|
196
226
|
*/
|
|
197
227
|
private isCustomPrefixFilter;
|
|
228
|
+
/**
|
|
229
|
+
* Gets all jobs from the queue with a custom prefix filter.
|
|
230
|
+
* Used for subscriptions with custom prefix filters (filters at DB level).
|
|
231
|
+
*
|
|
232
|
+
* @param prefixFilter - The prefix values to filter by (empty object = all jobs)
|
|
233
|
+
* @returns A promise that resolves to an array of jobs
|
|
234
|
+
*/
|
|
198
235
|
private getAllJobsWithFilter;
|
|
199
236
|
/**
|
|
200
237
|
* Subscribes to changes in the queue.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SupabaseQueueStorage.d.ts","sourceRoot":"","sources":["../../src/job-queue/SupabaseQueueStorage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAElB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAmB,MAAM,qBAAqB,CAAC;AAIjE,eAAO,MAAM,sBAAsB,gEAElC,CAAC;AAEF;;;GAGG;AACH,qBAAa,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAE,YAAW,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC;IAepF,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM;IAdtC,SAAgB,KAAK,EAAG,SAAS,CAAU;IAC3C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAC1C,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IACrD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IAC3E,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IACrC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,cAAc,CAIN;IAEhB,YACE,MAAM,EAAE,cAAc,EACH,SAAS,EAAE,MAAM,EACpC,OAAO,CAAC,EAAE,mBAAmB,EAY9B;IAED;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAS7B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAQ7B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAqB3B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAyB;IAElE;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;;;;;;;;OASG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"SupabaseQueueStorage.d.ts","sourceRoot":"","sources":["../../src/job-queue/SupabaseQueueStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -140,7 +140,8 @@ class SupabaseQueueStorage {
|
|
|
140
140
|
const indexes = [
|
|
141
141
|
`CREATE INDEX IF NOT EXISTS job_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}id, status, visible_at)`,
|
|
142
142
|
`CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx ON ${this.tableName} (${prefixIndexPrefix}queue, status, visible_at)`,
|
|
143
|
-
`CREATE INDEX IF NOT EXISTS jobs_fingerprint${indexSuffix}_unique_idx ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status)
|
|
143
|
+
`CREATE INDEX IF NOT EXISTS jobs_fingerprint${indexSuffix}_unique_idx ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint, status)`,
|
|
144
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_${this.tableName}_fingerprint_active ON ${this.tableName} (${prefixIndexPrefix}queue, fingerprint) WHERE status IN ('PENDING','PROCESSING')`
|
|
144
145
|
];
|
|
145
146
|
for (const indexSql of indexes) {
|
|
146
147
|
await this.client.rpc("exec_sql", { query: indexSql });
|
|
@@ -153,7 +154,7 @@ class SupabaseQueueStorage {
|
|
|
153
154
|
const now = new Date().toISOString();
|
|
154
155
|
job.queue = this.queueName;
|
|
155
156
|
job.job_run_id = job.job_run_id ?? uuid4();
|
|
156
|
-
job.fingerprint = await makeFingerprint(job.input);
|
|
157
|
+
job.fingerprint = job.fingerprint ?? await makeFingerprint(job.input);
|
|
157
158
|
job.status = JobStatus.PENDING;
|
|
158
159
|
job.progress = 0;
|
|
159
160
|
job.progress_message = "";
|
|
@@ -175,8 +176,19 @@ class SupabaseQueueStorage {
|
|
|
175
176
|
progress_message: job.progress_message,
|
|
176
177
|
progress_details: job.progress_details
|
|
177
178
|
}).select("id").single();
|
|
178
|
-
if (error)
|
|
179
|
+
if (error) {
|
|
180
|
+
const e = error;
|
|
181
|
+
const isUniqueViolation = e?.code === "23505";
|
|
182
|
+
const involvesFingerprint = typeof e?.details === "string" && /fingerprint/i.test(e.details) || typeof e?.message === "string" && /fingerprint/i.test(e.message);
|
|
183
|
+
if (isUniqueViolation && involvesFingerprint && job.fingerprint) {
|
|
184
|
+
const winner = await this.findActiveByFingerprint(job.fingerprint, this.queueName);
|
|
185
|
+
if (winner?.id != null) {
|
|
186
|
+
job.id = winner.id;
|
|
187
|
+
return winner.id;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
179
190
|
throw error;
|
|
191
|
+
}
|
|
180
192
|
if (!data)
|
|
181
193
|
throw new Error("Failed to add to queue");
|
|
182
194
|
job.id = data.id;
|
|
@@ -417,6 +429,8 @@ class SupabaseQueueStorage {
|
|
|
417
429
|
patch.progress_message = fields.progress_message ?? "";
|
|
418
430
|
if ("progress_details" in fields)
|
|
419
431
|
patch.progress_details = fields.progress_details ?? null;
|
|
432
|
+
if ("visible_at" in fields)
|
|
433
|
+
patch.visible_at = fields.visible_at ?? null;
|
|
420
434
|
if (Object.keys(patch).length === 0)
|
|
421
435
|
return;
|
|
422
436
|
let query = this.client.from(this.tableName).update(patch).eq("id", id).eq("queue", this.queueName);
|
|
@@ -498,6 +512,76 @@ class SupabaseQueueStorage {
|
|
|
498
512
|
if (error)
|
|
499
513
|
throw error;
|
|
500
514
|
}
|
|
515
|
+
async findActiveByFingerprint(fingerprint, queueName) {
|
|
516
|
+
const prefixConditions = this.buildPrefixWhereSql();
|
|
517
|
+
const validatedQueueName = this.validateSqlValue(queueName, "queueName");
|
|
518
|
+
const escapedQueueName = this.escapeSqlString(validatedQueueName);
|
|
519
|
+
const escapedFingerprint = this.escapeSqlString(fingerprint);
|
|
520
|
+
const sql = `
|
|
521
|
+
SELECT * FROM ${this.tableName}
|
|
522
|
+
WHERE fingerprint = '${escapedFingerprint}' AND queue = '${escapedQueueName}'
|
|
523
|
+
AND status IN ('PENDING','PROCESSING')${prefixConditions}
|
|
524
|
+
ORDER BY created_at DESC
|
|
525
|
+
LIMIT 1`;
|
|
526
|
+
const { data, error } = await this.client.rpc("exec_sql", { query: sql });
|
|
527
|
+
if (error)
|
|
528
|
+
throw error;
|
|
529
|
+
if (!data || !Array.isArray(data) || data.length === 0)
|
|
530
|
+
return;
|
|
531
|
+
return data[0];
|
|
532
|
+
}
|
|
533
|
+
async getMany(ids) {
|
|
534
|
+
if (ids.length === 0)
|
|
535
|
+
return [];
|
|
536
|
+
let query = this.client.from(this.tableName).select("*").in("id", ids).eq("queue", this.queueName);
|
|
537
|
+
query = this.applyPrefixFilters(query);
|
|
538
|
+
const { data, error } = await query;
|
|
539
|
+
if (error)
|
|
540
|
+
throw error;
|
|
541
|
+
const map = new Map;
|
|
542
|
+
for (const row of data ?? []) {
|
|
543
|
+
map.set(row.id, row);
|
|
544
|
+
}
|
|
545
|
+
return ids.map((id) => map.get(id));
|
|
546
|
+
}
|
|
547
|
+
async completeWithResult(id, result) {
|
|
548
|
+
const now = new Date().toISOString();
|
|
549
|
+
let query = this.client.from(this.tableName).update({
|
|
550
|
+
output: result ?? null,
|
|
551
|
+
status: "COMPLETED",
|
|
552
|
+
progress: 100,
|
|
553
|
+
progress_message: "",
|
|
554
|
+
progress_details: null,
|
|
555
|
+
completed_at: now
|
|
556
|
+
}).eq("id", id).eq("queue", this.queueName);
|
|
557
|
+
query = this.applyPrefixFilters(query);
|
|
558
|
+
const { error } = await query;
|
|
559
|
+
if (error)
|
|
560
|
+
throw error;
|
|
561
|
+
}
|
|
562
|
+
async failWithError(id, opts) {
|
|
563
|
+
const numericId = Number(id);
|
|
564
|
+
if (!Number.isFinite(numericId)) {
|
|
565
|
+
throw new Error(`Invalid job id: ${id}`);
|
|
566
|
+
}
|
|
567
|
+
const prefixConditions = this.buildPrefixWhereSql();
|
|
568
|
+
const validatedQueueName = this.validateSqlValue(this.queueName, "queueName");
|
|
569
|
+
const escapedQueueName = this.escapeSqlString(validatedQueueName);
|
|
570
|
+
const errorLiteral = "error" in opts ? opts.error != null ? `'${this.escapeSqlString(opts.error)}'` : "NULL" : "NULL";
|
|
571
|
+
const errorCodeLiteral = "errorCode" in opts ? opts.errorCode != null ? `'${this.escapeSqlString(opts.errorCode)}'` : "NULL" : "NULL";
|
|
572
|
+
const abortClause = opts.abortRequested === true ? `CASE WHEN abort_requested_at IS NOT NULL THEN abort_requested_at ELSE NOW() AT TIME ZONE 'UTC' END` : `abort_requested_at`;
|
|
573
|
+
const sql = `
|
|
574
|
+
UPDATE ${this.tableName}
|
|
575
|
+
SET error = COALESCE(${errorLiteral}, error),
|
|
576
|
+
error_code = COALESCE(${errorCodeLiteral}, error_code),
|
|
577
|
+
abort_requested_at = ${abortClause},
|
|
578
|
+
status = 'FAILED',
|
|
579
|
+
completed_at = COALESCE(completed_at, NOW() AT TIME ZONE 'UTC')
|
|
580
|
+
WHERE id = ${numericId} AND queue = '${escapedQueueName}'${prefixConditions}`;
|
|
581
|
+
const { error } = await this.client.rpc("exec_sql", { query: sql });
|
|
582
|
+
if (error)
|
|
583
|
+
throw error;
|
|
584
|
+
}
|
|
501
585
|
async deleteJobsByStatusAndAge(status, olderThanMs) {
|
|
502
586
|
const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();
|
|
503
587
|
let query = this.client.from(this.tableName).delete().eq("queue", this.queueName).eq("status", status).not("completed_at", "is", null).lte("completed_at", cutoffDate);
|
|
@@ -1067,6 +1151,36 @@ class SupabaseJobStore {
|
|
|
1067
1151
|
async saveStatus(id, status) {
|
|
1068
1152
|
await this.core.saveStatus(id, status);
|
|
1069
1153
|
}
|
|
1154
|
+
async create(body, opts) {
|
|
1155
|
+
const enriched = {
|
|
1156
|
+
...body,
|
|
1157
|
+
fingerprint: opts.fingerprint ?? body.fingerprint,
|
|
1158
|
+
job_run_id: opts.jobRunId ?? body.job_run_id,
|
|
1159
|
+
max_attempts: opts.maxAttempts ?? body.max_attempts,
|
|
1160
|
+
deadline_at: opts.timeoutSeconds != null ? new Date(Date.now() + opts.timeoutSeconds * 1000).toISOString() : body.deadline_at
|
|
1161
|
+
};
|
|
1162
|
+
return this.core.add(enriched);
|
|
1163
|
+
}
|
|
1164
|
+
async findActiveByFingerprint(fingerprint, queueName) {
|
|
1165
|
+
return this.core.findActiveByFingerprint(fingerprint, queueName);
|
|
1166
|
+
}
|
|
1167
|
+
async getMany(ids) {
|
|
1168
|
+
return this.core.getMany(ids);
|
|
1169
|
+
}
|
|
1170
|
+
async completeWithResult(id, result) {
|
|
1171
|
+
this.pending.delete(id);
|
|
1172
|
+
await this.core.completeWithResult(id, result);
|
|
1173
|
+
}
|
|
1174
|
+
async failWithError(id, opts) {
|
|
1175
|
+
this.pending.delete(id);
|
|
1176
|
+
await this.core.failWithError(id, opts);
|
|
1177
|
+
}
|
|
1178
|
+
async markEnqueueDeferred(id, opts) {
|
|
1179
|
+
await this.core.finalize(id, {
|
|
1180
|
+
visible_at: opts.visible_at.toISOString(),
|
|
1181
|
+
error_code: opts.errorCode
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1070
1184
|
}
|
|
1071
1185
|
// src/job-queue/createSupabaseQueue.ts
|
|
1072
1186
|
function createSupabaseQueue(queueName, client, opts) {
|
|
@@ -1088,4 +1202,4 @@ export {
|
|
|
1088
1202
|
SUPABASE_QUEUE_STORAGE
|
|
1089
1203
|
};
|
|
1090
1204
|
|
|
1091
|
-
//# debugId=
|
|
1205
|
+
//# debugId=9D95D30C4B098D6464756E2164756E21
|