@dudousxd/nestjs-durable-store-drizzle 0.20.0 → 0.22.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/index.cjs +115 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +116 -3
- package/dist/index.js.map +1 -1
- package/dist/pg/index.cjs +234 -99
- package/dist/pg/index.cjs.map +1 -1
- package/dist/pg/index.d.cts +15 -2
- package/dist/pg/index.d.ts +15 -2
- package/dist/pg/index.js +182 -48
- package/dist/pg/index.js.map +1 -1
- package/package.json +4 -4
package/dist/pg/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(pg_exports, {
|
|
|
35
35
|
durableStepCheckpoints: () => durableStepCheckpoints,
|
|
36
36
|
durableWorkflowRuns: () => durableWorkflowRuns,
|
|
37
37
|
ensureDrizzlePgDurableSchema: () => ensureDrizzlePgDurableSchema,
|
|
38
|
+
rowsOf: () => rowsOf,
|
|
38
39
|
toDrizzleSql: () => toDrizzleSql
|
|
39
40
|
});
|
|
40
41
|
module.exports = __toCommonJS(pg_exports);
|
|
@@ -124,6 +125,7 @@ var DURABLE_PG_DDL = [
|
|
|
124
125
|
`CREATE INDEX IF NOT EXISTS "durable_workflow_runs_namespace_status_idx" ON "durable_workflow_runs" USING btree ("namespace","status","created_at")`,
|
|
125
126
|
`CREATE INDEX IF NOT EXISTS "durable_runs_tags_gin_idx" ON "durable_workflow_runs" USING gin ("tags" jsonb_path_ops)`,
|
|
126
127
|
`CREATE INDEX IF NOT EXISTS "durable_runs_status_updated_idx" ON "durable_workflow_runs" USING btree ("status","updated_at")`,
|
|
128
|
+
`CREATE INDEX IF NOT EXISTS "durable_step_checkpoints_group_idx" ON "durable_step_checkpoints" USING btree ("run_id","parallel_group","seq")`,
|
|
127
129
|
`CREATE INDEX IF NOT EXISTS "durable_run_attributes_num_idx" ON "durable_run_attributes" USING btree ("key","num_value")`,
|
|
128
130
|
`CREATE INDEX IF NOT EXISTS "durable_run_attributes_str_idx" ON "durable_run_attributes" USING btree ("key","str_value")`,
|
|
129
131
|
`CREATE INDEX IF NOT EXISTS "durable_signal_waiters_run_id_idx" ON "durable_signal_waiters" USING btree ("run_id")`,
|
|
@@ -142,10 +144,42 @@ __name(ensureDrizzlePgDurableSchema, "ensureDrizzlePgDurableSchema");
|
|
|
142
144
|
|
|
143
145
|
// src/pg/drizzle-pg-state-store.ts
|
|
144
146
|
var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
|
|
145
|
-
var
|
|
147
|
+
var import_drizzle_orm4 = require("drizzle-orm");
|
|
146
148
|
|
|
147
|
-
// src/pg/
|
|
149
|
+
// src/pg/executor.ts
|
|
148
150
|
var import_drizzle_orm2 = require("drizzle-orm");
|
|
151
|
+
function toDrizzleSql(text2, params = []) {
|
|
152
|
+
const chunks = [];
|
|
153
|
+
let last = 0;
|
|
154
|
+
for (const match of text2.matchAll(/\$(\d+)/g)) {
|
|
155
|
+
const index2 = Number(match[1]) - 1;
|
|
156
|
+
if (index2 < 0 || index2 >= params.length) throw new Error(`placeholder ${match[0]} has no bound parameter`);
|
|
157
|
+
chunks.push(import_drizzle_orm2.sql.raw(text2.slice(last, match.index)), import_drizzle_orm2.sql`${params[index2]}`);
|
|
158
|
+
last = (match.index ?? 0) + match[0].length;
|
|
159
|
+
}
|
|
160
|
+
chunks.push(import_drizzle_orm2.sql.raw(text2.slice(last)));
|
|
161
|
+
return import_drizzle_orm2.sql.join(chunks);
|
|
162
|
+
}
|
|
163
|
+
__name(toDrizzleSql, "toDrizzleSql");
|
|
164
|
+
function rowsOf(result) {
|
|
165
|
+
if (Array.isArray(result)) return result;
|
|
166
|
+
return result?.rows ?? [];
|
|
167
|
+
}
|
|
168
|
+
__name(rowsOf, "rowsOf");
|
|
169
|
+
function drizzlePgExecutor(db) {
|
|
170
|
+
return {
|
|
171
|
+
dialect: "postgres",
|
|
172
|
+
escapeId: /* @__PURE__ */ __name((id) => `"${id.replace(/"/g, '""')}"`, "escapeId"),
|
|
173
|
+
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await db.execute(toDrizzleSql(text2, params))), "query"),
|
|
174
|
+
transaction: /* @__PURE__ */ __name((fn) => db.transaction((tx) => fn({
|
|
175
|
+
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await tx.execute(toDrizzleSql(text2, params))), "query")
|
|
176
|
+
})), "transaction")
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
__name(drizzlePgExecutor, "drizzlePgExecutor");
|
|
180
|
+
|
|
181
|
+
// src/pg/schema.ts
|
|
182
|
+
var import_drizzle_orm3 = require("drizzle-orm");
|
|
149
183
|
var import_pg_core = require("drizzle-orm/pg-core");
|
|
150
184
|
var DEFAULT_NAMESPACE = "default";
|
|
151
185
|
var tstz = /* @__PURE__ */ __name((name) => (0, import_pg_core.timestamp)(name, {
|
|
@@ -220,7 +254,9 @@ var durableStepCheckpoints = (0, import_pg_core.pgTable)(
|
|
|
220
254
|
t.runId,
|
|
221
255
|
t.seq
|
|
222
256
|
]
|
|
223
|
-
})
|
|
257
|
+
}),
|
|
258
|
+
// A run detail reads one fan at a time: checkpointStats / queryCheckpoints by group, seq-paged.
|
|
259
|
+
(0, import_pg_core.index)("durable_step_checkpoints_group_idx").on(t.runId, t.parallelGroup, t.seq)
|
|
224
260
|
]
|
|
225
261
|
);
|
|
226
262
|
var durableRunAttributes = (0, import_pg_core.pgTable)("durable_run_attributes", {
|
|
@@ -302,22 +338,22 @@ var durablePgSchema = {
|
|
|
302
338
|
durableSchedules
|
|
303
339
|
};
|
|
304
340
|
function durablePgManagedTables() {
|
|
305
|
-
return Object.values(durablePgSchema).map((table) => (0,
|
|
341
|
+
return Object.values(durablePgSchema).map((table) => (0, import_drizzle_orm3.getTableName)(table));
|
|
306
342
|
}
|
|
307
343
|
__name(durablePgManagedTables, "durablePgManagedTables");
|
|
308
344
|
|
|
309
345
|
// src/pg/drizzle-pg-state-store.ts
|
|
310
346
|
function anyOf(conditions) {
|
|
311
347
|
const present = conditions.filter((c) => c !== void 0);
|
|
312
|
-
return present.length ? (0,
|
|
348
|
+
return present.length ? (0, import_drizzle_orm4.or)(...present) : import_drizzle_orm4.sql`1 = 0`;
|
|
313
349
|
}
|
|
314
350
|
__name(anyOf, "anyOf");
|
|
315
351
|
function namespaceFilter(namespace) {
|
|
316
|
-
return namespace === void 0 ? void 0 : (0,
|
|
352
|
+
return namespace === void 0 ? void 0 : (0, import_drizzle_orm4.eq)(durableWorkflowRuns.namespace, namespace);
|
|
317
353
|
}
|
|
318
354
|
__name(namespaceFilter, "namespaceFilter");
|
|
319
355
|
function hasTag(tag) {
|
|
320
|
-
return
|
|
356
|
+
return import_drizzle_orm4.sql`${durableWorkflowRuns.tags} @> ${JSON.stringify([
|
|
321
357
|
tag
|
|
322
358
|
])}::jsonb`;
|
|
323
359
|
}
|
|
@@ -355,7 +391,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
355
391
|
}
|
|
356
392
|
async tryAdmitSingleton(runId, tag, workflow, limit, retryWakeAt) {
|
|
357
393
|
return this.db.transaction(async (tx) => {
|
|
358
|
-
const where = (0,
|
|
394
|
+
const where = (0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.workflow, workflow), (0, import_drizzle_orm4.inArray)(durableWorkflowRuns.status, import_nestjs_durable_core.SINGLETON_ACTIVE_STATUSES), this.scope());
|
|
359
395
|
await tx.update(durableWorkflowRuns).set({
|
|
360
396
|
workflow
|
|
361
397
|
}).where(where);
|
|
@@ -364,12 +400,12 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
364
400
|
const tags = (0, import_nestjs_durable_core.singletonAdmissionTags)(runs, runId, tag, workflow, limit);
|
|
365
401
|
if (!tags) {
|
|
366
402
|
const patch = (0, import_nestjs_durable_core.singletonAdmissionDenialPatch)(runs, runId, tag, workflow, retryWakeAt);
|
|
367
|
-
if (patch) await tx.update(durableWorkflowRuns).set(toRunPatch(patch)).where((0,
|
|
403
|
+
if (patch) await tx.update(durableWorkflowRuns).set(toRunPatch(patch)).where((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId));
|
|
368
404
|
return false;
|
|
369
405
|
}
|
|
370
406
|
await tx.update(durableWorkflowRuns).set({
|
|
371
407
|
tags
|
|
372
|
-
}).where((0,
|
|
408
|
+
}).where((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId));
|
|
373
409
|
return true;
|
|
374
410
|
});
|
|
375
411
|
}
|
|
@@ -385,12 +421,28 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
385
421
|
const reindex = "searchAttributes" in patch;
|
|
386
422
|
if (!Object.keys(row).length && !reindex) return;
|
|
387
423
|
await this.db.transaction(async (tx) => {
|
|
388
|
-
if (Object.keys(row).length) await tx.update(durableWorkflowRuns).set(row).where((0,
|
|
424
|
+
if (Object.keys(row).length) await tx.update(durableWorkflowRuns).set(row).where((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId));
|
|
389
425
|
if (reindex) await reindexAttributes(tx, runId, patch.searchAttributes);
|
|
390
426
|
});
|
|
391
427
|
}
|
|
428
|
+
async updateRunIf(runId, expectedStatuses, inputPatch) {
|
|
429
|
+
if (expectedStatuses.length === 0) return false;
|
|
430
|
+
const patch = inputPatch.status && import_nestjs_durable_core.TERMINAL_RUN_STATUSES.includes(inputPatch.status) ? await (0, import_nestjs_durable_core.clearTerminalSingletonAdmission)(runId, inputPatch, (id) => this.withScope({}).getRun(id)) : inputPatch;
|
|
431
|
+
const row = toRunPatch(patch);
|
|
432
|
+
const reindex = "searchAttributes" in patch;
|
|
433
|
+
const matches = (0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId), (0, import_drizzle_orm4.inArray)(durableWorkflowRuns.status, expectedStatuses));
|
|
434
|
+
return this.db.transaction(async (tx) => {
|
|
435
|
+
const applied = Object.keys(row).length ? (await tx.update(durableWorkflowRuns).set(row).where(matches).returning({
|
|
436
|
+
id: durableWorkflowRuns.id
|
|
437
|
+
})).length === 1 : (await tx.select({
|
|
438
|
+
id: durableWorkflowRuns.id
|
|
439
|
+
}).from(durableWorkflowRuns).where(matches).for("update")).length === 1;
|
|
440
|
+
if (applied && reindex) await reindexAttributes(tx, runId, patch.searchAttributes);
|
|
441
|
+
return applied;
|
|
442
|
+
});
|
|
443
|
+
}
|
|
392
444
|
async getRun(runId) {
|
|
393
|
-
const rows = await this.db.select().from(durableWorkflowRuns).where((0,
|
|
445
|
+
const rows = await this.db.select().from(durableWorkflowRuns).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId), this.scope())).limit(1);
|
|
394
446
|
return rows[0] ? fromRunRow(rows[0]) : null;
|
|
395
447
|
}
|
|
396
448
|
async deleteRun(runId) {
|
|
@@ -420,7 +472,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
420
472
|
const cutoff = new Date(nowMs - (0, import_nestjs_durable_core.parseDuration)(policy.maxAge));
|
|
421
473
|
const rows = await tx.select({
|
|
422
474
|
id: durableWorkflowRuns.id
|
|
423
|
-
}).from(durableWorkflowRuns).where((0,
|
|
475
|
+
}).from(durableWorkflowRuns).where((0, import_drizzle_orm4.and)(...scoped, (0, import_drizzle_orm4.lt)(durableWorkflowRuns.updatedAt, cutoff))).orderBy((0, import_drizzle_orm4.asc)(durableWorkflowRuns.updatedAt)).limit(limit).for("update", {
|
|
424
476
|
skipLocked: true
|
|
425
477
|
});
|
|
426
478
|
for (const r of rows) ids.add(r.id);
|
|
@@ -428,7 +480,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
428
480
|
if (policy.maxCount != null && ids.size < limit) {
|
|
429
481
|
const rows = await tx.select({
|
|
430
482
|
id: durableWorkflowRuns.id
|
|
431
|
-
}).from(durableWorkflowRuns).where((0,
|
|
483
|
+
}).from(durableWorkflowRuns).where((0, import_drizzle_orm4.and)(...scoped)).orderBy((0, import_drizzle_orm4.desc)(durableWorkflowRuns.updatedAt), (0, import_drizzle_orm4.desc)(durableWorkflowRuns.id)).limit(limit).offset(policy.maxCount).for("update", {
|
|
432
484
|
skipLocked: true
|
|
433
485
|
});
|
|
434
486
|
for (const r of rows) {
|
|
@@ -445,7 +497,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
445
497
|
});
|
|
446
498
|
}
|
|
447
499
|
async getCheckpoint(runId, seq) {
|
|
448
|
-
const rows = await this.db.select().from(durableStepCheckpoints).where((0,
|
|
500
|
+
const rows = await this.db.select().from(durableStepCheckpoints).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableStepCheckpoints.runId, runId), (0, import_drizzle_orm4.eq)(durableStepCheckpoints.seq, seq))).limit(1);
|
|
449
501
|
return rows[0] ? fromCheckpointRow(rows[0]) : null;
|
|
450
502
|
}
|
|
451
503
|
async saveCheckpoint(checkpoint) {
|
|
@@ -453,11 +505,35 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
453
505
|
}
|
|
454
506
|
async saveCheckpointIfPending(checkpoint) {
|
|
455
507
|
const { runId, seq, ...set } = toCheckpointRow(checkpoint);
|
|
456
|
-
const rows = await this.db.update(durableStepCheckpoints).set(set).where((0,
|
|
508
|
+
const rows = await this.db.update(durableStepCheckpoints).set(set).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableStepCheckpoints.runId, runId), (0, import_drizzle_orm4.eq)(durableStepCheckpoints.seq, seq), (0, import_drizzle_orm4.eq)(durableStepCheckpoints.status, "pending"))).returning({
|
|
457
509
|
seq: durableStepCheckpoints.seq
|
|
458
510
|
});
|
|
459
511
|
return rows.length === 1;
|
|
460
512
|
}
|
|
513
|
+
async saveCheckpointsIfPending(checkpoints) {
|
|
514
|
+
const wrote = checkpoints.map(() => false);
|
|
515
|
+
if (checkpoints.length === 0) return wrote;
|
|
516
|
+
await this.db.transaction(async (tx) => {
|
|
517
|
+
for (const round of distinctRounds(checkpoints)) {
|
|
518
|
+
for (let at = 0; at < round.length; at += CHECKPOINT_BATCH_ROWS) {
|
|
519
|
+
const chunk = round.slice(at, at + CHECKPOINT_BATCH_ROWS);
|
|
520
|
+
const updated = rowsOf(await tx.execute(updateIfPendingFrom(chunk.map((i) => checkpoints[i]))));
|
|
521
|
+
const byKey = new Map(chunk.map((i) => [
|
|
522
|
+
rowKey(checkpoints[i]),
|
|
523
|
+
i
|
|
524
|
+
]));
|
|
525
|
+
for (const row of updated) {
|
|
526
|
+
const i = byKey.get(rowKey({
|
|
527
|
+
runId: row.run_id,
|
|
528
|
+
seq: Number(row.seq)
|
|
529
|
+
}));
|
|
530
|
+
if (i !== void 0) wrote[i] = true;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
return wrote;
|
|
536
|
+
}
|
|
461
537
|
async transaction(work) {
|
|
462
538
|
return this.db.transaction(async (tx) => work({
|
|
463
539
|
raw: tx,
|
|
@@ -466,20 +542,28 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
466
542
|
}
|
|
467
543
|
/** Crash recovery. Namespace-scoped: a worker re-drives only its own tenant's runs. */
|
|
468
544
|
async listIncompleteRuns(namespace) {
|
|
469
|
-
const rows = await this.db.select().from(durableWorkflowRuns).where((0,
|
|
545
|
+
const rows = await this.db.select().from(durableWorkflowRuns).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.inArray)(durableWorkflowRuns.status, [
|
|
470
546
|
"running",
|
|
471
547
|
"cancelling"
|
|
472
548
|
]), namespaceFilter(namespace), this.scope()));
|
|
473
549
|
return rows.map(fromRunRow);
|
|
474
550
|
}
|
|
551
|
+
async listOrphanedRuns(nowMs, limit, namespace) {
|
|
552
|
+
if (limit <= 0) return [];
|
|
553
|
+
const rows = await this.db.select().from(durableWorkflowRuns).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.inArray)(durableWorkflowRuns.status, [
|
|
554
|
+
"running",
|
|
555
|
+
"cancelling"
|
|
556
|
+
]), (0, import_drizzle_orm4.or)((0, import_drizzle_orm4.isNull)(durableWorkflowRuns.lockedUntil), (0, import_drizzle_orm4.lte)(durableWorkflowRuns.lockedUntil, new Date(nowMs))), namespaceFilter(namespace), this.scope())).orderBy((0, import_drizzle_orm4.asc)(durableWorkflowRuns.createdAt)).limit(limit);
|
|
557
|
+
return rows.map(fromRunRow);
|
|
558
|
+
}
|
|
475
559
|
/** FIFO pick-up, served by `durable_workflow_runs_namespace_status_idx`. The engine then leases
|
|
476
560
|
* each run with {@link tryLockRun}; the listing itself takes no locks (it runs outside a tx). */
|
|
477
561
|
async listPendingRuns(limit, namespace) {
|
|
478
|
-
const rows = await this.db.select().from(durableWorkflowRuns).where((0,
|
|
562
|
+
const rows = await this.db.select().from(durableWorkflowRuns).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.status, "pending"), namespaceFilter(namespace), this.scope())).orderBy((0, import_drizzle_orm4.asc)(durableWorkflowRuns.createdAt)).limit(limit);
|
|
479
563
|
return rows.map(fromRunRow);
|
|
480
564
|
}
|
|
481
565
|
async listDueTimers(nowMs, namespace, limit) {
|
|
482
|
-
const query = this.db.select().from(durableWorkflowRuns).where((0,
|
|
566
|
+
const query = this.db.select().from(durableWorkflowRuns).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.status, "suspended"), (0, import_drizzle_orm4.isNotNull)(durableWorkflowRuns.wakeAt), (0, import_drizzle_orm4.lte)(durableWorkflowRuns.wakeAt, new Date(nowMs)), namespaceFilter(namespace), this.scope())).orderBy((0, import_drizzle_orm4.asc)(durableWorkflowRuns.wakeAt));
|
|
483
567
|
const rows = limit !== void 0 ? await query.limit(limit) : await query;
|
|
484
568
|
return rows.map(fromRunRow);
|
|
485
569
|
}
|
|
@@ -487,7 +571,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
487
571
|
const rows = await this.db.update(durableWorkflowRuns).set({
|
|
488
572
|
lockedBy: owner,
|
|
489
573
|
lockedUntil: new Date(leaseUntilMs)
|
|
490
|
-
}).where((0,
|
|
574
|
+
}).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId), (0, import_drizzle_orm4.or)((0, import_drizzle_orm4.isNull)(durableWorkflowRuns.lockedUntil), (0, import_drizzle_orm4.lte)(durableWorkflowRuns.lockedUntil, new Date(nowMs))))).returning({
|
|
491
575
|
id: durableWorkflowRuns.id
|
|
492
576
|
});
|
|
493
577
|
return rows.length === 1;
|
|
@@ -496,12 +580,12 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
496
580
|
await this.db.update(durableWorkflowRuns).set({
|
|
497
581
|
lockedBy: null,
|
|
498
582
|
lockedUntil: null
|
|
499
|
-
}).where((0,
|
|
583
|
+
}).where((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId));
|
|
500
584
|
}
|
|
501
585
|
async renewRunLock(runId, owner, leaseUntilMs) {
|
|
502
586
|
const rows = await this.db.update(durableWorkflowRuns).set({
|
|
503
587
|
lockedUntil: new Date(leaseUntilMs)
|
|
504
|
-
}).where((0,
|
|
588
|
+
}).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableWorkflowRuns.id, runId), (0, import_drizzle_orm4.eq)(durableWorkflowRuns.lockedBy, owner))).returning({
|
|
505
589
|
id: durableWorkflowRuns.id
|
|
506
590
|
});
|
|
507
591
|
return rows.length === 1;
|
|
@@ -510,17 +594,17 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
510
594
|
runFilters(query) {
|
|
511
595
|
return [
|
|
512
596
|
this.scope(),
|
|
513
|
-
query.workflow ? (0,
|
|
514
|
-
query.workflows ? query.workflows.length ? (0,
|
|
597
|
+
query.workflow ? (0, import_drizzle_orm4.eq)(durableWorkflowRuns.workflow, query.workflow) : void 0,
|
|
598
|
+
query.workflows ? query.workflows.length ? (0, import_drizzle_orm4.inArray)(durableWorkflowRuns.workflow, query.workflows) : import_drizzle_orm4.sql`1 = 0` : void 0,
|
|
515
599
|
// The tenant boundary. Also the engine's execution-timeout sweep path
|
|
516
600
|
// (`listRuns({ workflow, status, namespace })`) — unscoped, it would cancel another tenant's runs.
|
|
517
601
|
namespaceFilter(query.namespace),
|
|
518
|
-
query.namespaces ? query.namespaces.length ? (0,
|
|
602
|
+
query.namespaces ? query.namespaces.length ? (0, import_drizzle_orm4.inArray)(durableWorkflowRuns.namespace, query.namespaces) : import_drizzle_orm4.sql`1 = 0` : void 0,
|
|
519
603
|
// `null` selects the unattributed bucket; a value never matches a NULL origin.
|
|
520
|
-
query.origin === null ? (0,
|
|
521
|
-
query.origins ? anyOf(query.origins.map((o) => o === null ? (0,
|
|
522
|
-
query.status ? (0,
|
|
523
|
-
query.statuses ? query.statuses.length ? (0,
|
|
604
|
+
query.origin === null ? (0, import_drizzle_orm4.isNull)(durableWorkflowRuns.origin) : query.origin !== void 0 ? (0, import_drizzle_orm4.eq)(durableWorkflowRuns.origin, query.origin) : void 0,
|
|
605
|
+
query.origins ? anyOf(query.origins.map((o) => o === null ? (0, import_drizzle_orm4.isNull)(durableWorkflowRuns.origin) : (0, import_drizzle_orm4.eq)(durableWorkflowRuns.origin, o))) : void 0,
|
|
606
|
+
query.status ? (0, import_drizzle_orm4.eq)(durableWorkflowRuns.status, query.status) : void 0,
|
|
607
|
+
query.statuses ? query.statuses.length ? (0, import_drizzle_orm4.inArray)(durableWorkflowRuns.status, query.statuses) : import_drizzle_orm4.sql`1 = 0` : void 0,
|
|
524
608
|
query.tag ? hasTag(query.tag) : void 0,
|
|
525
609
|
query.tags ? anyOf(query.tags.map(hasTag)) : void 0,
|
|
526
610
|
// One EXISTS per attribute predicate against the normalized side table (ANDed).
|
|
@@ -529,7 +613,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
529
613
|
}
|
|
530
614
|
async listRuns(query) {
|
|
531
615
|
const filters = this.runFilters(query);
|
|
532
|
-
const base = this.db.select().from(durableWorkflowRuns).where(filters.length ? (0,
|
|
616
|
+
const base = this.db.select().from(durableWorkflowRuns).where(filters.length ? (0, import_drizzle_orm4.and)(...filters) : void 0).orderBy((0, import_drizzle_orm4.desc)(durableWorkflowRuns.createdAt), (0, import_drizzle_orm4.desc)(durableWorkflowRuns.id)).$dynamic();
|
|
533
617
|
if (query.limit != null) base.limit(query.limit);
|
|
534
618
|
if (query.offset != null) base.offset(query.offset);
|
|
535
619
|
const rows = await base;
|
|
@@ -538,8 +622,8 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
538
622
|
async countRuns(query) {
|
|
539
623
|
const filters = this.runFilters(query);
|
|
540
624
|
const rows = await this.db.select({
|
|
541
|
-
count:
|
|
542
|
-
}).from(durableWorkflowRuns).where(filters.length ? (0,
|
|
625
|
+
count: import_drizzle_orm4.sql`count(*)`.mapWith(Number)
|
|
626
|
+
}).from(durableWorkflowRuns).where(filters.length ? (0, import_drizzle_orm4.and)(...filters) : void 0);
|
|
543
627
|
return rows[0]?.count ?? 0;
|
|
544
628
|
}
|
|
545
629
|
async runFacets(query) {
|
|
@@ -547,8 +631,8 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
547
631
|
const rows = await this.db.select({
|
|
548
632
|
status: durableWorkflowRuns.status,
|
|
549
633
|
origin: durableWorkflowRuns.origin,
|
|
550
|
-
count:
|
|
551
|
-
}).from(durableWorkflowRuns).where(filters.length ? (0,
|
|
634
|
+
count: import_drizzle_orm4.sql`count(*)`.mapWith(Number)
|
|
635
|
+
}).from(durableWorkflowRuns).where(filters.length ? (0, import_drizzle_orm4.and)(...filters) : void 0).groupBy(durableWorkflowRuns.status, durableWorkflowRuns.origin);
|
|
552
636
|
return (0, import_nestjs_durable_core.mergeRunFacetRows)(rows.map((r) => ({
|
|
553
637
|
status: r.status,
|
|
554
638
|
origin: r.origin,
|
|
@@ -569,8 +653,8 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
569
653
|
const filters = this.runFilters(query);
|
|
570
654
|
const rows = await this.db.select({
|
|
571
655
|
value: column,
|
|
572
|
-
count:
|
|
573
|
-
}).from(durableWorkflowRuns).where(filters.length ? (0,
|
|
656
|
+
count: import_drizzle_orm4.sql`count(*)`.mapWith(Number)
|
|
657
|
+
}).from(durableWorkflowRuns).where(filters.length ? (0, import_drizzle_orm4.and)(...filters) : void 0).groupBy(column);
|
|
574
658
|
return (0, import_nestjs_durable_core.mergeRunValueFacetRows)(rows.map((r) => ({
|
|
575
659
|
value: r.value ?? null,
|
|
576
660
|
count: r.count
|
|
@@ -580,10 +664,10 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
580
664
|
* excludes runs lacking the key (EXISTS requires the row). Numbers compare `num_value`, strings
|
|
581
665
|
* and booleans `str_value`; an `in` set ORs its members inside the one EXISTS. */
|
|
582
666
|
attributeExists(f) {
|
|
583
|
-
const comparisons = (0, import_nestjs_durable_core.attributePredicateOperands)(f).map(({ column, comparator, operand }) =>
|
|
584
|
-
return (0,
|
|
585
|
-
one:
|
|
586
|
-
}).from(durableRunAttributes).where((0,
|
|
667
|
+
const comparisons = (0, import_nestjs_durable_core.attributePredicateOperands)(f).map(({ column, comparator, operand }) => import_drizzle_orm4.sql`${column === "numValue" ? durableRunAttributes.numValue : durableRunAttributes.strValue} ${import_drizzle_orm4.sql.raw(comparator)} ${operand}`);
|
|
668
|
+
return (0, import_drizzle_orm4.exists)(this.db.select({
|
|
669
|
+
one: import_drizzle_orm4.sql`1`
|
|
670
|
+
}).from(durableRunAttributes).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableRunAttributes.runId, durableWorkflowRuns.id), (0, import_drizzle_orm4.eq)(durableRunAttributes.key, f.key), anyOf(comparisons))));
|
|
587
671
|
}
|
|
588
672
|
// ---- persisted schedules ----------------------------------------------------------------------
|
|
589
673
|
async saveSchedule(record) {
|
|
@@ -594,52 +678,99 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
594
678
|
});
|
|
595
679
|
}
|
|
596
680
|
async getSchedule(id) {
|
|
597
|
-
const rows = await this.db.select().from(durableSchedules).where((0,
|
|
681
|
+
const rows = await this.db.select().from(durableSchedules).where((0, import_drizzle_orm4.eq)(durableSchedules.id, id)).limit(1);
|
|
598
682
|
return rows[0] ? fromScheduleRow(rows[0]) : null;
|
|
599
683
|
}
|
|
600
684
|
/** A single conditional `UPDATE … RETURNING`: the compare-and-set on `next_fire_at` is atomic. */
|
|
601
685
|
async updateSchedule(id, patch, expectedNextFireAt) {
|
|
602
686
|
const set = toSchedulePatch(patch);
|
|
603
687
|
if (!Object.keys(set).length) return await this.getSchedule(id) !== null;
|
|
604
|
-
const rows = await this.db.update(durableSchedules).set(set).where((0,
|
|
688
|
+
const rows = await this.db.update(durableSchedules).set(set).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableSchedules.id, id), expectedNextFireAt === void 0 ? void 0 : expectedNextFireAt === null ? (0, import_drizzle_orm4.isNull)(durableSchedules.nextFireAt) : (0, import_drizzle_orm4.eq)(durableSchedules.nextFireAt, new Date(expectedNextFireAt)))).returning({
|
|
605
689
|
id: durableSchedules.id
|
|
606
690
|
});
|
|
607
691
|
return rows.length > 0;
|
|
608
692
|
}
|
|
609
693
|
async deleteSchedule(id) {
|
|
610
|
-
const rows = await this.db.delete(durableSchedules).where((0,
|
|
694
|
+
const rows = await this.db.delete(durableSchedules).where((0, import_drizzle_orm4.eq)(durableSchedules.id, id)).returning({
|
|
611
695
|
id: durableSchedules.id
|
|
612
696
|
});
|
|
613
697
|
return rows.length > 0;
|
|
614
698
|
}
|
|
615
699
|
async listSchedules(query) {
|
|
616
|
-
const base = this.db.select().from(durableSchedules).where((0,
|
|
700
|
+
const base = this.db.select().from(durableSchedules).where((0, import_drizzle_orm4.and)(query.namespace !== void 0 ? (0, import_drizzle_orm4.eq)(durableSchedules.namespace, query.namespace) : void 0, query.workflow !== void 0 ? (0, import_drizzle_orm4.eq)(durableSchedules.workflow, query.workflow) : void 0, query.paused !== void 0 ? (0, import_drizzle_orm4.eq)(durableSchedules.paused, query.paused) : void 0, query.tag !== void 0 ? import_drizzle_orm4.sql`${durableSchedules.tags} @> ${JSON.stringify([
|
|
617
701
|
query.tag
|
|
618
|
-
])}::jsonb` : void 0, query.dueBy !== void 0 ? (0,
|
|
702
|
+
])}::jsonb` : void 0, query.dueBy !== void 0 ? (0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableSchedules.paused, false), (0, import_drizzle_orm4.lte)(durableSchedules.nextFireAt, new Date(query.dueBy))) : void 0)).orderBy(import_drizzle_orm4.sql`${durableSchedules.nextFireAt} ASC NULLS LAST`, (0, import_drizzle_orm4.asc)(durableSchedules.id)).$dynamic();
|
|
619
703
|
if (query.limit != null) base.limit(query.limit);
|
|
620
704
|
if (query.offset != null) base.offset(query.offset);
|
|
621
705
|
return (await base).map(fromScheduleRow);
|
|
622
706
|
}
|
|
623
707
|
async listCheckpoints(runId) {
|
|
624
|
-
const rows = await this.db.select().from(durableStepCheckpoints).where((0,
|
|
708
|
+
const rows = await this.db.select().from(durableStepCheckpoints).where((0, import_drizzle_orm4.eq)(durableStepCheckpoints.runId, runId)).orderBy((0, import_drizzle_orm4.asc)(durableStepCheckpoints.seq));
|
|
625
709
|
return rows.map(fromCheckpointRow);
|
|
626
710
|
}
|
|
627
711
|
async getLatestCheckpointByName(runId, name) {
|
|
628
|
-
const rows = await this.db.select().from(durableStepCheckpoints).where((0,
|
|
712
|
+
const rows = await this.db.select().from(durableStepCheckpoints).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableStepCheckpoints.runId, runId), (0, import_drizzle_orm4.eq)(durableStepCheckpoints.name, name))).orderBy((0, import_drizzle_orm4.desc)(durableStepCheckpoints.seq)).limit(1);
|
|
629
713
|
return rows[0] ? fromCheckpointRow(rows[0]) : void 0;
|
|
630
714
|
}
|
|
631
715
|
async countCheckpoints(runId, fromSeq, toSeq, statuses) {
|
|
632
716
|
if (statuses.length === 0) return 0;
|
|
633
717
|
const rows = await this.db.select({
|
|
634
|
-
count:
|
|
635
|
-
}).from(durableStepCheckpoints).where((0,
|
|
718
|
+
count: import_drizzle_orm4.sql`count(*)`.mapWith(Number)
|
|
719
|
+
}).from(durableStepCheckpoints).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableStepCheckpoints.runId, runId), (0, import_drizzle_orm4.gte)(durableStepCheckpoints.seq, fromSeq), (0, import_drizzle_orm4.lte)(durableStepCheckpoints.seq, toSeq), (0, import_drizzle_orm4.inArray)(durableStepCheckpoints.status, statuses)));
|
|
636
720
|
return rows[0]?.count ?? 0;
|
|
637
721
|
}
|
|
638
722
|
async listCheckpointsByNamePrefix(runId, prefixes) {
|
|
639
723
|
if (prefixes.length === 0) return [];
|
|
640
|
-
const rows = await this.db.select().from(durableStepCheckpoints).where((0,
|
|
724
|
+
const rows = await this.db.select().from(durableStepCheckpoints).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableStepCheckpoints.runId, runId), (0, import_drizzle_orm4.or)(...prefixes.map((p) => (0, import_drizzle_orm4.like)(durableStepCheckpoints.name, `${escapeLike(p)}%`))))).orderBy((0, import_drizzle_orm4.asc)(durableStepCheckpoints.seq));
|
|
641
725
|
return rows.map(fromCheckpointRow);
|
|
642
726
|
}
|
|
727
|
+
/** {@link StateStore.checkpointStats}: one `GROUP BY parallel_group, status, name_kind` over the
|
|
728
|
+
* run's checkpoints, so a wide fan comes back as a few bucket rows instead of every member. */
|
|
729
|
+
async checkpointStats(runId, opts) {
|
|
730
|
+
const c = durableStepCheckpoints;
|
|
731
|
+
const nameKind = import_drizzle_orm4.sql`CASE
|
|
732
|
+
WHEN ${c.name} LIKE 'signal:child:%' THEN 'child'
|
|
733
|
+
WHEN ${c.name} LIKE 'fan:%' THEN 'folded'
|
|
734
|
+
WHEN ${c.name} LIKE 'spawn:%' THEN 'spawn'
|
|
735
|
+
ELSE 'step' END`.as("name_kind");
|
|
736
|
+
const rows = await this.db.select({
|
|
737
|
+
group: c.parallelGroup,
|
|
738
|
+
status: c.status,
|
|
739
|
+
nameKind,
|
|
740
|
+
count: import_drizzle_orm4.sql`count(*)`.mapWith(Number),
|
|
741
|
+
minSeq: import_drizzle_orm4.sql`min(${c.seq})`.mapWith(Number),
|
|
742
|
+
maxSeq: import_drizzle_orm4.sql`max(${c.seq})`.mapWith(Number),
|
|
743
|
+
minName: import_drizzle_orm4.sql`min(${c.name})`,
|
|
744
|
+
maxName: import_drizzle_orm4.sql`max(${c.name})`,
|
|
745
|
+
minEnqueuedAt: import_drizzle_orm4.sql`min(coalesce(${c.enqueuedAt}, ${c.startedAt}))`.mapWith(c.startedAt),
|
|
746
|
+
minStartedAt: import_drizzle_orm4.sql`min(${c.startedAt})`.mapWith(c.startedAt),
|
|
747
|
+
maxStartedAt: import_drizzle_orm4.sql`max(${c.startedAt})`.mapWith(c.startedAt),
|
|
748
|
+
maxFinishedAt: import_drizzle_orm4.sql`max(${c.finishedAt})`.mapWith(c.finishedAt),
|
|
749
|
+
sumAttempts: import_drizzle_orm4.sql`sum(${c.attempts})`.mapWith(Number)
|
|
750
|
+
}).from(c).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(c.runId, runId), opts?.group !== void 0 ? (0, import_drizzle_orm4.eq)(c.parallelGroup, opts.group) : void 0)).groupBy(c.parallelGroup, c.status, import_drizzle_orm4.sql`name_kind`);
|
|
751
|
+
return rows.map((r) => ({
|
|
752
|
+
...r,
|
|
753
|
+
group: r.group ?? null,
|
|
754
|
+
status: r.status
|
|
755
|
+
}));
|
|
756
|
+
}
|
|
757
|
+
/** {@link StateStore.queryCheckpoints}: the run's checkpoints narrowed in SQL, in `seq` order and
|
|
758
|
+
* paged there, so reading one page of a wide fan never loads the rest of it. */
|
|
759
|
+
async queryCheckpoints(runId, query) {
|
|
760
|
+
if (query.statuses?.length === 0 || query.namePrefixes?.length === 0) return [];
|
|
761
|
+
const c = durableStepCheckpoints;
|
|
762
|
+
const base = this.db.select().from(c).where((0, import_drizzle_orm4.and)(
|
|
763
|
+
(0, import_drizzle_orm4.eq)(c.runId, runId),
|
|
764
|
+
query.group !== void 0 ? (0, import_drizzle_orm4.eq)(c.parallelGroup, query.group) : void 0,
|
|
765
|
+
// `NOT IN` is never true for a NULL group, so ungrouped rows are kept explicitly.
|
|
766
|
+
query.excludeGroups?.length ? (0, import_drizzle_orm4.or)((0, import_drizzle_orm4.isNull)(c.parallelGroup), (0, import_drizzle_orm4.notInArray)(c.parallelGroup, query.excludeGroups)) : void 0,
|
|
767
|
+
query.statuses ? (0, import_drizzle_orm4.inArray)(c.status, query.statuses) : void 0,
|
|
768
|
+
query.namePrefixes ? (0, import_drizzle_orm4.or)(...query.namePrefixes.map((p) => (0, import_drizzle_orm4.like)(c.name, `${escapeLike(p)}%`))) : void 0
|
|
769
|
+
)).orderBy((0, import_drizzle_orm4.asc)(c.seq)).$dynamic();
|
|
770
|
+
if (query.limit != null) base.limit(query.limit);
|
|
771
|
+
if (query.offset != null) base.offset(query.offset);
|
|
772
|
+
return (await base).map(fromCheckpointRow);
|
|
773
|
+
}
|
|
643
774
|
async putSignalWaiter(waiter) {
|
|
644
775
|
const set = {
|
|
645
776
|
runId: waiter.runId,
|
|
@@ -655,12 +786,12 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
655
786
|
});
|
|
656
787
|
}
|
|
657
788
|
async takeSignalWaiter(token) {
|
|
658
|
-
const rows = await this.db.delete(durableSignalWaiters).where((0,
|
|
789
|
+
const rows = await this.db.delete(durableSignalWaiters).where((0, import_drizzle_orm4.eq)(durableSignalWaiters.token, token)).returning();
|
|
659
790
|
const row = rows[0];
|
|
660
791
|
return row ? fromWaiterRow(row) : null;
|
|
661
792
|
}
|
|
662
793
|
async listSignalWaiters(prefix) {
|
|
663
|
-
const rows = await this.db.select().from(durableSignalWaiters).where((0,
|
|
794
|
+
const rows = await this.db.select().from(durableSignalWaiters).where((0, import_drizzle_orm4.like)(durableSignalWaiters.token, `${escapeLike(prefix)}%`));
|
|
664
795
|
return rows.map(fromWaiterRow);
|
|
665
796
|
}
|
|
666
797
|
async registerChildWaits(entries) {
|
|
@@ -690,23 +821,23 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
690
821
|
}
|
|
691
822
|
async compactCheckpoints(runId, fromSeq, toSeq, into) {
|
|
692
823
|
await this.db.transaction(async (tx) => {
|
|
693
|
-
await tx.delete(durableStepCheckpoints).where((0,
|
|
824
|
+
await tx.delete(durableStepCheckpoints).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableStepCheckpoints.runId, runId), (0, import_drizzle_orm4.gte)(durableStepCheckpoints.seq, fromSeq), (0, import_drizzle_orm4.lte)(durableStepCheckpoints.seq, toSeq)));
|
|
694
825
|
await upsertCheckpoint(tx, into);
|
|
695
826
|
});
|
|
696
827
|
}
|
|
697
828
|
async listSignalWaitersByRun(runIds) {
|
|
698
829
|
if (runIds.length === 0) return [];
|
|
699
|
-
const rows = await this.db.select().from(durableSignalWaiters).where((0,
|
|
830
|
+
const rows = await this.db.select().from(durableSignalWaiters).where((0, import_drizzle_orm4.inArray)(durableSignalWaiters.runId, runIds));
|
|
700
831
|
return rows.map(fromWaiterRow);
|
|
701
832
|
}
|
|
702
833
|
async hasSignalWaiter(runId, tokenPrefix) {
|
|
703
834
|
const rows = await this.db.select({
|
|
704
835
|
token: durableSignalWaiters.token
|
|
705
|
-
}).from(durableSignalWaiters).where((0,
|
|
836
|
+
}).from(durableSignalWaiters).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableSignalWaiters.runId, runId), (0, import_drizzle_orm4.like)(durableSignalWaiters.token, `${escapeLike(tokenPrefix)}%`))).limit(1);
|
|
706
837
|
return rows.length > 0;
|
|
707
838
|
}
|
|
708
839
|
async removeSignalWaiter(waiter) {
|
|
709
|
-
await this.db.delete(durableSignalWaiters).where((0,
|
|
840
|
+
await this.db.delete(durableSignalWaiters).where((0, import_drizzle_orm4.and)((0, import_drizzle_orm4.eq)(durableSignalWaiters.token, waiter.token), (0, import_drizzle_orm4.eq)(durableSignalWaiters.runId, waiter.runId), (0, import_drizzle_orm4.eq)(durableSignalWaiters.seq, waiter.seq)));
|
|
710
841
|
}
|
|
711
842
|
async bufferSignal(token, payload) {
|
|
712
843
|
await this.db.insert(durableBufferedSignals).values({
|
|
@@ -717,10 +848,10 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
717
848
|
async takeBufferedSignal(token) {
|
|
718
849
|
const oldest = this.db.select({
|
|
719
850
|
id: durableBufferedSignals.id
|
|
720
|
-
}).from(durableBufferedSignals).where((0,
|
|
851
|
+
}).from(durableBufferedSignals).where((0, import_drizzle_orm4.eq)(durableBufferedSignals.token, token)).orderBy((0, import_drizzle_orm4.asc)(durableBufferedSignals.id)).limit(1).for("update", {
|
|
721
852
|
skipLocked: true
|
|
722
853
|
});
|
|
723
|
-
const rows = await this.db.delete(durableBufferedSignals).where((0,
|
|
854
|
+
const rows = await this.db.delete(durableBufferedSignals).where((0, import_drizzle_orm4.inArray)(durableBufferedSignals.id, oldest)).returning({
|
|
724
855
|
payload: durableBufferedSignals.payload
|
|
725
856
|
});
|
|
726
857
|
const row = rows[0];
|
|
@@ -737,7 +868,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
737
868
|
});
|
|
738
869
|
}
|
|
739
870
|
async listBufferedEvents(name, limit) {
|
|
740
|
-
const rows = await this.db.select().from(durableBufferedEvents).where((0,
|
|
871
|
+
const rows = await this.db.select().from(durableBufferedEvents).where((0, import_drizzle_orm4.eq)(durableBufferedEvents.name, name)).orderBy((0, import_drizzle_orm4.asc)(durableBufferedEvents.publishedAt), (0, import_drizzle_orm4.asc)(durableBufferedEvents.id)).limit(limit);
|
|
741
872
|
return rows.map((r) => ({
|
|
742
873
|
id: r.id,
|
|
743
874
|
payload: r.payload ?? void 0,
|
|
@@ -745,7 +876,7 @@ var DrizzlePgStateStore = class _DrizzlePgStateStore {
|
|
|
745
876
|
}));
|
|
746
877
|
}
|
|
747
878
|
async removeBufferedEvent(id) {
|
|
748
|
-
const rows = await this.db.delete(durableBufferedEvents).where((0,
|
|
879
|
+
const rows = await this.db.delete(durableBufferedEvents).where((0, import_drizzle_orm4.eq)(durableBufferedEvents.id, id)).returning({
|
|
749
880
|
id: durableBufferedEvents.id
|
|
750
881
|
});
|
|
751
882
|
return rows.length === 1;
|
|
@@ -755,6 +886,41 @@ function escapeLike(value) {
|
|
|
755
886
|
return value.replace(/[\\%_]/g, (c) => `\\${c}`);
|
|
756
887
|
}
|
|
757
888
|
__name(escapeLike, "escapeLike");
|
|
889
|
+
var CHECKPOINT_BATCH_ROWS = 500;
|
|
890
|
+
var rowKey = /* @__PURE__ */ __name((cp) => `${cp.seq}:${cp.runId}`, "rowKey");
|
|
891
|
+
function distinctRounds(checkpoints) {
|
|
892
|
+
const rounds = [];
|
|
893
|
+
const seen = /* @__PURE__ */ new Map();
|
|
894
|
+
checkpoints.forEach((cp, i) => {
|
|
895
|
+
const key = rowKey(cp);
|
|
896
|
+
const round = seen.get(key) ?? 0;
|
|
897
|
+
seen.set(key, round + 1);
|
|
898
|
+
const indexes = rounds[round] ?? [];
|
|
899
|
+
rounds[round] = indexes;
|
|
900
|
+
indexes.push(i);
|
|
901
|
+
});
|
|
902
|
+
return rounds;
|
|
903
|
+
}
|
|
904
|
+
__name(distinctRounds, "distinctRounds");
|
|
905
|
+
function updateIfPendingFrom(checkpoints) {
|
|
906
|
+
const json = /* @__PURE__ */ __name((v) => v == null ? null : JSON.stringify(v), "json");
|
|
907
|
+
const ts = /* @__PURE__ */ __name((v) => v == null ? null : v.toISOString(), "ts");
|
|
908
|
+
const values = checkpoints.map((cp) => {
|
|
909
|
+
const r = toCheckpointRow(cp);
|
|
910
|
+
return import_drizzle_orm4.sql`(${r.runId}::text, ${r.seq}::integer, ${r.name}::text, ${r.kind}::text, ${r.stepId}::text, ${r.status}::text, ${json(r.input)}::jsonb, ${json(r.output)}::jsonb, ${json(r.error)}::jsonb, ${json(r.events)}::jsonb, ${r.attempts}::integer, ${r.workerGroup}::text, ${r.parallelGroup}::text, ${ts(r.wakeAt)}::timestamptz, ${ts(r.enqueuedAt)}::timestamptz, ${ts(r.startedAt)}::timestamptz, ${ts(r.finishedAt)}::timestamptz)`;
|
|
911
|
+
});
|
|
912
|
+
return import_drizzle_orm4.sql`UPDATE ${durableStepCheckpoints} AS c SET
|
|
913
|
+
name = v.name, kind = v.kind, step_id = v.step_id, status = v.status, input = v.input,
|
|
914
|
+
output = v.output, error = v.error, events = v.events, attempts = v.attempts,
|
|
915
|
+
worker_group = v.worker_group, parallel_group = v.parallel_group, wake_at = v.wake_at,
|
|
916
|
+
enqueued_at = v.enqueued_at, started_at = v.started_at, finished_at = v.finished_at
|
|
917
|
+
FROM (VALUES ${import_drizzle_orm4.sql.join(values, import_drizzle_orm4.sql`, `)}) AS v(run_id, seq, name, kind, step_id, status, input,
|
|
918
|
+
output, error, events, attempts, worker_group, parallel_group, wake_at, enqueued_at, started_at,
|
|
919
|
+
finished_at)
|
|
920
|
+
WHERE c.run_id = v.run_id AND c.seq = v.seq AND c.status = 'pending'
|
|
921
|
+
RETURNING c.run_id, c.seq`;
|
|
922
|
+
}
|
|
923
|
+
__name(updateIfPendingFrom, "updateIfPendingFrom");
|
|
758
924
|
async function upsertCheckpoint(db, cp) {
|
|
759
925
|
const row = toCheckpointRow(cp);
|
|
760
926
|
await db.insert(durableStepCheckpoints).values(row).onConflictDoUpdate({
|
|
@@ -767,16 +933,16 @@ async function upsertCheckpoint(db, cp) {
|
|
|
767
933
|
}
|
|
768
934
|
__name(upsertCheckpoint, "upsertCheckpoint");
|
|
769
935
|
async function reindexAttributes(db, runId, attributes) {
|
|
770
|
-
await db.delete(durableRunAttributes).where((0,
|
|
936
|
+
await db.delete(durableRunAttributes).where((0, import_drizzle_orm4.eq)(durableRunAttributes.runId, runId));
|
|
771
937
|
const rows = (0, import_nestjs_durable_core.normalizeAttributeRows)(runId, attributes);
|
|
772
938
|
if (rows.length) await db.insert(durableRunAttributes).values(rows);
|
|
773
939
|
}
|
|
774
940
|
__name(reindexAttributes, "reindexAttributes");
|
|
775
941
|
async function deleteRunsCascade(db, runIds) {
|
|
776
|
-
await db.delete(durableStepCheckpoints).where((0,
|
|
777
|
-
await db.delete(durableSignalWaiters).where((0,
|
|
778
|
-
await db.delete(durableRunAttributes).where((0,
|
|
779
|
-
await db.delete(durableWorkflowRuns).where((0,
|
|
942
|
+
await db.delete(durableStepCheckpoints).where((0, import_drizzle_orm4.inArray)(durableStepCheckpoints.runId, runIds));
|
|
943
|
+
await db.delete(durableSignalWaiters).where((0, import_drizzle_orm4.inArray)(durableSignalWaiters.runId, runIds));
|
|
944
|
+
await db.delete(durableRunAttributes).where((0, import_drizzle_orm4.inArray)(durableRunAttributes.runId, runIds));
|
|
945
|
+
await db.delete(durableWorkflowRuns).where((0, import_drizzle_orm4.inArray)(durableWorkflowRuns.id, runIds));
|
|
780
946
|
}
|
|
781
947
|
__name(deleteRunsCascade, "deleteRunsCascade");
|
|
782
948
|
function fromWaiterRow(row) {
|
|
@@ -950,44 +1116,12 @@ function fromScheduleRow(row) {
|
|
|
950
1116
|
}
|
|
951
1117
|
__name(fromScheduleRow, "fromScheduleRow");
|
|
952
1118
|
function excludedSet(table, only) {
|
|
953
|
-
return Object.fromEntries(Object.entries((0,
|
|
1119
|
+
return Object.fromEntries(Object.entries((0, import_drizzle_orm4.getTableColumns)(table)).filter(([key]) => !only || only.includes(key)).map(([key, column]) => [
|
|
954
1120
|
key,
|
|
955
|
-
|
|
1121
|
+
import_drizzle_orm4.sql.raw(`excluded."${column.name}"`)
|
|
956
1122
|
]));
|
|
957
1123
|
}
|
|
958
1124
|
__name(excludedSet, "excludedSet");
|
|
959
|
-
|
|
960
|
-
// src/pg/executor.ts
|
|
961
|
-
var import_drizzle_orm4 = require("drizzle-orm");
|
|
962
|
-
function toDrizzleSql(text2, params = []) {
|
|
963
|
-
const chunks = [];
|
|
964
|
-
let last = 0;
|
|
965
|
-
for (const match of text2.matchAll(/\$(\d+)/g)) {
|
|
966
|
-
const index2 = Number(match[1]) - 1;
|
|
967
|
-
if (index2 < 0 || index2 >= params.length) throw new Error(`placeholder ${match[0]} has no bound parameter`);
|
|
968
|
-
chunks.push(import_drizzle_orm4.sql.raw(text2.slice(last, match.index)), import_drizzle_orm4.sql`${params[index2]}`);
|
|
969
|
-
last = (match.index ?? 0) + match[0].length;
|
|
970
|
-
}
|
|
971
|
-
chunks.push(import_drizzle_orm4.sql.raw(text2.slice(last)));
|
|
972
|
-
return import_drizzle_orm4.sql.join(chunks);
|
|
973
|
-
}
|
|
974
|
-
__name(toDrizzleSql, "toDrizzleSql");
|
|
975
|
-
function rowsOf(result) {
|
|
976
|
-
if (Array.isArray(result)) return result;
|
|
977
|
-
return result?.rows ?? [];
|
|
978
|
-
}
|
|
979
|
-
__name(rowsOf, "rowsOf");
|
|
980
|
-
function drizzlePgExecutor(db) {
|
|
981
|
-
return {
|
|
982
|
-
dialect: "postgres",
|
|
983
|
-
escapeId: /* @__PURE__ */ __name((id) => `"${id.replace(/"/g, '""')}"`, "escapeId"),
|
|
984
|
-
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await db.execute(toDrizzleSql(text2, params))), "query"),
|
|
985
|
-
transaction: /* @__PURE__ */ __name((fn) => db.transaction((tx) => fn({
|
|
986
|
-
query: /* @__PURE__ */ __name(async (text2, params) => rowsOf(await tx.execute(toDrizzleSql(text2, params))), "query")
|
|
987
|
-
})), "transaction")
|
|
988
|
-
};
|
|
989
|
-
}
|
|
990
|
-
__name(drizzlePgExecutor, "drizzlePgExecutor");
|
|
991
1125
|
// Annotate the CommonJS export names for ESM import in node:
|
|
992
1126
|
0 && (module.exports = {
|
|
993
1127
|
DEFAULT_NAMESPACE,
|
|
@@ -1004,6 +1138,7 @@ __name(drizzlePgExecutor, "drizzlePgExecutor");
|
|
|
1004
1138
|
durableStepCheckpoints,
|
|
1005
1139
|
durableWorkflowRuns,
|
|
1006
1140
|
ensureDrizzlePgDurableSchema,
|
|
1141
|
+
rowsOf,
|
|
1007
1142
|
toDrizzleSql
|
|
1008
1143
|
});
|
|
1009
1144
|
//# sourceMappingURL=index.cjs.map
|