@dudousxd/nestjs-durable-store-mikro-orm 0.27.0 → 0.28.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.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _mikro_orm_core from '@mikro-orm/core';
2
2
  import { EntityRepository, EntityRepositoryType, EntitySchema, MikroORM } from '@mikro-orm/core';
3
- import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, SignalWaiter } from '@dudousxd/nestjs-durable-core';
3
+ import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, SignalWaiter, ChildWait } from '@dudousxd/nestjs-durable-core';
4
4
 
5
5
  /**
6
6
  * Custom repositories for the durable entities, so a host app can `@InjectRepository`/inject a
@@ -185,8 +185,9 @@ declare class MikroOrmStateStore implements StateStore {
185
185
  */
186
186
  private fork;
187
187
  ensureSchema(): Promise<void>;
188
+ tryAdmitSingleton(runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number): Promise<boolean>;
188
189
  createRun(run: WorkflowRun): Promise<void>;
189
- updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void>;
190
+ updateRun(runId: string, inputPatch: Partial<WorkflowRun>): Promise<void>;
190
191
  /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors
191
192
  * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */
192
193
  private reindexAttributes;
@@ -290,6 +291,10 @@ declare class MikroOrmStateStore implements StateStore {
290
291
  putSignalWaiter(waiter: SignalWaiter): Promise<void>;
291
292
  takeSignalWaiter(token: string): Promise<SignalWaiter | null>;
292
293
  listSignalWaiters(prefix: string): Promise<SignalWaiter[]>;
294
+ registerChildWaits(entries: ChildWait[]): Promise<void>;
295
+ compactCheckpoints(runId: string, fromSeq: number, toSeq: number, into: StepCheckpoint): Promise<void>;
296
+ listSignalWaitersByRun(runIds: string[]): Promise<SignalWaiter[]>;
297
+ hasSignalWaiter(runId: string, tokenPrefix: string): Promise<boolean>;
293
298
  removeSignalWaiter(waiter: SignalWaiter): Promise<void>;
294
299
  bufferSignal(token: string, payload: unknown): Promise<void>;
295
300
  takeBufferedSignal(token: string): Promise<{
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _mikro_orm_core from '@mikro-orm/core';
2
2
  import { EntityRepository, EntityRepositoryType, EntitySchema, MikroORM } from '@mikro-orm/core';
3
- import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, SignalWaiter } from '@dudousxd/nestjs-durable-core';
3
+ import { StepKind, RunStatus, StateStore, WorkflowRun, RetentionPolicy, StepCheckpoint, RunQuery, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScheduleRecord, ScheduleQuery, SignalWaiter, ChildWait } from '@dudousxd/nestjs-durable-core';
4
4
 
5
5
  /**
6
6
  * Custom repositories for the durable entities, so a host app can `@InjectRepository`/inject a
@@ -185,8 +185,9 @@ declare class MikroOrmStateStore implements StateStore {
185
185
  */
186
186
  private fork;
187
187
  ensureSchema(): Promise<void>;
188
+ tryAdmitSingleton(runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number): Promise<boolean>;
188
189
  createRun(run: WorkflowRun): Promise<void>;
189
- updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void>;
190
+ updateRun(runId: string, inputPatch: Partial<WorkflowRun>): Promise<void>;
190
191
  /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors
191
192
  * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */
192
193
  private reindexAttributes;
@@ -290,6 +291,10 @@ declare class MikroOrmStateStore implements StateStore {
290
291
  putSignalWaiter(waiter: SignalWaiter): Promise<void>;
291
292
  takeSignalWaiter(token: string): Promise<SignalWaiter | null>;
292
293
  listSignalWaiters(prefix: string): Promise<SignalWaiter[]>;
294
+ registerChildWaits(entries: ChildWait[]): Promise<void>;
295
+ compactCheckpoints(runId: string, fromSeq: number, toSeq: number, into: StepCheckpoint): Promise<void>;
296
+ listSignalWaitersByRun(runIds: string[]): Promise<SignalWaiter[]>;
297
+ hasSignalWaiter(runId: string, tokenPrefix: string): Promise<boolean>;
293
298
  removeSignalWaiter(waiter: SignalWaiter): Promise<void>;
294
299
  bufferSignal(token: string, payload: unknown): Promise<void>;
295
300
  takeBufferedSignal(token: string): Promise<{
package/dist/index.js CHANGED
@@ -472,6 +472,15 @@ function durableEntities(options = {}) {
472
472
  class: SignalWaiterEntity,
473
473
  tableName: "durable_signal_waiters",
474
474
  repository: /* @__PURE__ */ __name(() => SignalWaiterRepository, "repository"),
475
+ // A run's waiters: the `ctx.all` join barrier probes them once per settled child.
476
+ indexes: [
477
+ {
478
+ name: "durable_signal_waiters_run_id_idx",
479
+ properties: [
480
+ "runId"
481
+ ]
482
+ }
483
+ ],
475
484
  properties: {
476
485
  token: {
477
486
  type: "string",
@@ -633,7 +642,7 @@ __name(durableEntities, "durableEntities");
633
642
  var ENTITIES = durableEntities();
634
643
 
635
644
  // src/mikro-orm-state-store.ts
636
- import { ENGINE_MINTED_TAG_PREFIXES, RUN_VALUE_FACET_LIMIT, TERMINAL_RUN_STATUSES, attributePredicateOperands, axisIsRunColumn, facetOrigin, mergeRunFacetRows, normalizeAttributeRows, parseDuration } from "@dudousxd/nestjs-durable-core";
645
+ import { ENGINE_MINTED_TAG_PREFIXES, RUN_VALUE_FACET_LIMIT, SINGLETON_ACTIVE_STATUSES, TERMINAL_RUN_STATUSES, attributePredicateOperands, axisIsRunColumn, clearTerminalSingletonAdmission, facetOrigin, mergeRunFacetRows, normalizeAttributeRows, parseDuration, singletonAdmissionDenialPatch, singletonAdmissionTags } from "@dudousxd/nestjs-durable-core";
637
646
  import { raw } from "@mikro-orm/core";
638
647
 
639
648
  // src/schema.ts
@@ -892,13 +901,50 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
892
901
  async ensureSchema() {
893
902
  await ensureMikroOrmDurableSchema(this.orm);
894
903
  }
904
+ async tryAdmitSingleton(runId, tag, workflow, limit, retryWakeAt) {
905
+ return this.fork().transactional(async (em) => {
906
+ const where = {
907
+ workflow,
908
+ status: {
909
+ $in: SINGLETON_ACTIVE_STATUSES
910
+ },
911
+ ...this.scopeNamespace !== void 0 ? {
912
+ namespace: this.scopeNamespace
913
+ } : {}
914
+ };
915
+ await em.nativeUpdate(WorkflowRunEntity, where, {
916
+ workflow
917
+ });
918
+ const rows = await em.find(WorkflowRunEntity, where);
919
+ const runs = rows.map(fromRunEntity);
920
+ const tags = singletonAdmissionTags(runs, runId, tag, workflow, limit);
921
+ if (!tags) {
922
+ const patch = singletonAdmissionDenialPatch(runs, runId, tag, workflow, retryWakeAt);
923
+ if (patch) await em.nativeUpdate(WorkflowRunEntity, {
924
+ id: runId
925
+ }, {
926
+ status: "suspended",
927
+ wakeAt: new Date(patch.wakeAt),
928
+ updatedAt: patch.updatedAt
929
+ });
930
+ return false;
931
+ }
932
+ await em.nativeUpdate(WorkflowRunEntity, {
933
+ id: runId
934
+ }, {
935
+ tags
936
+ });
937
+ return true;
938
+ });
939
+ }
895
940
  async createRun(run) {
896
941
  const em = this.fork();
897
942
  em.create(WorkflowRunEntity, toRunEntity(run));
898
943
  await em.flush();
899
944
  await this.reindexAttributes(run.id, run.searchAttributes);
900
945
  }
901
- async updateRun(runId, patch) {
946
+ async updateRun(runId, inputPatch) {
947
+ const patch = inputPatch.status && TERMINAL_RUN_STATUSES.includes(inputPatch.status) ? await clearTerminalSingletonAdmission(runId, inputPatch, (id) => this.withScope({}).getRun(id)) : inputPatch;
902
948
  const em = this.fork();
903
949
  const entity = await em.findOneOrFail(WorkflowRunEntity, {
904
950
  id: runId
@@ -1561,6 +1607,66 @@ var MikroOrmStateStore = class _MikroOrmStateStore {
1561
1607
  parallelGroup: e.parallelGroup ?? void 0
1562
1608
  }));
1563
1609
  }
1610
+ async registerChildWaits(entries) {
1611
+ if (entries.length === 0) return;
1612
+ await this.fork().transactional(async (em) => {
1613
+ await em.upsertMany(SignalWaiterEntity, entries.map(({ waiter }) => ({
1614
+ token: waiter.token,
1615
+ runId: waiter.runId,
1616
+ seq: waiter.seq,
1617
+ parallelGroup: waiter.parallelGroup ?? null
1618
+ })));
1619
+ await em.upsertMany(StepCheckpointEntity, entries.map(({ checkpoint }) => toCheckpointEntity(checkpoint)));
1620
+ });
1621
+ }
1622
+ async compactCheckpoints(runId, fromSeq, toSeq, into) {
1623
+ await this.fork().transactional(async (em) => {
1624
+ await em.nativeDelete(StepCheckpointEntity, {
1625
+ runId,
1626
+ seq: {
1627
+ $gte: fromSeq,
1628
+ $lte: toSeq
1629
+ }
1630
+ });
1631
+ await em.upsert(StepCheckpointEntity, toCheckpointEntity(into));
1632
+ });
1633
+ }
1634
+ async listSignalWaitersByRun(runIds) {
1635
+ if (runIds.length === 0) return [];
1636
+ const rows = await this.fork().find(SignalWaiterEntity, {
1637
+ runId: {
1638
+ $in: runIds
1639
+ }
1640
+ });
1641
+ return rows.map((e) => ({
1642
+ token: e.token,
1643
+ runId: e.runId,
1644
+ seq: e.seq,
1645
+ parallelGroup: e.parallelGroup ?? void 0
1646
+ }));
1647
+ }
1648
+ async hasSignalWaiter(runId, tokenPrefix) {
1649
+ const em = this.fork();
1650
+ const where = {
1651
+ runId,
1652
+ token: {
1653
+ $like: `${tokenPrefix}%`
1654
+ }
1655
+ };
1656
+ const first = await em.findOne(SignalWaiterEntity, where, {
1657
+ fields: [
1658
+ "token"
1659
+ ]
1660
+ });
1661
+ if (!first) return false;
1662
+ if (first.token.startsWith(tokenPrefix)) return true;
1663
+ const rows = await em.find(SignalWaiterEntity, where, {
1664
+ fields: [
1665
+ "token"
1666
+ ]
1667
+ });
1668
+ return rows.some((r) => r.token.startsWith(tokenPrefix));
1669
+ }
1564
1670
  async removeSignalWaiter(waiter) {
1565
1671
  const em = this.fork();
1566
1672
  await em.nativeDelete(SignalWaiterEntity, {