@dudousxd/nestjs-durable-store-typeorm 0.19.0 → 0.20.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 +132 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +134 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -417,6 +417,14 @@ function durableEntities(options = {}) {
|
|
|
417
417
|
name: "SignalWaiterEntity",
|
|
418
418
|
target: SignalWaiterEntity,
|
|
419
419
|
tableName: "durable_signal_waiters",
|
|
420
|
+
indices: [
|
|
421
|
+
{
|
|
422
|
+
name: "durable_signal_waiters_run_id_idx",
|
|
423
|
+
columns: [
|
|
424
|
+
"runId"
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
],
|
|
420
428
|
columns: {
|
|
421
429
|
token: {
|
|
422
430
|
type: "text",
|
|
@@ -832,6 +840,11 @@ async function ensureTypeOrmDurableSchema(dataSource) {
|
|
|
832
840
|
"durable_runs_namespace_status_idx",
|
|
833
841
|
`${runs} (${runsCol("namespace")}, ${runsCol("status")}, ${runsCol("createdAt")})`
|
|
834
842
|
],
|
|
843
|
+
// A run's waiters: the `ctx.all` join barrier probes them once per settled child.
|
|
844
|
+
[
|
|
845
|
+
"durable_signal_waiters_run_id_idx",
|
|
846
|
+
`${waiters} (${waiterCol("runId")})`
|
|
847
|
+
],
|
|
835
848
|
// buffered signals are taken FIFO per token (smallest id) — index the token for the scan.
|
|
836
849
|
[
|
|
837
850
|
"durable_buffered_signals_token_idx",
|
|
@@ -886,6 +899,7 @@ __name(existingColumns, "existingColumns");
|
|
|
886
899
|
// src/typeorm-state-store.ts
|
|
887
900
|
var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
|
|
888
901
|
var import_typeorm2 = require("typeorm");
|
|
902
|
+
var sqliteSingletonClaims = /* @__PURE__ */ new WeakMap();
|
|
889
903
|
var TypeOrmStateStore = class {
|
|
890
904
|
static {
|
|
891
905
|
__name(this, "TypeOrmStateStore");
|
|
@@ -928,11 +942,63 @@ var TypeOrmStateStore = class {
|
|
|
928
942
|
const rows = (0, import_nestjs_durable_core.normalizeAttributeRows)(runId, attributes);
|
|
929
943
|
if (rows.length) await repo.insert(rows);
|
|
930
944
|
}
|
|
945
|
+
async tryAdmitSingleton(runId, tag, workflow, limit, retryWakeAt) {
|
|
946
|
+
const previous = sqliteSingletonClaims.get(this.dataSource) ?? Promise.resolve();
|
|
947
|
+
const sqlite = [
|
|
948
|
+
"sqlite",
|
|
949
|
+
"better-sqlite3",
|
|
950
|
+
"sqljs"
|
|
951
|
+
].includes(this.dataSource.options.type);
|
|
952
|
+
let release;
|
|
953
|
+
if (sqlite) {
|
|
954
|
+
const next = new Promise((resolve) => {
|
|
955
|
+
release = resolve;
|
|
956
|
+
});
|
|
957
|
+
sqliteSingletonClaims.set(this.dataSource, previous.then(() => next));
|
|
958
|
+
await previous;
|
|
959
|
+
}
|
|
960
|
+
try {
|
|
961
|
+
return await this.dataSource.transaction(async (em) => {
|
|
962
|
+
const repo = em.getRepository(WorkflowRunEntity);
|
|
963
|
+
const where = {
|
|
964
|
+
workflow,
|
|
965
|
+
status: (0, import_typeorm2.In)(import_nestjs_durable_core.SINGLETON_ACTIVE_STATUSES)
|
|
966
|
+
};
|
|
967
|
+
await repo.update(where, {
|
|
968
|
+
workflow
|
|
969
|
+
});
|
|
970
|
+
const runs = (await repo.find({
|
|
971
|
+
where
|
|
972
|
+
})).map(fromRunEntity);
|
|
973
|
+
const tags = (0, import_nestjs_durable_core.singletonAdmissionTags)(runs, runId, tag, workflow, limit);
|
|
974
|
+
if (!tags) {
|
|
975
|
+
const patch = (0, import_nestjs_durable_core.singletonAdmissionDenialPatch)(runs, runId, tag, workflow, retryWakeAt);
|
|
976
|
+
if (patch) await repo.update({
|
|
977
|
+
id: runId
|
|
978
|
+
}, {
|
|
979
|
+
status: "suspended",
|
|
980
|
+
wakeAt: new Date(patch.wakeAt),
|
|
981
|
+
updatedAt: patch.updatedAt
|
|
982
|
+
});
|
|
983
|
+
return false;
|
|
984
|
+
}
|
|
985
|
+
await repo.update({
|
|
986
|
+
id: runId
|
|
987
|
+
}, {
|
|
988
|
+
tags
|
|
989
|
+
});
|
|
990
|
+
return true;
|
|
991
|
+
});
|
|
992
|
+
} finally {
|
|
993
|
+
release?.();
|
|
994
|
+
}
|
|
995
|
+
}
|
|
931
996
|
async createRun(run) {
|
|
932
997
|
await this.runs().save(toRunEntity(run));
|
|
933
998
|
await this.reindexAttributes(run.id, run.searchAttributes);
|
|
934
999
|
}
|
|
935
|
-
async updateRun(runId,
|
|
1000
|
+
async updateRun(runId, inputPatch) {
|
|
1001
|
+
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.getRun(id)) : inputPatch;
|
|
936
1002
|
const update = {};
|
|
937
1003
|
if ("workflow" in patch) update.workflow = patch.workflow;
|
|
938
1004
|
if ("workflowVersion" in patch) update.workflowVersion = patch.workflowVersion;
|
|
@@ -1364,6 +1430,71 @@ var TypeOrmStateStore = class {
|
|
|
1364
1430
|
parallelGroup: e.parallelGroup ?? void 0
|
|
1365
1431
|
}));
|
|
1366
1432
|
}
|
|
1433
|
+
async registerChildWaits(entries) {
|
|
1434
|
+
if (entries.length === 0) return;
|
|
1435
|
+
await this.dataSource.transaction(async (em) => {
|
|
1436
|
+
await em.getRepository(SignalWaiterEntity).upsert(entries.map(({ waiter }) => ({
|
|
1437
|
+
token: waiter.token,
|
|
1438
|
+
runId: waiter.runId,
|
|
1439
|
+
seq: waiter.seq,
|
|
1440
|
+
parallelGroup: waiter.parallelGroup ?? null
|
|
1441
|
+
})), [
|
|
1442
|
+
"token"
|
|
1443
|
+
]);
|
|
1444
|
+
await em.getRepository(StepCheckpointEntity).upsert(entries.map(({ checkpoint }) => toCheckpointEntity(checkpoint)), [
|
|
1445
|
+
"runId",
|
|
1446
|
+
"seq"
|
|
1447
|
+
]);
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
async compactCheckpoints(runId, fromSeq, toSeq, into) {
|
|
1451
|
+
await this.dataSource.transaction(async (em) => {
|
|
1452
|
+
const checkpoints = em.getRepository(StepCheckpointEntity);
|
|
1453
|
+
await checkpoints.delete({
|
|
1454
|
+
runId,
|
|
1455
|
+
seq: (0, import_typeorm2.Between)(fromSeq, toSeq)
|
|
1456
|
+
});
|
|
1457
|
+
await checkpoints.upsert(toCheckpointEntity(into), [
|
|
1458
|
+
"runId",
|
|
1459
|
+
"seq"
|
|
1460
|
+
]);
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
async listSignalWaitersByRun(runIds) {
|
|
1464
|
+
if (runIds.length === 0) return [];
|
|
1465
|
+
const rows = await this.waiters().find({
|
|
1466
|
+
where: {
|
|
1467
|
+
runId: (0, import_typeorm2.In)(runIds)
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1470
|
+
return rows.map((e) => ({
|
|
1471
|
+
token: e.token,
|
|
1472
|
+
runId: e.runId,
|
|
1473
|
+
seq: e.seq,
|
|
1474
|
+
parallelGroup: e.parallelGroup ?? void 0
|
|
1475
|
+
}));
|
|
1476
|
+
}
|
|
1477
|
+
async hasSignalWaiter(runId, tokenPrefix) {
|
|
1478
|
+
const where = {
|
|
1479
|
+
runId,
|
|
1480
|
+
token: (0, import_typeorm2.Like)(`${tokenPrefix}%`)
|
|
1481
|
+
};
|
|
1482
|
+
const first = await this.waiters().findOne({
|
|
1483
|
+
where,
|
|
1484
|
+
select: {
|
|
1485
|
+
token: true
|
|
1486
|
+
}
|
|
1487
|
+
});
|
|
1488
|
+
if (!first) return false;
|
|
1489
|
+
if (first.token.startsWith(tokenPrefix)) return true;
|
|
1490
|
+
const rows = await this.waiters().find({
|
|
1491
|
+
where,
|
|
1492
|
+
select: {
|
|
1493
|
+
token: true
|
|
1494
|
+
}
|
|
1495
|
+
});
|
|
1496
|
+
return rows.some((r) => r.token.startsWith(tokenPrefix));
|
|
1497
|
+
}
|
|
1367
1498
|
async takeSignalWaiter(token) {
|
|
1368
1499
|
const e = await this.waiters().findOneBy({
|
|
1369
1500
|
token
|