@dudousxd/nestjs-durable-store-typeorm 0.13.0 → 0.15.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 +122 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +121 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/index.ts
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
|
+
BufferedEventEntity: () => BufferedEventEntity,
|
|
24
25
|
BufferedSignalEntity: () => BufferedSignalEntity,
|
|
25
26
|
ENTITIES: () => ENTITIES,
|
|
26
27
|
JSON_BLOB_COLUMNS: () => JSON_BLOB_COLUMNS,
|
|
@@ -89,6 +90,7 @@ var WorkflowRunEntity = class {
|
|
|
89
90
|
tags;
|
|
90
91
|
searchAttributes;
|
|
91
92
|
priority;
|
|
93
|
+
origin;
|
|
92
94
|
createdAt;
|
|
93
95
|
updatedAt;
|
|
94
96
|
};
|
|
@@ -140,6 +142,15 @@ var BufferedSignalEntity = class {
|
|
|
140
142
|
token;
|
|
141
143
|
payload;
|
|
142
144
|
};
|
|
145
|
+
var BufferedEventEntity = class {
|
|
146
|
+
static {
|
|
147
|
+
__name(this, "BufferedEventEntity");
|
|
148
|
+
}
|
|
149
|
+
id;
|
|
150
|
+
name;
|
|
151
|
+
payload;
|
|
152
|
+
publishedAt;
|
|
153
|
+
};
|
|
143
154
|
function durableEntities(options = {}) {
|
|
144
155
|
const col = columnNamer(options.naming ?? "snake_case");
|
|
145
156
|
const workflowRuns = new import_typeorm.EntitySchema({
|
|
@@ -226,6 +237,18 @@ function durableEntities(options = {}) {
|
|
|
226
237
|
nullable: true,
|
|
227
238
|
name: col("priority")
|
|
228
239
|
},
|
|
240
|
+
// Which library/module registered the workflow this run belongs to (e.g.
|
|
241
|
+
// `@dudousxd/nestjs-catalog-pipeline`), derived at registration time — never caller input.
|
|
242
|
+
// Nullable with NO default: an origin cannot be reconstructed for a row written before this
|
|
243
|
+
// column existed, so it stays NULL and reads back as `undefined` = "unknown". Defaulting it to
|
|
244
|
+
// a real-looking string would be indistinguishable from a genuine registration in the
|
|
245
|
+
// dashboard's facet. `ensureTypeOrmDurableSchema` back-fills the COLUMN onto pre-existing
|
|
246
|
+
// tables (see the `additive` map in ./schema), never its value.
|
|
247
|
+
origin: {
|
|
248
|
+
type: "text",
|
|
249
|
+
nullable: true,
|
|
250
|
+
name: col("origin")
|
|
251
|
+
},
|
|
229
252
|
createdAt: {
|
|
230
253
|
type: Date,
|
|
231
254
|
name: col("createdAt")
|
|
@@ -408,12 +431,44 @@ function durableEntities(options = {}) {
|
|
|
408
431
|
}
|
|
409
432
|
}
|
|
410
433
|
});
|
|
434
|
+
const bufferedEvents = new import_typeorm.EntitySchema({
|
|
435
|
+
name: "BufferedEventEntity",
|
|
436
|
+
target: BufferedEventEntity,
|
|
437
|
+
tableName: "durable_buffered_events",
|
|
438
|
+
// No `indices` here (unlike MikroORM's EntitySchema, which does declare one): this store manages
|
|
439
|
+
// its DDL — including the `(name, publishedAt)` index — via raw SQL in `schema.ts`'s
|
|
440
|
+
// `ensureTypeOrmDurableSchema`, the same as every other durable_* table's indexes.
|
|
441
|
+
columns: {
|
|
442
|
+
// Caller-minted uuid (engine.publishEvent), not autoincrement — removeBufferedEvent targets it
|
|
443
|
+
// directly and needs to be handed the SAME id it was buffered with.
|
|
444
|
+
id: {
|
|
445
|
+
type: "text",
|
|
446
|
+
primary: true,
|
|
447
|
+
name: col("id")
|
|
448
|
+
},
|
|
449
|
+
name: {
|
|
450
|
+
type: "text",
|
|
451
|
+
name: col("name")
|
|
452
|
+
},
|
|
453
|
+
payload: {
|
|
454
|
+
type: "text",
|
|
455
|
+
nullable: true,
|
|
456
|
+
name: col("payload"),
|
|
457
|
+
transformer: jsonColumnTransformer("buffered.eventPayload")
|
|
458
|
+
},
|
|
459
|
+
publishedAt: {
|
|
460
|
+
type: Date,
|
|
461
|
+
name: col("publishedAt")
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
});
|
|
411
465
|
return [
|
|
412
466
|
workflowRuns,
|
|
413
467
|
stepCheckpoints,
|
|
414
468
|
runAttributes,
|
|
415
469
|
signalWaiters,
|
|
416
|
-
bufferedSignals
|
|
470
|
+
bufferedSignals,
|
|
471
|
+
bufferedEvents
|
|
417
472
|
];
|
|
418
473
|
}
|
|
419
474
|
__name(durableEntities, "durableEntities");
|
|
@@ -440,7 +495,8 @@ var TABLE_TO_ENTITY = {
|
|
|
440
495
|
durable_step_checkpoints: StepCheckpointEntity,
|
|
441
496
|
durable_run_attributes: RunAttributeEntity,
|
|
442
497
|
durable_signal_waiters: SignalWaiterEntity,
|
|
443
|
-
durable_buffered_signals: BufferedSignalEntity
|
|
498
|
+
durable_buffered_signals: BufferedSignalEntity,
|
|
499
|
+
durable_buffered_events: BufferedEventEntity
|
|
444
500
|
};
|
|
445
501
|
function durableManagedTables() {
|
|
446
502
|
return Object.keys(TABLE_TO_ENTITY);
|
|
@@ -490,11 +546,13 @@ async function ensureTypeOrmDurableSchema(dataSource) {
|
|
|
490
546
|
const runAttributes = q("durable_run_attributes");
|
|
491
547
|
const waiters = q("durable_signal_waiters");
|
|
492
548
|
const buffered = q("durable_buffered_signals");
|
|
549
|
+
const bufferedEvents = q("durable_buffered_events");
|
|
493
550
|
const runsCol = /* @__PURE__ */ __name((property) => q(resolve("durable_workflow_runs", property)), "runsCol");
|
|
494
551
|
const cpCol = /* @__PURE__ */ __name((property) => q(resolve("durable_step_checkpoints", property)), "cpCol");
|
|
495
552
|
const attrCol = /* @__PURE__ */ __name((property) => q(resolve("durable_run_attributes", property)), "attrCol");
|
|
496
553
|
const waiterCol = /* @__PURE__ */ __name((property) => q(resolve("durable_signal_waiters", property)), "waiterCol");
|
|
497
554
|
const bufCol = /* @__PURE__ */ __name((property) => q(resolve("durable_buffered_signals", property)), "bufCol");
|
|
555
|
+
const bevCol = /* @__PURE__ */ __name((property) => q(resolve("durable_buffered_events", property)), "bevCol");
|
|
498
556
|
const num = isPg ? "double precision" : isMysql ? "double" : "real";
|
|
499
557
|
const bufferedId = isSqlite ? `${bufCol("id")} integer PRIMARY KEY AUTOINCREMENT` : isMysql ? `${bufCol("id")} bigint NOT NULL AUTO_INCREMENT PRIMARY KEY` : isPg ? `${bufCol("id")} bigserial PRIMARY KEY` : `${bufCol("id")} bigint NOT NULL AUTO_INCREMENT PRIMARY KEY`;
|
|
500
558
|
const tables = [
|
|
@@ -507,7 +565,7 @@ async function ensureTypeOrmDurableSchema(dataSource) {
|
|
|
507
565
|
${runsCol("wakeAt")} ${ts}, ${runsCol("lockedBy")} ${str}, ${runsCol("lockedUntil")} ${ts},
|
|
508
566
|
${runsCol("awaitingDecisionTaskId")} ${str},
|
|
509
567
|
${runsCol("recoveryAttempts")} ${int}, ${runsCol("tags")} ${txt}, ${runsCol("searchAttributes")} ${txt},
|
|
510
|
-
${runsCol("priority")} ${int},
|
|
568
|
+
${runsCol("priority")} ${int}, ${runsCol("origin")} ${str},
|
|
511
569
|
${runsCol("createdAt")} ${ts} NOT NULL, ${runsCol("updatedAt")} ${ts} NOT NULL
|
|
512
570
|
)`,
|
|
513
571
|
`CREATE TABLE IF NOT EXISTS ${checkpoints} (
|
|
@@ -532,6 +590,12 @@ async function ensureTypeOrmDurableSchema(dataSource) {
|
|
|
532
590
|
)`,
|
|
533
591
|
`CREATE TABLE IF NOT EXISTS ${buffered} (
|
|
534
592
|
${bufferedId}, ${bufCol("token")} ${str} NOT NULL, ${bufCol("payload")} ${txt}
|
|
593
|
+
)`,
|
|
594
|
+
// Caller-minted uuid PK (engine.publishEvent), not auto-increment — unlike durable_buffered_signals
|
|
595
|
+
// above, removeBufferedEvent needs to target the EXACT id it was buffered with.
|
|
596
|
+
`CREATE TABLE IF NOT EXISTS ${bufferedEvents} (
|
|
597
|
+
${bevCol("id")} ${str} PRIMARY KEY, ${bevCol("name")} ${str} NOT NULL,
|
|
598
|
+
${bevCol("payload")} ${txt}, ${bevCol("publishedAt")} ${ts} NOT NULL
|
|
535
599
|
)`
|
|
536
600
|
];
|
|
537
601
|
const additive = {
|
|
@@ -567,6 +631,14 @@ async function ensureTypeOrmDurableSchema(dataSource) {
|
|
|
567
631
|
[
|
|
568
632
|
"priority",
|
|
569
633
|
int
|
|
634
|
+
],
|
|
635
|
+
// Nullable and NOT back-filled with a value: every row that predates the column keeps a NULL
|
|
636
|
+
// origin, which the store reads as `undefined` = "unknown origin". There is no honest value to
|
|
637
|
+
// back-fill — the origin is derived from the registration that created the run, which is long
|
|
638
|
+
// gone by the time this ALTER runs.
|
|
639
|
+
[
|
|
640
|
+
"origin",
|
|
641
|
+
str
|
|
570
642
|
]
|
|
571
643
|
],
|
|
572
644
|
durable_step_checkpoints: [
|
|
@@ -643,6 +715,11 @@ async function ensureTypeOrmDurableSchema(dataSource) {
|
|
|
643
715
|
"durable_buffered_signals_token_idx",
|
|
644
716
|
`${buffered} (${bufCol("token")})`
|
|
645
717
|
],
|
|
718
|
+
// buffered events are scanned oldest-first per name — one composite index serves both.
|
|
719
|
+
[
|
|
720
|
+
"durable_buffered_events_name_published_at_idx",
|
|
721
|
+
`${bufferedEvents} (${bevCol("name")}, ${bevCol("publishedAt")})`
|
|
722
|
+
],
|
|
646
723
|
// Search-attribute pushdown: equality + range predicates probe by (key, value). Two composite
|
|
647
724
|
// indexes — one per typed column — so a numeric range or a string equality is an index scan.
|
|
648
725
|
[
|
|
@@ -705,6 +782,9 @@ var TypeOrmStateStore = class {
|
|
|
705
782
|
buffered() {
|
|
706
783
|
return this.dataSource.getRepository(BufferedSignalEntity);
|
|
707
784
|
}
|
|
785
|
+
bufferedEvents() {
|
|
786
|
+
return this.dataSource.getRepository(BufferedEventEntity);
|
|
787
|
+
}
|
|
708
788
|
attributes() {
|
|
709
789
|
return this.dataSource.getRepository(RunAttributeEntity);
|
|
710
790
|
}
|
|
@@ -738,6 +818,7 @@ var TypeOrmStateStore = class {
|
|
|
738
818
|
if ("tags" in patch) update.tags = patch.tags ?? null;
|
|
739
819
|
if ("searchAttributes" in patch) update.searchAttributes = patch.searchAttributes ?? null;
|
|
740
820
|
if ("priority" in patch) update.priority = patch.priority ?? null;
|
|
821
|
+
if ("origin" in patch) update.origin = patch.origin ?? null;
|
|
741
822
|
if ("createdAt" in patch) update.createdAt = patch.createdAt;
|
|
742
823
|
if ("updatedAt" in patch) update.updatedAt = patch.updatedAt;
|
|
743
824
|
const result = await this.runs().createQueryBuilder().update().set(update).where({
|
|
@@ -851,6 +932,9 @@ var TypeOrmStateStore = class {
|
|
|
851
932
|
if (query.workflow) qb.andWhere("r.workflow = :workflow", {
|
|
852
933
|
workflow: query.workflow
|
|
853
934
|
});
|
|
935
|
+
if (query.origin !== void 0) qb.andWhere("r.origin = :origin", {
|
|
936
|
+
origin: query.origin
|
|
937
|
+
});
|
|
854
938
|
if (query.status) qb.andWhere("r.status = :status", {
|
|
855
939
|
status: query.status
|
|
856
940
|
});
|
|
@@ -999,6 +1083,36 @@ var TypeOrmStateStore = class {
|
|
|
999
1083
|
payload: e.payload ?? void 0
|
|
1000
1084
|
};
|
|
1001
1085
|
}
|
|
1086
|
+
async bufferEvent(input) {
|
|
1087
|
+
await this.bufferedEvents().save({
|
|
1088
|
+
id: input.id,
|
|
1089
|
+
name: input.name,
|
|
1090
|
+
payload: input.payload ?? null,
|
|
1091
|
+
publishedAt: new Date(input.publishedAt)
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
async listBufferedEvents(name, limit) {
|
|
1095
|
+
const rows = await this.bufferedEvents().find({
|
|
1096
|
+
where: {
|
|
1097
|
+
name
|
|
1098
|
+
},
|
|
1099
|
+
order: {
|
|
1100
|
+
publishedAt: "ASC"
|
|
1101
|
+
},
|
|
1102
|
+
take: limit
|
|
1103
|
+
});
|
|
1104
|
+
return rows.map((e) => ({
|
|
1105
|
+
id: e.id,
|
|
1106
|
+
payload: e.payload ?? void 0,
|
|
1107
|
+
publishedAt: e.publishedAt.getTime()
|
|
1108
|
+
}));
|
|
1109
|
+
}
|
|
1110
|
+
async removeBufferedEvent(id) {
|
|
1111
|
+
const result = await this.bufferedEvents().delete({
|
|
1112
|
+
id
|
|
1113
|
+
});
|
|
1114
|
+
return result.affected === 1;
|
|
1115
|
+
}
|
|
1002
1116
|
};
|
|
1003
1117
|
function toRunEntity(run) {
|
|
1004
1118
|
return {
|
|
@@ -1023,6 +1137,8 @@ function toRunEntity(run) {
|
|
|
1023
1137
|
tags: run.tags ?? null,
|
|
1024
1138
|
searchAttributes: run.searchAttributes ?? null,
|
|
1025
1139
|
priority: run.priority ?? null,
|
|
1140
|
+
// Absent origin stays SQL NULL — "unknown", never coerced into a real-looking library name.
|
|
1141
|
+
origin: run.origin ?? null,
|
|
1026
1142
|
createdAt: run.createdAt,
|
|
1027
1143
|
updatedAt: run.updatedAt
|
|
1028
1144
|
};
|
|
@@ -1045,6 +1161,8 @@ function fromRunEntity(e) {
|
|
|
1045
1161
|
tags: e.tags ?? void 0,
|
|
1046
1162
|
searchAttributes: e.searchAttributes ?? void 0,
|
|
1047
1163
|
priority: e.priority ?? void 0,
|
|
1164
|
+
// NULL (a row written before the column existed) surfaces as `undefined` = unknown origin.
|
|
1165
|
+
origin: e.origin ?? void 0,
|
|
1048
1166
|
createdAt: e.createdAt,
|
|
1049
1167
|
updatedAt: e.updatedAt
|
|
1050
1168
|
};
|
|
@@ -1099,6 +1217,7 @@ function fromCheckpointEntity(e) {
|
|
|
1099
1217
|
__name(fromCheckpointEntity, "fromCheckpointEntity");
|
|
1100
1218
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1101
1219
|
0 && (module.exports = {
|
|
1220
|
+
BufferedEventEntity,
|
|
1102
1221
|
BufferedSignalEntity,
|
|
1103
1222
|
ENTITIES,
|
|
1104
1223
|
JSON_BLOB_COLUMNS,
|