@dudousxd/nestjs-durable-store-mikro-orm 0.17.0 → 0.18.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 +70 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -10
- package/dist/index.d.ts +33 -10
- package/dist/index.js +70 -26
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -84,11 +84,28 @@ var BufferedSignalEntity = class {
|
|
|
84
84
|
token;
|
|
85
85
|
payload;
|
|
86
86
|
};
|
|
87
|
+
function namespaceFilterCond(args) {
|
|
88
|
+
if (args.namespace === void 0) return {};
|
|
89
|
+
return {
|
|
90
|
+
namespace: args.namespace
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
__name(namespaceFilterCond, "namespaceFilterCond");
|
|
87
94
|
function durableEntities(options = {}) {
|
|
88
95
|
const col = columnNamer(options.naming ?? "snake_case");
|
|
89
96
|
const workflowRuns = new EntitySchema({
|
|
90
97
|
class: WorkflowRunEntity,
|
|
91
98
|
tableName: "durable_workflow_runs",
|
|
99
|
+
// Global filter: confines every read to the tenant's namespace when the store is scoped.
|
|
100
|
+
// The `cond` returns `{}` (no-op) when the `namespace` arg is `undefined`, so an unscoped
|
|
101
|
+
// (operator / control-plane) store sees all rows unchanged — existing behaviour is preserved.
|
|
102
|
+
filters: {
|
|
103
|
+
namespace: {
|
|
104
|
+
name: "namespace",
|
|
105
|
+
cond: namespaceFilterCond,
|
|
106
|
+
default: true
|
|
107
|
+
}
|
|
108
|
+
},
|
|
92
109
|
// Indexes mirror the Prisma adapter so a store swap keeps the same plan. The poller hits these
|
|
93
110
|
// every tick: `(status, wakeAt)` serves both the due-timer scan (status='suspended' AND wakeAt<=now)
|
|
94
111
|
// and, via its `status` prefix, the pending/incomplete status lookups; `(workflow, status)` serves
|
|
@@ -614,25 +631,51 @@ async function alignDurableCollation(orm) {
|
|
|
614
631
|
__name(alignDurableCollation, "alignDurableCollation");
|
|
615
632
|
|
|
616
633
|
// src/mikro-orm-state-store.ts
|
|
617
|
-
var MikroOrmStateStore = class {
|
|
634
|
+
var MikroOrmStateStore = class _MikroOrmStateStore {
|
|
618
635
|
static {
|
|
619
636
|
__name(this, "MikroOrmStateStore");
|
|
620
637
|
}
|
|
621
638
|
orm;
|
|
622
|
-
|
|
639
|
+
scopeNamespace;
|
|
640
|
+
constructor(orm, opts) {
|
|
623
641
|
this.orm = orm;
|
|
642
|
+
this.scopeNamespace = opts?.scope?.namespace;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Derive a store confined to a single tenant `scope.namespace`, sharing this store's ORM (no new
|
|
646
|
+
* connection). Turns the operator (unscoped) store into a tenant-boundary view at wiring time —
|
|
647
|
+
* used by the NestJS module's `scopeReads` option, which receives a pre-built store and can't
|
|
648
|
+
* reconstruct it. Pass `{ namespace: undefined }` for the unscoped operator view.
|
|
649
|
+
*/
|
|
650
|
+
withScope(scope) {
|
|
651
|
+
return new _MikroOrmStateStore(this.orm, {
|
|
652
|
+
scope
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Create a forked EntityManager and activate the `namespace` global filter with the store's
|
|
657
|
+
* scope (if any). All read operations go through this so the tenant boundary is applied
|
|
658
|
+
* uniformly. Write operations (nativeDelete, nativeUpdate, upsert, insertMany) bypass global
|
|
659
|
+
* filters in MikroORM and are unaffected.
|
|
660
|
+
*/
|
|
661
|
+
fork() {
|
|
662
|
+
const em = this.orm.em.fork();
|
|
663
|
+
em.setFilterParams("namespace", {
|
|
664
|
+
namespace: this.scopeNamespace
|
|
665
|
+
});
|
|
666
|
+
return em;
|
|
624
667
|
}
|
|
625
668
|
async ensureSchema() {
|
|
626
669
|
await ensureMikroOrmDurableSchema(this.orm);
|
|
627
670
|
}
|
|
628
671
|
async createRun(run) {
|
|
629
|
-
const em = this.
|
|
672
|
+
const em = this.fork();
|
|
630
673
|
em.create(WorkflowRunEntity, toRunEntity(run));
|
|
631
674
|
await em.flush();
|
|
632
675
|
await this.reindexAttributes(run.id, run.searchAttributes);
|
|
633
676
|
}
|
|
634
677
|
async updateRun(runId, patch) {
|
|
635
|
-
const em = this.
|
|
678
|
+
const em = this.fork();
|
|
636
679
|
const entity = await em.findOneOrFail(WorkflowRunEntity, {
|
|
637
680
|
id: runId
|
|
638
681
|
});
|
|
@@ -646,7 +689,7 @@ var MikroOrmStateStore = class {
|
|
|
646
689
|
/** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors
|
|
647
690
|
* the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */
|
|
648
691
|
async reindexAttributes(runId, attributes, forked) {
|
|
649
|
-
const em = forked ?? this.
|
|
692
|
+
const em = forked ?? this.fork();
|
|
650
693
|
await em.nativeDelete(RunAttributeEntity, {
|
|
651
694
|
runId
|
|
652
695
|
});
|
|
@@ -654,14 +697,14 @@ var MikroOrmStateStore = class {
|
|
|
654
697
|
if (rows.length) await em.insertMany(RunAttributeEntity, rows);
|
|
655
698
|
}
|
|
656
699
|
async getRun(runId) {
|
|
657
|
-
const em = this.
|
|
700
|
+
const em = this.fork();
|
|
658
701
|
const entity = await em.findOne(WorkflowRunEntity, {
|
|
659
702
|
id: runId
|
|
660
703
|
});
|
|
661
704
|
return entity ? fromRunEntity(entity) : null;
|
|
662
705
|
}
|
|
663
706
|
async deleteRun(runId) {
|
|
664
|
-
const em = this.
|
|
707
|
+
const em = this.fork();
|
|
665
708
|
await em.nativeDelete(StepCheckpointEntity, {
|
|
666
709
|
runId
|
|
667
710
|
});
|
|
@@ -677,7 +720,7 @@ var MikroOrmStateStore = class {
|
|
|
677
720
|
}
|
|
678
721
|
async pruneTerminalRuns(policy, nowMs, limit) {
|
|
679
722
|
if (policy.statuses.length === 0 || limit <= 0) return 0;
|
|
680
|
-
const em = this.
|
|
723
|
+
const em = this.fork();
|
|
681
724
|
const status = {
|
|
682
725
|
$in: policy.statuses
|
|
683
726
|
};
|
|
@@ -743,7 +786,7 @@ var MikroOrmStateStore = class {
|
|
|
743
786
|
return idList.length;
|
|
744
787
|
}
|
|
745
788
|
async getCheckpoint(runId, seq) {
|
|
746
|
-
const em = this.
|
|
789
|
+
const em = this.fork();
|
|
747
790
|
const entity = await em.findOne(StepCheckpointEntity, {
|
|
748
791
|
runId,
|
|
749
792
|
seq
|
|
@@ -751,12 +794,12 @@ var MikroOrmStateStore = class {
|
|
|
751
794
|
return entity ? fromCheckpointEntity(entity) : null;
|
|
752
795
|
}
|
|
753
796
|
async saveCheckpoint(checkpoint) {
|
|
754
|
-
const em = this.
|
|
797
|
+
const em = this.fork();
|
|
755
798
|
await em.upsert(StepCheckpointEntity, toCheckpointEntity(checkpoint));
|
|
756
799
|
await em.flush();
|
|
757
800
|
}
|
|
758
801
|
async transaction(work) {
|
|
759
|
-
return this.
|
|
802
|
+
return this.fork().transactional(async (em) => work({
|
|
760
803
|
raw: em,
|
|
761
804
|
saveCheckpoint: /* @__PURE__ */ __name(async (cp) => {
|
|
762
805
|
await em.upsert(StepCheckpointEntity, toCheckpointEntity(cp));
|
|
@@ -764,7 +807,7 @@ var MikroOrmStateStore = class {
|
|
|
764
807
|
}));
|
|
765
808
|
}
|
|
766
809
|
async listIncompleteRuns(namespace) {
|
|
767
|
-
const em = this.
|
|
810
|
+
const em = this.fork();
|
|
768
811
|
const rows = await em.find(WorkflowRunEntity, {
|
|
769
812
|
status: {
|
|
770
813
|
$in: [
|
|
@@ -779,7 +822,7 @@ var MikroOrmStateStore = class {
|
|
|
779
822
|
return rows.map(fromRunEntity);
|
|
780
823
|
}
|
|
781
824
|
async listPendingRuns(limit, namespace) {
|
|
782
|
-
const em = this.
|
|
825
|
+
const em = this.fork();
|
|
783
826
|
const rows = await em.find(WorkflowRunEntity, {
|
|
784
827
|
status: "pending",
|
|
785
828
|
...namespace !== void 0 ? {
|
|
@@ -794,7 +837,7 @@ var MikroOrmStateStore = class {
|
|
|
794
837
|
return rows.map(fromRunEntity);
|
|
795
838
|
}
|
|
796
839
|
async listDueTimers(nowMs, namespace) {
|
|
797
|
-
const em = this.
|
|
840
|
+
const em = this.fork();
|
|
798
841
|
const rows = await em.find(WorkflowRunEntity, {
|
|
799
842
|
status: "suspended",
|
|
800
843
|
wakeAt: {
|
|
@@ -808,7 +851,7 @@ var MikroOrmStateStore = class {
|
|
|
808
851
|
return rows.map(fromRunEntity);
|
|
809
852
|
}
|
|
810
853
|
async tryLockRun(runId, owner, leaseUntilMs, nowMs) {
|
|
811
|
-
const em = this.
|
|
854
|
+
const em = this.fork();
|
|
812
855
|
const affected = await em.nativeUpdate(WorkflowRunEntity, {
|
|
813
856
|
id: runId,
|
|
814
857
|
$or: [
|
|
@@ -828,7 +871,7 @@ var MikroOrmStateStore = class {
|
|
|
828
871
|
return affected === 1;
|
|
829
872
|
}
|
|
830
873
|
async releaseRunLock(runId) {
|
|
831
|
-
const em = this.
|
|
874
|
+
const em = this.fork();
|
|
832
875
|
await em.nativeUpdate(WorkflowRunEntity, {
|
|
833
876
|
id: runId
|
|
834
877
|
}, {
|
|
@@ -837,7 +880,7 @@ var MikroOrmStateStore = class {
|
|
|
837
880
|
});
|
|
838
881
|
}
|
|
839
882
|
async renewRunLock(runId, owner, leaseUntilMs) {
|
|
840
|
-
const em = this.
|
|
883
|
+
const em = this.fork();
|
|
841
884
|
const affected = await em.nativeUpdate(WorkflowRunEntity, {
|
|
842
885
|
id: runId,
|
|
843
886
|
lockedBy: owner
|
|
@@ -847,7 +890,7 @@ var MikroOrmStateStore = class {
|
|
|
847
890
|
return affected === 1;
|
|
848
891
|
}
|
|
849
892
|
async listRuns(query) {
|
|
850
|
-
const em = this.
|
|
893
|
+
const em = this.fork();
|
|
851
894
|
const where = {};
|
|
852
895
|
if (query.workflow) where.workflow = query.workflow;
|
|
853
896
|
if (query.namespace !== void 0) where.namespace = query.namespace;
|
|
@@ -873,6 +916,7 @@ var MikroOrmStateStore = class {
|
|
|
873
916
|
createdAt: "desc"
|
|
874
917
|
};
|
|
875
918
|
if (query.tag || query.attributes?.length) {
|
|
919
|
+
if (this.scopeNamespace !== void 0) where.namespace = this.scopeNamespace;
|
|
876
920
|
const quote = this.idQuote(em);
|
|
877
921
|
const cols = this.attributeColumns(em);
|
|
878
922
|
const qb = em.createQueryBuilder(WorkflowRunEntity, "r").where(where).orderBy(orderBy);
|
|
@@ -955,7 +999,7 @@ var MikroOrmStateStore = class {
|
|
|
955
999
|
return (id) => `${ch}${id}${ch}`;
|
|
956
1000
|
}
|
|
957
1001
|
async listCheckpoints(runId) {
|
|
958
|
-
const em = this.
|
|
1002
|
+
const em = this.fork();
|
|
959
1003
|
const rows = await em.find(StepCheckpointEntity, {
|
|
960
1004
|
runId
|
|
961
1005
|
}, {
|
|
@@ -966,7 +1010,7 @@ var MikroOrmStateStore = class {
|
|
|
966
1010
|
return rows.map(fromCheckpointEntity);
|
|
967
1011
|
}
|
|
968
1012
|
async getLatestCheckpointByName(runId, name) {
|
|
969
|
-
const em = this.
|
|
1013
|
+
const em = this.fork();
|
|
970
1014
|
const entity = await em.findOne(StepCheckpointEntity, {
|
|
971
1015
|
runId,
|
|
972
1016
|
name
|
|
@@ -979,7 +1023,7 @@ var MikroOrmStateStore = class {
|
|
|
979
1023
|
}
|
|
980
1024
|
async listCheckpointsByNamePrefix(runId, prefixes) {
|
|
981
1025
|
if (prefixes.length === 0) return [];
|
|
982
|
-
const em = this.
|
|
1026
|
+
const em = this.fork();
|
|
983
1027
|
const rows = await em.find(StepCheckpointEntity, {
|
|
984
1028
|
runId,
|
|
985
1029
|
$or: prefixes.map((p) => ({
|
|
@@ -995,7 +1039,7 @@ var MikroOrmStateStore = class {
|
|
|
995
1039
|
return rows.map(fromCheckpointEntity);
|
|
996
1040
|
}
|
|
997
1041
|
async putSignalWaiter(waiter) {
|
|
998
|
-
const em = this.
|
|
1042
|
+
const em = this.fork();
|
|
999
1043
|
await em.upsert(SignalWaiterEntity, {
|
|
1000
1044
|
token: waiter.token,
|
|
1001
1045
|
runId: waiter.runId,
|
|
@@ -1005,7 +1049,7 @@ var MikroOrmStateStore = class {
|
|
|
1005
1049
|
await em.flush();
|
|
1006
1050
|
}
|
|
1007
1051
|
async takeSignalWaiter(token) {
|
|
1008
|
-
const em = this.
|
|
1052
|
+
const em = this.fork();
|
|
1009
1053
|
const entity = await em.findOne(SignalWaiterEntity, {
|
|
1010
1054
|
token
|
|
1011
1055
|
});
|
|
@@ -1020,7 +1064,7 @@ var MikroOrmStateStore = class {
|
|
|
1020
1064
|
return waiter;
|
|
1021
1065
|
}
|
|
1022
1066
|
async listSignalWaiters(prefix) {
|
|
1023
|
-
const em = this.
|
|
1067
|
+
const em = this.fork();
|
|
1024
1068
|
const rows = await em.find(SignalWaiterEntity, {
|
|
1025
1069
|
token: {
|
|
1026
1070
|
$like: `${prefix}%`
|
|
@@ -1034,7 +1078,7 @@ var MikroOrmStateStore = class {
|
|
|
1034
1078
|
}));
|
|
1035
1079
|
}
|
|
1036
1080
|
async bufferSignal(token, payload) {
|
|
1037
|
-
const em = this.
|
|
1081
|
+
const em = this.fork();
|
|
1038
1082
|
const e = new BufferedSignalEntity();
|
|
1039
1083
|
e.token = token;
|
|
1040
1084
|
e.payload = payload ?? null;
|
|
@@ -1042,7 +1086,7 @@ var MikroOrmStateStore = class {
|
|
|
1042
1086
|
await em.flush();
|
|
1043
1087
|
}
|
|
1044
1088
|
async takeBufferedSignal(token) {
|
|
1045
|
-
const em = this.
|
|
1089
|
+
const em = this.fork();
|
|
1046
1090
|
const entity = await em.findOne(BufferedSignalEntity, {
|
|
1047
1091
|
token
|
|
1048
1092
|
}, {
|