@dudousxd/nestjs-durable-testing 0.17.0 → 0.19.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.js CHANGED
@@ -187,7 +187,7 @@ async function assertOutput(store, runId, expected) {
187
187
  }
188
188
  __name(assertOutput, "assertOutput");
189
189
  async function recordedSteps(store, runId) {
190
- return (await store.listCheckpoints(runId)).map((cp) => cp.name);
190
+ return (await store.listCheckpoints(runId)).map((cp2) => cp2.name);
191
191
  }
192
192
  __name(recordedSteps, "recordedSteps");
193
193
  async function assertStepsRan(store, runId, names) {
@@ -200,10 +200,10 @@ async function assertStepsRan(store, runId, names) {
200
200
  }
201
201
  __name(assertStepsRan, "assertStepsRan");
202
202
  async function assertStepAttempts(store, runId, name, attempts) {
203
- const cp = (await store.listCheckpoints(runId)).find((c) => c.name === name);
204
- if (!cp) throw new Error(`expected step "${name}" to have run, but it did not`);
205
- if (cp.attempts !== attempts) {
206
- throw new Error(`expected step "${name}" to take ${attempts} attempt(s), took ${cp.attempts}`);
203
+ const cp2 = (await store.listCheckpoints(runId)).find((c) => c.name === name);
204
+ if (!cp2) throw new Error(`expected step "${name}" to have run, but it did not`);
205
+ if (cp2.attempts !== attempts) {
206
+ throw new Error(`expected step "${name}" to take ${attempts} attempt(s), took ${cp2.attempts}`);
207
207
  }
208
208
  }
209
209
  __name(assertStepAttempts, "assertStepAttempts");
@@ -341,11 +341,11 @@ var MutableClock = class {
341
341
  this.current = current;
342
342
  }
343
343
  now = /* @__PURE__ */ __name(() => this.current, "now");
344
- set(ms) {
345
- this.current = ms;
344
+ set(ms2) {
345
+ this.current = ms2;
346
346
  }
347
- advance(ms) {
348
- this.current += ms;
347
+ advance(ms2) {
348
+ this.current += ms2;
349
349
  }
350
350
  };
351
351
  function createTestEngine() {
@@ -362,8 +362,8 @@ function createTestEngine() {
362
362
  store,
363
363
  transport,
364
364
  clock,
365
- async tick(ms) {
366
- clock.advance(ms);
365
+ async tick(ms2) {
366
+ clock.advance(ms2);
367
367
  return engine.resumeDueTimers(clock.now());
368
368
  },
369
369
  async run(workflow, input, runId, opts) {
@@ -384,7 +384,7 @@ async function assertReplayable(register, history) {
384
384
  lockedBy: void 0,
385
385
  lockedUntil: void 0
386
386
  });
387
- for (const cp of history.checkpoints) await store.saveCheckpoint(cp);
387
+ for (const cp2 of history.checkpoints) await store.saveCheckpoint(cp2);
388
388
  const engine = new WorkflowEngine2({
389
389
  store
390
390
  });
@@ -400,7 +400,352 @@ __name(assertReplayable, "assertReplayable");
400
400
 
401
401
  // src/state-store-conformance.ts
402
402
  import { SINGLETON_ADMITTED_TAG, WorkflowEngine as WorkflowEngine3 } from "@dudousxd/nestjs-durable-core";
403
- import { beforeEach, describe as describe2, expect as expect2, it as it2 } from "vitest";
403
+ import { beforeEach, describe as describe2, expect as expect3, it as it2 } from "vitest";
404
+
405
+ // src/checkpoint-aggregation-contract.ts
406
+ import { SUMMARY_CHILD_LIMIT, aggregatesCheckpoints, checkpointStatsOf, childIdsOf, pageFan, pageFanFromStore, queryCheckpointsOf, summarizeRunFromStore, summarizeTimeline } from "@dudousxd/nestjs-durable-core";
407
+ import { expect as expect2 } from "vitest";
408
+ var base = Date.parse("2026-06-11T00:00:00.000Z");
409
+ var ms = /* @__PURE__ */ __name((n) => new Date(base + n), "ms");
410
+ function cp(seq, over = {}) {
411
+ return {
412
+ runId: "r1",
413
+ seq,
414
+ name: "Lines.process",
415
+ kind: "remote",
416
+ stepId: `r1:${seq}`,
417
+ status: "completed",
418
+ output: {
419
+ n: seq
420
+ },
421
+ attempts: 1,
422
+ enqueuedAt: ms(seq * 10),
423
+ startedAt: ms(seq * 10 + 3),
424
+ finishedAt: ms(seq * 10 + 7),
425
+ ...over
426
+ };
427
+ }
428
+ __name(cp, "cp");
429
+ var child = /* @__PURE__ */ __name((seq, group, over = {}) => cp(seq, {
430
+ name: `signal:child:r1.all.${group.split(":")[1]}.${seq}`,
431
+ kind: "signal",
432
+ parallelGroup: group,
433
+ output: {
434
+ ok: true,
435
+ value: seq
436
+ },
437
+ ...over
438
+ }), "child");
439
+ var folded = /* @__PURE__ */ __name((seq, group, wave, from, n) => cp(seq, {
440
+ name: `fan:r1.all.${group.split(":")[1]}.w${wave}.`,
441
+ kind: "signal",
442
+ parallelGroup: group,
443
+ output: {
444
+ from,
445
+ values: Array.from({
446
+ length: n
447
+ }, (_, i) => i)
448
+ }
449
+ }), "folded");
450
+ function aggregationFixture() {
451
+ const rows = [
452
+ cp(0, {
453
+ name: "Lines.load",
454
+ kind: "local"
455
+ })
456
+ ];
457
+ rows.push(cp(1, {
458
+ name: "spawn:audit-1",
459
+ kind: "local",
460
+ output: "audit-1"
461
+ }));
462
+ for (let i = 0; i < 120; i++) {
463
+ const seq = 2 + i;
464
+ rows.push(cp(seq, {
465
+ parallelGroup: "steps:2:120",
466
+ ...i % 4 === 0 && i < 100 ? {
467
+ status: "failed",
468
+ attempts: 3,
469
+ error: {
470
+ message: `bad ${i}`
471
+ }
472
+ } : i >= 100 && i < 120 && i !== 105 && i !== 106 ? {
473
+ status: "pending",
474
+ output: void 0
475
+ } : i === 105 || i === 106 ? {
476
+ status: "running",
477
+ output: void 0
478
+ } : {}
479
+ }));
480
+ }
481
+ for (let i = 0; i < 5; i++) rows.push(cp(122 + i, {
482
+ parallelGroup: "steps:122:5"
483
+ }));
484
+ for (let i = 0; i < 30; i++) {
485
+ rows.push(cp(127 + i, {
486
+ parallelGroup: "steps:127:40000",
487
+ name: "Rows.score",
488
+ ...i >= 12 ? {
489
+ status: "pending",
490
+ output: void 0
491
+ } : {}
492
+ }));
493
+ }
494
+ for (let i = 0; i < 30; i++) {
495
+ rows.push(cp(157 + i, {
496
+ parallelGroup: "steps:157:60:failFast",
497
+ name: i % 2 === 0 ? "Check.a" : "Check.b",
498
+ ...i === 7 ? {
499
+ status: "failed",
500
+ error: {
501
+ message: "stop"
502
+ }
503
+ } : {}
504
+ }));
505
+ }
506
+ for (let i = 0; i < 60; i++) {
507
+ const seq = 187 + i;
508
+ rows.push(child(seq, "all:187:n80", {
509
+ ...i >= 50 ? {
510
+ status: "running",
511
+ output: void 0
512
+ } : i % 3 === 0 ? {
513
+ output: {
514
+ ok: false,
515
+ error: `child ${i}`
516
+ }
517
+ } : i % 7 === 1 ? {
518
+ status: "failed",
519
+ error: {
520
+ message: "lost"
521
+ }
522
+ } : {}
523
+ }));
524
+ }
525
+ rows.push(folded(247, "all:187:n80", 9, 60, 20));
526
+ rows.push(folded(300, "all:300:n3000:failFast", 0, 0, 1e3));
527
+ rows.push(folded(301, "all:300:n3000:failFast", 1, 1e3, 1e3));
528
+ rows.push(folded(302, "all:300:n3000:failFast", 2, 2e3, 0));
529
+ for (let i = 0; i < 4; i++) {
530
+ rows.push(child(303 + i, "all:300:n3000:failFast", {
531
+ status: "running",
532
+ output: void 0
533
+ }));
534
+ }
535
+ rows.push(child(400, "all:400:n3"));
536
+ rows.push(child(401, "all:400:n3", {
537
+ output: {
538
+ ok: false,
539
+ error: "narrow"
540
+ }
541
+ }));
542
+ rows.push(child(402, "all:400:n3", {
543
+ status: "running",
544
+ output: void 0
545
+ }));
546
+ for (let i = 0; i < 55; i++) {
547
+ rows.push(child(450 + i, "all:450", i === 54 ? {
548
+ output: {
549
+ ok: false
550
+ }
551
+ } : {}));
552
+ }
553
+ rows.push(cp(600, {
554
+ name: "Lines.report",
555
+ kind: "local",
556
+ status: "failed"
557
+ }));
558
+ return rows;
559
+ }
560
+ __name(aggregationFixture, "aggregationFixture");
561
+ var GROUPS = [
562
+ "steps:2:120",
563
+ "steps:122:5",
564
+ "steps:127:40000",
565
+ "steps:157:60:failFast",
566
+ "all:187:n80",
567
+ "all:300:n3000:failFast",
568
+ "all:400:n3",
569
+ "all:450",
570
+ "absent"
571
+ ];
572
+ var QUERIES = [
573
+ {},
574
+ {
575
+ offset: 10,
576
+ limit: 7
577
+ },
578
+ {
579
+ offset: 0,
580
+ limit: 500
581
+ },
582
+ {
583
+ offset: 118,
584
+ limit: 50
585
+ },
586
+ {
587
+ offset: 5e3
588
+ },
589
+ {
590
+ failedOnly: true
591
+ },
592
+ {
593
+ failedOnly: true,
594
+ offset: 3,
595
+ limit: 4
596
+ },
597
+ {
598
+ failedOnly: true,
599
+ offset: 15,
600
+ limit: 10
601
+ },
602
+ {
603
+ failedOnly: true,
604
+ offset: 1e3
605
+ }
606
+ ];
607
+ function comparable(stats) {
608
+ return stats.map(({ minName, maxName, ...rest }) => ({
609
+ ...rest,
610
+ uniform: minName === maxName
611
+ })).sort((a, b) => `${a.group}|${a.status}|${a.nameKind}`.localeCompare(`${b.group}|${b.status}|${b.nameKind}`));
612
+ }
613
+ __name(comparable, "comparable");
614
+ async function seed(store, run2) {
615
+ await store.createRun(run2());
616
+ for (const row of aggregationFixture()) await store.saveCheckpoint(row);
617
+ await store.createRun(run2({
618
+ id: "r2"
619
+ }));
620
+ for (let i = 0; i < 3; i++) {
621
+ await store.saveCheckpoint(cp(2 + i, {
622
+ runId: "r2",
623
+ stepId: `r2:${i}`,
624
+ parallelGroup: "steps:2:120",
625
+ status: "failed"
626
+ }));
627
+ }
628
+ }
629
+ __name(seed, "seed");
630
+ function registerCheckpointAggregationCases(t, getStore, run2) {
631
+ t("checkpointStats and queryCheckpoints agree with the in-memory reference", async () => {
632
+ const store = getStore();
633
+ expect2(store.checkpointStats).toBeDefined();
634
+ expect2(store.queryCheckpoints).toBeDefined();
635
+ if (!aggregatesCheckpoints(store)) return;
636
+ await seed(store, run2);
637
+ const full = await store.listCheckpoints("r1");
638
+ expect2(comparable(await store.checkpointStats("r1"))).toEqual(comparable(checkpointStatsOf(full)));
639
+ for (const group of GROUPS) {
640
+ expect2(comparable(await store.checkpointStats("r1", {
641
+ group
642
+ }))).toEqual(comparable(checkpointStatsOf(full, {
643
+ group
644
+ })));
645
+ }
646
+ expect2(await store.checkpointStats("nope")).toEqual([]);
647
+ const queries = [
648
+ {},
649
+ {
650
+ group: "steps:2:120"
651
+ },
652
+ {
653
+ group: "steps:2:120",
654
+ statuses: [
655
+ "failed"
656
+ ],
657
+ limit: 20
658
+ },
659
+ {
660
+ group: "steps:2:120",
661
+ offset: 30,
662
+ limit: 5
663
+ },
664
+ {
665
+ group: "all:187:n80",
666
+ statuses: [
667
+ "completed"
668
+ ],
669
+ namePrefixes: [
670
+ "signal:child:"
671
+ ]
672
+ },
673
+ {
674
+ excludeGroups: [
675
+ "steps:2:120",
676
+ "all:187:n80",
677
+ "all:450"
678
+ ]
679
+ },
680
+ {
681
+ excludeGroups: []
682
+ },
683
+ {
684
+ namePrefixes: [
685
+ "signal:child:",
686
+ "fan:",
687
+ "spawn:"
688
+ ],
689
+ offset: 200,
690
+ limit: 200
691
+ },
692
+ {
693
+ namePrefixes: [
694
+ "fan:"
695
+ ]
696
+ },
697
+ {
698
+ statuses: []
699
+ },
700
+ {
701
+ namePrefixes: []
702
+ },
703
+ {
704
+ statuses: [
705
+ "pending",
706
+ "running"
707
+ ],
708
+ offset: 3
709
+ }
710
+ ];
711
+ for (const query of queries) {
712
+ expect2(await store.queryCheckpoints("r1", query)).toEqual(queryCheckpointsOf(full, query));
713
+ }
714
+ });
715
+ t("a run detail read through the aggregates is the one summarizeTimeline builds", async () => {
716
+ const store = getStore();
717
+ if (!aggregatesCheckpoints(store)) return;
718
+ await seed(store, run2);
719
+ const full = await store.listCheckpoints("r1");
720
+ for (const over of [
721
+ 50,
722
+ 0,
723
+ 1e3
724
+ ]) {
725
+ const ids = childIdsOf(full);
726
+ const expected = {
727
+ ...summarizeTimeline(full, over),
728
+ children: ids.slice(0, SUMMARY_CHILD_LIMIT),
729
+ childCount: ids.length
730
+ };
731
+ expect2(await summarizeRunFromStore(store, "r1", over)).toEqual(expected);
732
+ }
733
+ });
734
+ t("a fan page read through the aggregates is the one pageFan builds", async () => {
735
+ const store = getStore();
736
+ if (!aggregatesCheckpoints(store)) return;
737
+ await seed(store, run2);
738
+ const full = await store.listCheckpoints("r1");
739
+ for (const group of GROUPS) {
740
+ for (const query of QUERIES) {
741
+ expect2(await pageFanFromStore(store, "r1", group, query)).toEqual(pageFan(full, group, query));
742
+ }
743
+ }
744
+ });
745
+ }
746
+ __name(registerCheckpointAggregationCases, "registerCheckpointAggregationCases");
747
+
748
+ // src/state-store-conformance.ts
404
749
  var StateStoreUnavailableError = class extends Error {
405
750
  static {
406
751
  __name(this, "StateStoreUnavailableError");
@@ -486,7 +831,7 @@ function runStateStoreContract(name, makeStore) {
486
831
  });
487
832
  }, "t");
488
833
  t("atomically admits holders without displacement by later same-millisecond IDs", async () => {
489
- expect2(store.tryAdmitSingleton).toBeTypeOf("function");
834
+ expect3(store.tryAdmitSingleton).toBeTypeOf("function");
490
835
  const claim = /* @__PURE__ */ __name((id, limit = 1) => store.tryAdmitSingleton?.(id, "singleton:k", "checkout", limit), "claim");
491
836
  await store.createRun(run({
492
837
  id: "z-holder",
@@ -495,12 +840,12 @@ function runStateStoreContract(name, makeStore) {
495
840
  "user-tag"
496
841
  ]
497
842
  }));
498
- expect2(await claim("z-holder")).toBe(true);
843
+ expect3(await claim("z-holder")).toBe(true);
499
844
  await store.updateRun("z-holder", {
500
845
  status: "suspended",
501
846
  wakeAt: 1e4
502
847
  });
503
- expect2(await claim("z-holder")).toBe(true);
848
+ expect3(await claim("z-holder")).toBe(true);
504
849
  await store.updateRun("z-holder", {
505
850
  status: "blocked",
506
851
  lockedBy: "expired",
@@ -512,25 +857,25 @@ function runStateStoreContract(name, makeStore) {
512
857
  "singleton:k"
513
858
  ]
514
859
  }));
515
- expect2(await claim("a-waiter")).toBe(false);
516
- expect2(await claim("z-holder")).toBe(true);
860
+ expect3(await claim("a-waiter")).toBe(false);
861
+ expect3(await claim("z-holder")).toBe(true);
517
862
  await store.updateRun("z-holder", {
518
863
  status: "cancelling"
519
864
  });
520
- expect2(await claim("a-waiter")).toBe(false);
865
+ expect3(await claim("a-waiter")).toBe(false);
521
866
  await store.updateRun("z-holder", {
522
867
  status: "completed"
523
868
  });
524
- expect2((await store.getRun("z-holder"))?.tags).toEqual([
869
+ expect3((await store.getRun("z-holder"))?.tags).toEqual([
525
870
  "singleton:k",
526
871
  "user-tag"
527
872
  ]);
528
- expect2(await claim("a-waiter")).toBe(true);
873
+ expect3(await claim("a-waiter")).toBe(true);
529
874
  await store.updateRun("z-holder", {
530
875
  status: "running"
531
876
  });
532
- expect2(await claim("z-holder")).toBe(false);
533
- expect2(await claim("missing")).toBe(false);
877
+ expect3(await claim("z-holder")).toBe(false);
878
+ expect3(await claim("missing")).toBe(false);
534
879
  });
535
880
  t("singleton denial atomically parks waiters and preserves cancelling/terminal state", async () => {
536
881
  await store.createRun(run({
@@ -539,15 +884,15 @@ function runStateStoreContract(name, makeStore) {
539
884
  "singleton:k"
540
885
  ]
541
886
  }));
542
- expect2(await store.tryAdmitSingleton?.("holder", "singleton:k", "checkout", 1)).toBe(true);
887
+ expect3(await store.tryAdmitSingleton?.("holder", "singleton:k", "checkout", 1)).toBe(true);
543
888
  await store.createRun(run({
544
889
  id: "waiter",
545
890
  tags: [
546
891
  "singleton:k"
547
892
  ]
548
893
  }));
549
- expect2(await peerStore.tryAdmitSingleton?.("waiter", "singleton:k", "checkout", 1, 12e3)).toBe(false);
550
- expect2(await store.getRun("waiter")).toMatchObject({
894
+ expect3(await peerStore.tryAdmitSingleton?.("waiter", "singleton:k", "checkout", 1, 12e3)).toBe(false);
895
+ expect3(await store.getRun("waiter")).toMatchObject({
551
896
  status: "suspended",
552
897
  wakeAt: 12e3
553
898
  });
@@ -555,16 +900,16 @@ function runStateStoreContract(name, makeStore) {
555
900
  status: "cancelling",
556
901
  wakeAt: void 0
557
902
  });
558
- expect2(await peerStore.tryAdmitSingleton?.("waiter", "singleton:k", "checkout", 1, 14e3)).toBe(false);
559
- expect2(await store.getRun("waiter")).toMatchObject({
903
+ expect3(await peerStore.tryAdmitSingleton?.("waiter", "singleton:k", "checkout", 1, 14e3)).toBe(false);
904
+ expect3(await store.getRun("waiter")).toMatchObject({
560
905
  status: "cancelling"
561
906
  });
562
- expect2((await store.getRun("waiter"))?.wakeAt).toBeUndefined();
907
+ expect3((await store.getRun("waiter"))?.wakeAt).toBeUndefined();
563
908
  await store.updateRun("waiter", {
564
909
  status: "cancelled"
565
910
  });
566
- expect2(await peerStore.tryAdmitSingleton?.("waiter", "singleton:k", "checkout", 1, 16e3)).toBe(false);
567
- expect2((await store.getRun("waiter"))?.status).toBe("cancelled");
911
+ expect3(await peerStore.tryAdmitSingleton?.("waiter", "singleton:k", "checkout", 1, 16e3)).toBe(false);
912
+ expect3((await store.getRun("waiter"))?.status).toBe("cancelled");
568
913
  await store.updateRun("holder", {
569
914
  status: "completed"
570
915
  });
@@ -575,8 +920,8 @@ function runStateStoreContract(name, makeStore) {
575
920
  "singleton:k"
576
921
  ]
577
922
  }));
578
- expect2(await store.tryAdmitSingleton?.("cancelling", "singleton:k", "checkout", 1, 18e3)).toBe(false);
579
- expect2((await store.getRun("cancelling"))?.tags).not.toContain(SINGLETON_ADMITTED_TAG);
923
+ expect3(await store.tryAdmitSingleton?.("cancelling", "singleton:k", "checkout", 1, 18e3)).toBe(false);
924
+ expect3((await store.getRun("cancelling"))?.tags).not.toContain(SINGLETON_ADMITTED_TAG);
580
925
  });
581
926
  t("competing store instances atomically claim an empty singleton slot", async () => {
582
927
  for (const id of [
@@ -596,13 +941,13 @@ function runStateStoreContract(name, makeStore) {
596
941
  store.tryAdmitSingleton?.("a-first", "singleton:k", "checkout", 1),
597
942
  peerStore.tryAdmitSingleton?.("c-third", "singleton:k", "checkout", 1)
598
943
  ]);
599
- expect2(results).toEqual([
944
+ expect3(results).toEqual([
600
945
  false,
601
946
  true,
602
947
  false
603
948
  ]);
604
- expect2(await peerStore.tryAdmitSingleton?.("a-first", "singleton:k", "checkout", 1)).toBe(true);
605
- expect2((await store.getRun("a-first"))?.tags).toContain(SINGLETON_ADMITTED_TAG);
949
+ expect3(await peerStore.tryAdmitSingleton?.("a-first", "singleton:k", "checkout", 1)).toBe(true);
950
+ expect3((await store.getRun("a-first"))?.tags).toContain(SINGLETON_ADMITTED_TAG);
606
951
  });
607
952
  t("concurrent singleton claims honor limits and independent keys/workflows", async () => {
608
953
  const claim = /* @__PURE__ */ __name((id, tag = "singleton:k", workflow = "checkout") => store.tryAdmitSingleton?.(id, tag, workflow, 2), "claim");
@@ -616,7 +961,7 @@ function runStateStoreContract(name, makeStore) {
616
961
  "singleton:k"
617
962
  ]
618
963
  }));
619
- expect2(await claim(id)).toBe(true);
964
+ expect3(await claim(id)).toBe(true);
620
965
  }
621
966
  for (const id of [
622
967
  "a-waiter",
@@ -631,7 +976,7 @@ function runStateStoreContract(name, makeStore) {
631
976
  ]
632
977
  }));
633
978
  }
634
- expect2(await Promise.all([
979
+ expect3(await Promise.all([
635
980
  "a-waiter",
636
981
  "b-waiter",
637
982
  "c-waiter"
@@ -643,7 +988,7 @@ function runStateStoreContract(name, makeStore) {
643
988
  await store.updateRun("z-holder", {
644
989
  status: "failed"
645
990
  });
646
- expect2(await Promise.all([
991
+ expect3(await Promise.all([
647
992
  "c-waiter",
648
993
  "b-waiter",
649
994
  "a-waiter"
@@ -659,14 +1004,14 @@ function runStateStoreContract(name, makeStore) {
659
1004
  "pending"
660
1005
  ]
661
1006
  });
662
- expect2(active.filter((r) => r.tags?.includes(SINGLETON_ADMITTED_TAG))).toHaveLength(2);
1007
+ expect3(active.filter((r) => r.tags?.includes(SINGLETON_ADMITTED_TAG))).toHaveLength(2);
663
1008
  await store.createRun(run({
664
1009
  id: "other-key",
665
1010
  tags: [
666
1011
  "singleton:other"
667
1012
  ]
668
1013
  }));
669
- expect2(await claim("other-key", "singleton:other")).toBe(true);
1014
+ expect3(await claim("other-key", "singleton:other")).toBe(true);
670
1015
  await store.createRun(run({
671
1016
  id: "other-workflow",
672
1017
  workflow: "other",
@@ -674,18 +1019,18 @@ function runStateStoreContract(name, makeStore) {
674
1019
  "singleton:k"
675
1020
  ]
676
1021
  }));
677
- expect2(await claim("other-workflow", "singleton:k", "other")).toBe(true);
1022
+ expect3(await claim("other-workflow", "singleton:k", "other")).toBe(true);
678
1023
  });
679
1024
  t("creates a run and reads it back with its JSON input", async () => {
680
1025
  await store.createRun(run());
681
1026
  const loaded = await store.getRun("r1");
682
- expect2(loaded?.workflow).toBe("checkout");
683
- expect2(loaded?.input).toEqual({
1027
+ expect3(loaded?.workflow).toBe("checkout");
1028
+ expect3(loaded?.input).toEqual({
684
1029
  orderId: "o1"
685
1030
  });
686
1031
  });
687
1032
  t("returns null for a missing run", async () => {
688
- expect2(await store.getRun("nope")).toBeNull();
1033
+ expect3(await store.getRun("nope")).toBeNull();
689
1034
  });
690
1035
  t("updates a run (status/output) and round-trips recoveryAttempts + dead status", async () => {
691
1036
  await store.createRun(run({
@@ -699,18 +1044,18 @@ function runStateStoreContract(name, makeStore) {
699
1044
  updatedAt: at
700
1045
  });
701
1046
  const done = await store.getRun("r1");
702
- expect2(done?.status).toBe("completed");
703
- expect2(done?.output).toEqual({
1047
+ expect3(done?.status).toBe("completed");
1048
+ expect3(done?.output).toEqual({
704
1049
  total: 42
705
1050
  });
706
- expect2(done?.recoveryAttempts).toBe(3);
1051
+ expect3(done?.recoveryAttempts).toBe(3);
707
1052
  await store.updateRun("r1", {
708
1053
  status: "dead",
709
1054
  recoveryAttempts: 4
710
1055
  });
711
1056
  const dead = await store.getRun("r1");
712
- expect2(dead?.status).toBe("dead");
713
- expect2(dead?.recoveryAttempts).toBe(4);
1057
+ expect3(dead?.status).toBe("dead");
1058
+ expect3(dead?.recoveryAttempts).toBe(4);
714
1059
  });
715
1060
  t("round-trips a run dispatch priority", async () => {
716
1061
  await store.createRun(run({
@@ -720,8 +1065,8 @@ function runStateStoreContract(name, makeStore) {
720
1065
  await store.createRun(run({
721
1066
  id: "noprio"
722
1067
  }));
723
- expect2((await store.getRun("withprio"))?.priority).toBe(7);
724
- expect2((await store.getRun("noprio"))?.priority).toBeUndefined();
1068
+ expect3((await store.getRun("withprio"))?.priority).toBe(7);
1069
+ expect3((await store.getRun("noprio"))?.priority).toBeUndefined();
725
1070
  });
726
1071
  t("deleteRun removes the run and all its rows (checkpoints, waiters, attributes)", async () => {
727
1072
  await store.createRun(run({
@@ -736,10 +1081,10 @@ function runStateStoreContract(name, makeStore) {
736
1081
  seq: 0
737
1082
  });
738
1083
  await store.deleteRun("r1");
739
- expect2(await store.getRun("r1")).toBeNull();
740
- expect2(await store.listCheckpoints("r1")).toEqual([]);
741
- expect2(await store.listSignalWaiters("approve-")).toEqual([]);
742
- expect2(await store.listRuns({
1084
+ expect3(await store.getRun("r1")).toBeNull();
1085
+ expect3(await store.listCheckpoints("r1")).toEqual([]);
1086
+ expect3(await store.listSignalWaiters("approve-")).toEqual([]);
1087
+ expect3(await store.listRuns({
743
1088
  attributes: [
744
1089
  {
745
1090
  key: "tier",
@@ -750,7 +1095,7 @@ function runStateStoreContract(name, makeStore) {
750
1095
  })).toEqual([]);
751
1096
  });
752
1097
  t("deleteRun is a no-op for a missing run", async () => {
753
- await expect2(store.deleteRun("nope")).resolves.toBeUndefined();
1098
+ await expect3(store.deleteRun("nope")).resolves.toBeUndefined();
754
1099
  });
755
1100
  t("deleteRuns removes every listed run with its rows and ignores missing ids", async () => {
756
1101
  await store.createRun(run({
@@ -774,18 +1119,18 @@ function runStateStoreContract(name, makeStore) {
774
1119
  runId: "d2",
775
1120
  seq: 0
776
1121
  });
777
- expect2(typeof store.deleteRuns).toBe("function");
1122
+ expect3(typeof store.deleteRuns).toBe("function");
778
1123
  await store.deleteRuns?.([
779
1124
  "d1",
780
1125
  "d2",
781
1126
  "ghost"
782
1127
  ]);
783
- expect2(await store.getRun("d1")).toBeNull();
784
- expect2(await store.getRun("d2")).toBeNull();
785
- expect2(await store.getRun("keep")).not.toBeNull();
786
- expect2(await store.listCheckpoints("d1")).toEqual([]);
787
- expect2(await store.listSignalWaiters("approve-")).toEqual([]);
788
- expect2(await store.listRuns({
1128
+ expect3(await store.getRun("d1")).toBeNull();
1129
+ expect3(await store.getRun("d2")).toBeNull();
1130
+ expect3(await store.getRun("keep")).not.toBeNull();
1131
+ expect3(await store.listCheckpoints("d1")).toEqual([]);
1132
+ expect3(await store.listSignalWaiters("approve-")).toEqual([]);
1133
+ expect3(await store.listRuns({
789
1134
  attributes: [
790
1135
  {
791
1136
  key: "tier",
@@ -794,7 +1139,7 @@ function runStateStoreContract(name, makeStore) {
794
1139
  }
795
1140
  ]
796
1141
  })).toEqual([]);
797
- await expect2(store.deleteRuns?.([])).resolves.toBeUndefined();
1142
+ await expect3(store.deleteRuns?.([])).resolves.toBeUndefined();
798
1143
  });
799
1144
  const aged = /* @__PURE__ */ __name((id, ageDays, over = {}) => run({
800
1145
  id,
@@ -817,7 +1162,7 @@ function runStateStoreContract(name, makeStore) {
817
1162
  runId: "old-done",
818
1163
  stepId: "old-done:0"
819
1164
  }));
820
- expect2(typeof store.pruneTerminalRuns).toBe("function");
1165
+ expect3(typeof store.pruneTerminalRuns).toBe("function");
821
1166
  const deleted = await store.pruneTerminalRuns?.({
822
1167
  statuses: [
823
1168
  "completed",
@@ -826,12 +1171,12 @@ function runStateStoreContract(name, makeStore) {
826
1171
  ],
827
1172
  maxAge: "7d"
828
1173
  }, NOW, 100);
829
- expect2(deleted).toBe(2);
830
- expect2(await ids()).toEqual([
1174
+ expect3(deleted).toBe(2);
1175
+ expect3(await ids()).toEqual([
831
1176
  "fresh-done",
832
1177
  "old-live"
833
1178
  ]);
834
- expect2(await store.listCheckpoints("old-done")).toEqual([]);
1179
+ expect3(await store.listCheckpoints("old-done")).toEqual([]);
835
1180
  });
836
1181
  t("pruneTerminalRuns keeps only the newest maxCount and drains in batches of limit", async () => {
837
1182
  for (let i = 1; i <= 5; i++) await store.createRun(aged(`c${i}`, i));
@@ -841,10 +1186,10 @@ function runStateStoreContract(name, makeStore) {
841
1186
  ],
842
1187
  maxCount: 2
843
1188
  };
844
- expect2(await store.pruneTerminalRuns?.(policy, NOW, 2)).toBe(2);
845
- expect2(await store.pruneTerminalRuns?.(policy, NOW, 2)).toBe(1);
846
- expect2(await store.pruneTerminalRuns?.(policy, NOW, 2)).toBe(0);
847
- expect2(await ids()).toEqual([
1189
+ expect3(await store.pruneTerminalRuns?.(policy, NOW, 2)).toBe(2);
1190
+ expect3(await store.pruneTerminalRuns?.(policy, NOW, 2)).toBe(1);
1191
+ expect3(await store.pruneTerminalRuns?.(policy, NOW, 2)).toBe(0);
1192
+ expect3(await ids()).toEqual([
848
1193
  "c1",
849
1194
  "c2"
850
1195
  ]);
@@ -871,7 +1216,7 @@ function runStateStoreContract(name, makeStore) {
871
1216
  namespace: "acme"
872
1217
  }
873
1218
  }, NOW, 100);
874
- expect2(await ids()).toEqual([
1219
+ expect3(await ids()).toEqual([
875
1220
  "acme-new",
876
1221
  "beta-old",
877
1222
  "report-old"
@@ -887,7 +1232,7 @@ function runStateStoreContract(name, makeStore) {
887
1232
  ]
888
1233
  }
889
1234
  }, NOW, 100);
890
- expect2(await ids()).toEqual([
1235
+ expect3(await ids()).toEqual([
891
1236
  "acme-new",
892
1237
  "beta-old"
893
1238
  ]);
@@ -903,7 +1248,7 @@ function runStateStoreContract(name, makeStore) {
903
1248
  namespace: "acme"
904
1249
  }
905
1250
  }, NOW, 100);
906
- expect2(await ids()).toEqual([
1251
+ expect3(await ids()).toEqual([
907
1252
  "acme-new",
908
1253
  "beta-old"
909
1254
  ]);
@@ -942,7 +1287,7 @@ function runStateStoreContract(name, makeStore) {
942
1287
  ]
943
1288
  }
944
1289
  }, NOW, 100);
945
- expect2(await ids()).toEqual([
1290
+ expect3(await ids()).toEqual([
946
1291
  "attr-old",
947
1292
  "attr-other",
948
1293
  "chatty-old"
@@ -962,7 +1307,7 @@ function runStateStoreContract(name, makeStore) {
962
1307
  ]
963
1308
  }
964
1309
  }, NOW, 100);
965
- expect2(await ids()).toEqual([
1310
+ expect3(await ids()).toEqual([
966
1311
  "attr-other",
967
1312
  "chatty-old"
968
1313
  ]);
@@ -979,21 +1324,24 @@ function runStateStoreContract(name, makeStore) {
979
1324
  engine.register("p-other", "1", async () => "done");
980
1325
  await engine.start("p-root", {}, "pr");
981
1326
  await engine.start("p-other", {}, "po");
982
- expect2((await engine.waitForRun("pc", {
1327
+ expect3((await engine.waitForRun("pr", {
983
1328
  timeoutMs: 2e4
984
1329
  })).status).toBe("suspended");
985
- expect2((await engine.waitForRun("po", {
1330
+ expect3((await engine.waitForRun("pc", {
1331
+ timeoutMs: 2e4
1332
+ })).status).toBe("suspended");
1333
+ expect3((await engine.waitForRun("po", {
986
1334
  timeoutMs: 2e4
987
1335
  })).status).toBe("completed");
988
- await expect2(engine.purgeRuns({})).rejects.toThrow(/empty scope/);
989
- expect2(await engine.purgeRuns({
1336
+ await expect3(engine.purgeRuns({})).rejects.toThrow(/empty scope/);
1337
+ expect3(await engine.purgeRuns({
990
1338
  workflows: [
991
1339
  "p-root"
992
1340
  ]
993
1341
  })).toBe(2);
994
- expect2(await store.getRun("pr")).toBeNull();
995
- expect2(await store.getRun("pc")).toBeNull();
996
- expect2(await store.getRun("po")).not.toBeNull();
1342
+ expect3(await store.getRun("pr")).toBeNull();
1343
+ expect3(await store.getRun("pc")).toBeNull();
1344
+ expect3(await store.getRun("po")).not.toBeNull();
997
1345
  });
998
1346
  t("updateRun maps every patchable field \u2014 clears error and patches tags/lockedBy/input/timers", async () => {
999
1347
  await store.createRun(run({
@@ -1025,29 +1373,29 @@ function runStateStoreContract(name, makeStore) {
1025
1373
  updatedAt: at
1026
1374
  });
1027
1375
  const r = await store.getRun("r1");
1028
- expect2(r?.status).toBe("completed");
1029
- expect2(r?.output).toEqual({
1376
+ expect3(r?.status).toBe("completed");
1377
+ expect3(r?.output).toEqual({
1030
1378
  ok: true
1031
1379
  });
1032
- expect2(r?.error).toBeUndefined();
1033
- expect2(r?.input).toEqual({
1380
+ expect3(r?.error).toBeUndefined();
1381
+ expect3(r?.input).toEqual({
1034
1382
  orderId: "o2"
1035
1383
  });
1036
- expect2(r?.tags).toEqual([
1384
+ expect3(r?.tags).toEqual([
1037
1385
  "x",
1038
1386
  "y"
1039
1387
  ]);
1040
- expect2(r?.lockedBy).toBe("owner-2");
1041
- expect2(r?.wakeAt).toBe(123456);
1042
- expect2(r?.lockedUntil).toBe(222222);
1388
+ expect3(r?.lockedBy).toBe("owner-2");
1389
+ expect3(r?.wakeAt).toBe(123456);
1390
+ expect3(r?.lockedUntil).toBe(222222);
1043
1391
  await store.updateRun("r1", {
1044
1392
  awaitingDecisionTaskId: "turn-7"
1045
1393
  });
1046
- expect2((await store.getRun("r1"))?.awaitingDecisionTaskId).toBe("turn-7");
1394
+ expect3((await store.getRun("r1"))?.awaitingDecisionTaskId).toBe("turn-7");
1047
1395
  await store.updateRun("r1", {
1048
1396
  awaitingDecisionTaskId: void 0
1049
1397
  });
1050
- expect2((await store.getRun("r1"))?.awaitingDecisionTaskId).toBeUndefined();
1398
+ expect3((await store.getRun("r1"))?.awaitingDecisionTaskId).toBeUndefined();
1051
1399
  });
1052
1400
  t("listDueTimers returns the most overdue first, capped at limit", async () => {
1053
1401
  for (const [id, wakeAt] of [
@@ -1074,18 +1422,18 @@ function runStateStoreContract(name, makeStore) {
1074
1422
  wakeAt
1075
1423
  }));
1076
1424
  }
1077
- expect2((await store.listDueTimers(5e3)).map((r) => r.id)).toEqual([
1425
+ expect3((await store.listDueTimers(5e3)).map((r) => r.id)).toEqual([
1078
1426
  "earliest",
1079
1427
  "middle",
1080
1428
  "late"
1081
1429
  ]);
1082
- expect2((await store.listDueTimers(5e3, void 0, 2)).map((r) => r.id)).toEqual([
1430
+ expect3((await store.listDueTimers(5e3, void 0, 2)).map((r) => r.id)).toEqual([
1083
1431
  "earliest",
1084
1432
  "middle"
1085
1433
  ]);
1086
1434
  });
1087
1435
  t("countCheckpoints counts a seq range by status", async () => {
1088
- expect2(store.countCheckpoints).toBeDefined();
1436
+ expect3(store.countCheckpoints).toBeDefined();
1089
1437
  if (!store.countCheckpoints) return;
1090
1438
  await store.createRun(run());
1091
1439
  for (const [seq, status] of [
@@ -1125,32 +1473,175 @@ function runStateStoreContract(name, makeStore) {
1125
1473
  status: "pending",
1126
1474
  stepId: "other:2"
1127
1475
  }));
1128
- expect2(await store.countCheckpoints("r1", 1, 3, [
1476
+ expect3(await store.countCheckpoints("r1", 1, 3, [
1129
1477
  "pending"
1130
1478
  ])).toBe(2);
1131
- expect2(await store.countCheckpoints("r1", 0, 4, [
1479
+ expect3(await store.countCheckpoints("r1", 0, 4, [
1132
1480
  "pending",
1133
1481
  "failed"
1134
1482
  ])).toBe(4);
1135
- expect2(await store.countCheckpoints("r1", 2, 2, [
1483
+ expect3(await store.countCheckpoints("r1", 2, 2, [
1136
1484
  "pending"
1137
1485
  ])).toBe(1);
1138
- expect2(await store.countCheckpoints("r1", 1, 4, [
1486
+ expect3(await store.countCheckpoints("r1", 1, 4, [
1139
1487
  "pending"
1140
1488
  ])).toBe(3);
1141
- expect2(await store.countCheckpoints("r1", 0, 0, [
1489
+ expect3(await store.countCheckpoints("r1", 0, 0, [
1142
1490
  "completed"
1143
1491
  ])).toBe(1);
1144
- expect2(await store.countCheckpoints("other", 0, 4, [
1492
+ expect3(await store.countCheckpoints("other", 0, 4, [
1145
1493
  "pending"
1146
1494
  ])).toBe(1);
1147
- expect2(await store.countCheckpoints("r1", 5, 9, [
1495
+ expect3(await store.countCheckpoints("r1", 5, 9, [
1148
1496
  "pending"
1149
1497
  ])).toBe(0);
1150
- expect2(await store.countCheckpoints("r1", 0, 4, [])).toBe(0);
1498
+ expect3(await store.countCheckpoints("r1", 0, 4, [])).toBe(0);
1499
+ });
1500
+ registerCheckpointAggregationCases(t, () => store, run);
1501
+ t("listOrphanedRuns returns incomplete runs with a free or expired lease, oldest first", async () => {
1502
+ expect3(store.listOrphanedRuns).toBeDefined();
1503
+ if (!store.listOrphanedRuns) return;
1504
+ const created = /* @__PURE__ */ __name((offset) => new Date(at.getTime() + offset * 1e3), "created");
1505
+ await store.createRun(run({
1506
+ id: "held",
1507
+ createdAt: created(1)
1508
+ }));
1509
+ expect3(await store.tryLockRun("held", "live", NOW + 3e4, NOW)).toBe(true);
1510
+ await store.createRun(run({
1511
+ id: "expired",
1512
+ createdAt: created(3)
1513
+ }));
1514
+ expect3(await store.tryLockRun("expired", "dead", NOW, NOW - 1)).toBe(true);
1515
+ await store.createRun(run({
1516
+ id: "free",
1517
+ createdAt: created(2)
1518
+ }));
1519
+ await store.createRun(run({
1520
+ id: "compensating",
1521
+ status: "cancelling",
1522
+ createdAt: created(4)
1523
+ }));
1524
+ await store.createRun(run({
1525
+ id: "parked",
1526
+ status: "suspended",
1527
+ createdAt: created(0)
1528
+ }));
1529
+ await store.createRun(run({
1530
+ id: "done",
1531
+ status: "completed",
1532
+ createdAt: created(0)
1533
+ }));
1534
+ await store.createRun(run({
1535
+ id: "tenant",
1536
+ namespace: "beta",
1537
+ createdAt: created(5)
1538
+ }));
1539
+ expect3((await store.listOrphanedRuns(NOW, 10)).map((r) => r.id)).toEqual([
1540
+ "free",
1541
+ "expired",
1542
+ "compensating",
1543
+ "tenant"
1544
+ ]);
1545
+ expect3((await store.listOrphanedRuns(NOW, 2)).map((r) => r.id)).toEqual([
1546
+ "free",
1547
+ "expired"
1548
+ ]);
1549
+ expect3((await store.listOrphanedRuns(NOW, 10, "beta")).map((r) => r.id)).toEqual([
1550
+ "tenant"
1551
+ ]);
1552
+ expect3((await store.listOrphanedRuns(NOW + 3e4, 10)).map((r) => r.id)).toContain("held");
1553
+ expect3(await store.listOrphanedRuns(NOW, 0)).toEqual([]);
1554
+ });
1555
+ t("updateRunIf writes only over an expected status", async () => {
1556
+ expect3(store.updateRunIf).toBeDefined();
1557
+ if (!store.updateRunIf) return;
1558
+ await store.createRun(run({
1559
+ error: {
1560
+ message: "earlier attempt"
1561
+ }
1562
+ }));
1563
+ expect3(await store.updateRunIf("r1", [
1564
+ "suspended",
1565
+ "blocked"
1566
+ ], {
1567
+ status: "completed",
1568
+ output: {
1569
+ total: 1
1570
+ }
1571
+ })).toBe(false);
1572
+ let current = await store.getRun("r1");
1573
+ expect3(current?.status).toBe("running");
1574
+ expect3(current?.output).toBeUndefined();
1575
+ expect3(await store.updateRunIf("r1", [
1576
+ "pending",
1577
+ "running"
1578
+ ], {
1579
+ status: "suspended",
1580
+ wakeAt: 7e3,
1581
+ error: void 0,
1582
+ updatedAt: new Date(at.getTime() + 1e3)
1583
+ })).toBe(true);
1584
+ current = await store.getRun("r1");
1585
+ expect3(current?.status).toBe("suspended");
1586
+ expect3(current?.wakeAt).toBe(7e3);
1587
+ expect3(current?.error).toBeUndefined();
1588
+ expect3(current?.updatedAt.getTime()).toBe(at.getTime() + 1e3);
1589
+ await store.updateRun("r1", {
1590
+ status: "cancelled",
1591
+ error: {
1592
+ message: "cancelled"
1593
+ }
1594
+ });
1595
+ expect3(await store.updateRunIf("r1", [
1596
+ "running",
1597
+ "suspended"
1598
+ ], {
1599
+ status: "completed",
1600
+ output: {
1601
+ total: 2
1602
+ }
1603
+ })).toBe(false);
1604
+ current = await store.getRun("r1");
1605
+ expect3(current?.status).toBe("cancelled");
1606
+ expect3(current?.error).toEqual({
1607
+ message: "cancelled"
1608
+ });
1609
+ expect3(current?.output).toBeUndefined();
1610
+ expect3(await store.updateRunIf("missing", [
1611
+ "running"
1612
+ ], {
1613
+ status: "completed"
1614
+ })).toBe(false);
1615
+ expect3(await store.getRun("missing")).toBeNull();
1616
+ });
1617
+ t("updateRunIf settling a run terminal drops its singleton admission like updateRun", async () => {
1618
+ expect3(store.updateRunIf).toBeDefined();
1619
+ if (!store.updateRunIf) return;
1620
+ await store.createRun(run({
1621
+ tags: [
1622
+ "singleton:k",
1623
+ SINGLETON_ADMITTED_TAG
1624
+ ]
1625
+ }));
1626
+ expect3(await store.updateRunIf("r1", [
1627
+ "running"
1628
+ ], {
1629
+ status: "completed",
1630
+ output: {
1631
+ ok: true
1632
+ }
1633
+ })).toBe(true);
1634
+ const settled = await store.getRun("r1");
1635
+ expect3(settled?.status).toBe("completed");
1636
+ expect3(settled?.output).toEqual({
1637
+ ok: true
1638
+ });
1639
+ expect3(settled?.tags).toEqual([
1640
+ "singleton:k"
1641
+ ]);
1151
1642
  });
1152
1643
  t("saveCheckpointIfPending writes over a pending row only", async () => {
1153
- expect2(store.saveCheckpointIfPending).toBeDefined();
1644
+ expect3(store.saveCheckpointIfPending).toBeDefined();
1154
1645
  if (!store.saveCheckpointIfPending) return;
1155
1646
  await store.createRun(run());
1156
1647
  const pending = checkpoint({
@@ -1158,11 +1649,11 @@ function runStateStoreContract(name, makeStore) {
1158
1649
  output: void 0
1159
1650
  });
1160
1651
  await store.saveCheckpoint(pending);
1161
- expect2(await store.saveCheckpointIfPending({
1652
+ expect3(await store.saveCheckpointIfPending({
1162
1653
  ...pending,
1163
1654
  wakeAt: 5e3
1164
1655
  })).toBe(true);
1165
- expect2((await store.getCheckpoint("r1", 0))?.wakeAt).toBe(5e3);
1656
+ expect3((await store.getCheckpoint("r1", 0))?.wakeAt).toBe(5e3);
1166
1657
  const done = {
1167
1658
  ...pending,
1168
1659
  status: "completed",
@@ -1170,33 +1661,190 @@ function runStateStoreContract(name, makeStore) {
1170
1661
  ok: true
1171
1662
  }
1172
1663
  };
1173
- expect2(await store.saveCheckpointIfPending(done)).toBe(true);
1174
- expect2(await store.saveCheckpointIfPending({
1664
+ expect3(await store.saveCheckpointIfPending(done)).toBe(true);
1665
+ expect3(await store.saveCheckpointIfPending({
1175
1666
  ...pending,
1176
1667
  wakeAt: 9e3
1177
1668
  })).toBe(false);
1178
1669
  const after = await store.getCheckpoint("r1", 0);
1179
- expect2(after?.status).toBe("completed");
1180
- expect2(after?.output).toEqual({
1670
+ expect3(after?.status).toBe("completed");
1671
+ expect3(after?.output).toEqual({
1181
1672
  ok: true
1182
1673
  });
1183
- expect2(after?.wakeAt).toBeUndefined();
1674
+ expect3(after?.wakeAt).toBeUndefined();
1184
1675
  await store.saveCheckpoint(checkpoint({
1185
1676
  seq: 1,
1186
1677
  status: "failed",
1187
1678
  stepId: "r1:1"
1188
1679
  }));
1189
- expect2(await store.saveCheckpointIfPending({
1680
+ expect3(await store.saveCheckpointIfPending({
1190
1681
  ...pending,
1191
1682
  seq: 1,
1192
1683
  stepId: "r1:1"
1193
1684
  })).toBe(false);
1194
- expect2((await store.getCheckpoint("r1", 1))?.status).toBe("failed");
1195
- expect2(await store.saveCheckpointIfPending({
1685
+ expect3((await store.getCheckpoint("r1", 1))?.status).toBe("failed");
1686
+ expect3(await store.saveCheckpointIfPending({
1196
1687
  ...pending,
1197
1688
  seq: 9
1198
1689
  })).toBe(false);
1199
- expect2(await store.getCheckpoint("r1", 9)).toBeNull();
1690
+ expect3(await store.getCheckpoint("r1", 9)).toBeNull();
1691
+ });
1692
+ t("saveCheckpointsIfPending settles a batch row by row, in order", async () => {
1693
+ expect3(store.saveCheckpointsIfPending).toBeDefined();
1694
+ if (!store.saveCheckpointsIfPending) return;
1695
+ expect3(await store.saveCheckpointsIfPending([])).toEqual([]);
1696
+ await store.createRun(run());
1697
+ await store.createRun(run({
1698
+ id: "r2"
1699
+ }));
1700
+ const pending = /* @__PURE__ */ __name((runId, seq) => checkpoint({
1701
+ runId,
1702
+ seq,
1703
+ stepId: `${runId}:${seq}`,
1704
+ status: "pending",
1705
+ output: void 0,
1706
+ wakeAt: 5e3
1707
+ }), "pending");
1708
+ for (const seq of [
1709
+ 0,
1710
+ 1,
1711
+ 2,
1712
+ 3
1713
+ ]) await store.saveCheckpoint(pending("r1", seq));
1714
+ await store.saveCheckpoint(pending("r2", 0));
1715
+ await store.saveCheckpoint({
1716
+ ...pending("r1", 1),
1717
+ status: "completed",
1718
+ output: {
1719
+ first: 1
1720
+ }
1721
+ });
1722
+ const done = /* @__PURE__ */ __name((runId, seq, output) => ({
1723
+ ...pending(runId, seq),
1724
+ status: "completed",
1725
+ output,
1726
+ wakeAt: void 0
1727
+ }), "done");
1728
+ const wrote = await store.saveCheckpointsIfPending([
1729
+ done("r1", 0, {
1730
+ n: 0
1731
+ }),
1732
+ done("r1", 1, {
1733
+ n: 1
1734
+ }),
1735
+ // A second copy of the same row: compared against the first copy's write, so refused.
1736
+ done("r1", 0, {
1737
+ n: "dup"
1738
+ }),
1739
+ {
1740
+ ...pending("r1", 2),
1741
+ status: "failed",
1742
+ error: {
1743
+ message: "boom"
1744
+ },
1745
+ wakeAt: void 0
1746
+ },
1747
+ // No such row: nothing is written.
1748
+ done("r1", 9, {
1749
+ n: 9
1750
+ }),
1751
+ // Another run's row, same seq as one above.
1752
+ done("r2", 0, {
1753
+ n: "r2"
1754
+ })
1755
+ ]);
1756
+ expect3(wrote).toEqual([
1757
+ true,
1758
+ false,
1759
+ false,
1760
+ true,
1761
+ false,
1762
+ true
1763
+ ]);
1764
+ const r1 = await store.listCheckpoints("r1");
1765
+ expect3(r1.map((c) => [
1766
+ c.seq,
1767
+ c.status,
1768
+ c.output
1769
+ ])).toEqual([
1770
+ [
1771
+ 0,
1772
+ "completed",
1773
+ {
1774
+ n: 0
1775
+ }
1776
+ ],
1777
+ [
1778
+ 1,
1779
+ "completed",
1780
+ {
1781
+ first: 1
1782
+ }
1783
+ ],
1784
+ [
1785
+ 2,
1786
+ "failed",
1787
+ void 0
1788
+ ],
1789
+ [
1790
+ 3,
1791
+ "pending",
1792
+ void 0
1793
+ ]
1794
+ ]);
1795
+ expect3(r1[2]?.error).toEqual({
1796
+ message: "boom"
1797
+ });
1798
+ expect3(r1[0]?.wakeAt).toBeUndefined();
1799
+ expect3(r1[3]?.wakeAt).toBe(5e3);
1800
+ expect3(await store.getCheckpoint("r1", 9)).toBeNull();
1801
+ expect3((await store.getCheckpoint("r2", 0))?.output).toEqual({
1802
+ n: "r2"
1803
+ });
1804
+ expect3(await store.saveCheckpointsIfPending([
1805
+ {
1806
+ ...pending("r1", 3),
1807
+ wakeAt: 9e3
1808
+ },
1809
+ done("r1", 3, {
1810
+ n: 3
1811
+ })
1812
+ ])).toEqual([
1813
+ true,
1814
+ true
1815
+ ]);
1816
+ expect3((await store.getCheckpoint("r1", 3))?.output).toEqual({
1817
+ n: 3
1818
+ });
1819
+ });
1820
+ t("saveCheckpointsIfPending writes a wide batch", async () => {
1821
+ if (!store.saveCheckpointsIfPending) return;
1822
+ await store.createRun(run());
1823
+ const n = 600;
1824
+ const rows = Array.from({
1825
+ length: n
1826
+ }, (_, seq) => checkpoint({
1827
+ seq,
1828
+ stepId: `r1:${seq}`,
1829
+ status: "pending",
1830
+ output: void 0
1831
+ }));
1832
+ for (const row of rows) await store.saveCheckpoint(row);
1833
+ const wrote = await store.saveCheckpointsIfPending(rows.map((row) => ({
1834
+ ...row,
1835
+ status: "completed",
1836
+ output: {
1837
+ seq: row.seq
1838
+ }
1839
+ })));
1840
+ expect3(wrote.every((w) => w === true)).toBe(true);
1841
+ expect3(wrote).toHaveLength(n);
1842
+ expect3(await store.countCheckpoints?.("r1", 0, n - 1, [
1843
+ "completed"
1844
+ ])).toBe(n);
1845
+ expect3((await store.getCheckpoint("r1", n - 1))?.output).toEqual({
1846
+ seq: n - 1
1847
+ });
1200
1848
  });
1201
1849
  t("upserts checkpoints, reads them by (runId, seq), and lists them ordered by seq", async () => {
1202
1850
  await store.createRun(run());
@@ -1214,13 +1862,13 @@ function runStateStoreContract(name, makeStore) {
1214
1862
  again: true
1215
1863
  }
1216
1864
  }));
1217
- expect2((await store.getCheckpoint("r1", 0))?.output).toEqual({
1865
+ expect3((await store.getCheckpoint("r1", 0))?.output).toEqual({
1218
1866
  ok: true,
1219
1867
  again: true
1220
1868
  });
1221
- expect2((await store.getCheckpoint("r1", 1))?.name).toBe("charge");
1869
+ expect3((await store.getCheckpoint("r1", 1))?.name).toBe("charge");
1222
1870
  const list = await store.listCheckpoints("r1");
1223
- expect2(list.map((c) => c.seq)).toEqual([
1871
+ expect3(list.map((c) => c.seq)).toEqual([
1224
1872
  0,
1225
1873
  1
1226
1874
  ]);
@@ -1256,14 +1904,14 @@ function runStateStoreContract(name, makeStore) {
1256
1904
  }
1257
1905
  }));
1258
1906
  const getLatestCheckpointByName = store.getLatestCheckpointByName;
1259
- expect2(getLatestCheckpointByName).toBeDefined();
1907
+ expect3(getLatestCheckpointByName).toBeDefined();
1260
1908
  if (!getLatestCheckpointByName) return;
1261
1909
  const latest = await getLatestCheckpointByName.call(store, "r1", "event:progress");
1262
- expect2(latest?.seq).toBe(3);
1263
- expect2(latest?.output).toEqual({
1910
+ expect3(latest?.seq).toBe(3);
1911
+ expect3(latest?.output).toEqual({
1264
1912
  pct: 90
1265
1913
  });
1266
- expect2(await getLatestCheckpointByName.call(store, "r1", "event:missing")).toBeUndefined();
1914
+ expect3(await getLatestCheckpointByName.call(store, "r1", "event:missing")).toBeUndefined();
1267
1915
  });
1268
1916
  t("listCheckpointsByNamePrefix returns prefix matches ordered by seq (empty => none)", async () => {
1269
1917
  await store.createRun(run());
@@ -1290,18 +1938,48 @@ function runStateStoreContract(name, makeStore) {
1290
1938
  output: "child-b"
1291
1939
  }));
1292
1940
  const listCheckpointsByNamePrefix = store.listCheckpointsByNamePrefix;
1293
- expect2(listCheckpointsByNamePrefix).toBeDefined();
1941
+ expect3(listCheckpointsByNamePrefix).toBeDefined();
1294
1942
  if (!listCheckpointsByNamePrefix) return;
1295
1943
  const matches = await listCheckpointsByNamePrefix.call(store, "r1", [
1296
1944
  "signal:child:",
1297
1945
  "spawn:"
1298
1946
  ]);
1299
- expect2(matches.map((c) => c.name)).toEqual([
1947
+ expect3(matches.map((c) => c.name)).toEqual([
1300
1948
  "spawn:0",
1301
1949
  "signal:child:c2",
1302
1950
  "spawn:1"
1303
1951
  ]);
1304
- expect2(await listCheckpointsByNamePrefix.call(store, "r1", [])).toEqual([]);
1952
+ expect3(await listCheckpointsByNamePrefix.call(store, "r1", [])).toEqual([]);
1953
+ });
1954
+ t("a name or token prefix matches literally \u2014 `_` and `%` are not wildcards", async () => {
1955
+ await store.createRun(run());
1956
+ await store.saveCheckpoint(checkpoint({
1957
+ seq: 0,
1958
+ name: "signal:child:job_1.onError.0"
1959
+ }));
1960
+ await store.saveCheckpoint(checkpoint({
1961
+ seq: 1,
1962
+ name: "signal:child:jobX1.onError.0"
1963
+ }));
1964
+ await store.putSignalWaiter({
1965
+ token: "child:job_1.child.0",
1966
+ runId: "r1",
1967
+ seq: 2
1968
+ });
1969
+ await store.putSignalWaiter({
1970
+ token: "child:jobX1.child.0",
1971
+ runId: "r1",
1972
+ seq: 3
1973
+ });
1974
+ const matches = await store.listCheckpointsByNamePrefix?.("r1", [
1975
+ "signal:child:job_1."
1976
+ ]);
1977
+ expect3(matches?.map((c) => c.name)).toEqual([
1978
+ "signal:child:job_1.onError.0"
1979
+ ]);
1980
+ expect3((await store.listSignalWaiters("child:job_1.")).map((w) => w.token)).toEqual([
1981
+ "child:job_1.child.0"
1982
+ ]);
1305
1983
  });
1306
1984
  t("round-trips checkpoint events and reads back a missing checkpoint as null", async () => {
1307
1985
  await store.createRun(run());
@@ -1316,7 +1994,7 @@ function runStateStoreContract(name, makeStore) {
1316
1994
  }
1317
1995
  ]
1318
1996
  }));
1319
- expect2((await store.getCheckpoint("r1", 0))?.events).toEqual([
1997
+ expect3((await store.getCheckpoint("r1", 0))?.events).toEqual([
1320
1998
  {
1321
1999
  at: 1,
1322
2000
  level: "error",
@@ -1325,7 +2003,7 @@ function runStateStoreContract(name, makeStore) {
1325
2003
  status: "failed"
1326
2004
  }
1327
2005
  ]);
1328
- expect2(await store.getCheckpoint("r1", 99)).toBeNull();
2006
+ expect3(await store.getCheckpoint("r1", 99)).toBeNull();
1329
2007
  });
1330
2008
  t("lists incomplete runs, pending runs (FIFO), and due timers", async () => {
1331
2009
  await store.createRun(run({
@@ -1351,20 +2029,20 @@ function runStateStoreContract(name, makeStore) {
1351
2029
  status: "pending",
1352
2030
  createdAt: /* @__PURE__ */ new Date("2026-06-11T00:00:01.000Z")
1353
2031
  }));
1354
- expect2((await store.listIncompleteRuns()).map((r) => r.id)).toEqual([
2032
+ expect3((await store.listIncompleteRuns()).map((r) => r.id)).toEqual([
1355
2033
  "running1"
1356
2034
  ]);
1357
- expect2((await store.listPendingRuns(10)).map((r) => r.id)).toEqual([
2035
+ expect3((await store.listPendingRuns(10)).map((r) => r.id)).toEqual([
1358
2036
  "pending1",
1359
2037
  "pending2"
1360
2038
  ]);
1361
- expect2((await store.listPendingRuns(1)).map((r) => r.id)).toEqual([
2039
+ expect3((await store.listPendingRuns(1)).map((r) => r.id)).toEqual([
1362
2040
  "pending1"
1363
2041
  ]);
1364
- expect2((await store.listDueTimers(1e4)).map((r) => r.id)).toEqual([
2042
+ expect3((await store.listDueTimers(1e4)).map((r) => r.id)).toEqual([
1365
2043
  "suspended1"
1366
2044
  ]);
1367
- expect2(await store.listDueTimers(1e3)).toHaveLength(0);
2045
+ expect3(await store.listDueTimers(1e3)).toHaveLength(0);
1368
2046
  });
1369
2047
  t("keeps a worker inside its own namespace on every path that picks work up", async () => {
1370
2048
  await store.createRun(run({
@@ -1399,33 +2077,33 @@ function runStateStoreContract(name, makeStore) {
1399
2077
  wakeAt: 5e3,
1400
2078
  namespace: "beta"
1401
2079
  }));
1402
- expect2((await store.listPendingRuns(10, "alpha")).map((r) => r.id)).toEqual([
2080
+ expect3((await store.listPendingRuns(10, "alpha")).map((r) => r.id)).toEqual([
1403
2081
  "a-pending"
1404
2082
  ]);
1405
- expect2((await store.listIncompleteRuns("alpha")).map((r) => r.id)).toEqual([
2083
+ expect3((await store.listIncompleteRuns("alpha")).map((r) => r.id)).toEqual([
1406
2084
  "a-running"
1407
2085
  ]);
1408
- expect2((await store.listDueTimers(1e4, "alpha")).map((r) => r.id)).toEqual([
2086
+ expect3((await store.listDueTimers(1e4, "alpha")).map((r) => r.id)).toEqual([
1409
2087
  "a-timer"
1410
2088
  ]);
1411
- expect2((await store.listRuns({
2089
+ expect3((await store.listRuns({
1412
2090
  namespace: "alpha",
1413
2091
  status: "running"
1414
2092
  })).map((r) => r.id)).toEqual([
1415
2093
  "a-running"
1416
2094
  ]);
1417
- expect2((await store.listPendingRuns(1, "alpha")).map((r) => r.id)).toEqual([
2095
+ expect3((await store.listPendingRuns(1, "alpha")).map((r) => r.id)).toEqual([
1418
2096
  "a-pending"
1419
2097
  ]);
1420
- expect2((await store.listPendingRuns(10)).map((r) => r.id).sort()).toEqual([
2098
+ expect3((await store.listPendingRuns(10)).map((r) => r.id).sort()).toEqual([
1421
2099
  "a-pending",
1422
2100
  "b-pending"
1423
2101
  ]);
1424
- expect2((await store.listIncompleteRuns()).map((r) => r.id).sort()).toEqual([
2102
+ expect3((await store.listIncompleteRuns()).map((r) => r.id).sort()).toEqual([
1425
2103
  "a-running",
1426
2104
  "b-running"
1427
2105
  ]);
1428
- expect2((await store.listDueTimers(1e4)).map((r) => r.id).sort()).toEqual([
2106
+ expect3((await store.listDueTimers(1e4)).map((r) => r.id).sort()).toEqual([
1429
2107
  "a-timer",
1430
2108
  "b-timer"
1431
2109
  ]);
@@ -1434,20 +2112,20 @@ function runStateStoreContract(name, makeStore) {
1434
2112
  await store.createRun(run({
1435
2113
  id: "r1"
1436
2114
  }));
1437
- expect2(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
1438
- expect2(await store.tryLockRun("r1", "B", 3e3, 1500)).toBe(false);
1439
- expect2(await store.tryLockRun("r1", "B", 4e3, 2500)).toBe(true);
2115
+ expect3(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
2116
+ expect3(await store.tryLockRun("r1", "B", 3e3, 1500)).toBe(false);
2117
+ expect3(await store.tryLockRun("r1", "B", 4e3, 2500)).toBe(true);
1440
2118
  await store.releaseRunLock("r1");
1441
- expect2(await store.tryLockRun("r1", "C", 9e3, 2600)).toBe(true);
2119
+ expect3(await store.tryLockRun("r1", "C", 9e3, 2600)).toBe(true);
1442
2120
  });
1443
2121
  t("renewRunLock only succeeds for the current owner", async () => {
1444
2122
  await store.createRun(run({
1445
2123
  id: "r1"
1446
2124
  }));
1447
- expect2(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
1448
- expect2(await store.renewRunLock("r1", "A", 5e3)).toBe(true);
1449
- expect2(await store.renewRunLock("r1", "B", 9e3)).toBe(false);
1450
- expect2(await store.tryLockRun("r1", "B", 6e3, 4e3)).toBe(false);
2125
+ expect3(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
2126
+ expect3(await store.renewRunLock("r1", "A", 5e3)).toBe(true);
2127
+ expect3(await store.renewRunLock("r1", "B", 9e3)).toBe(false);
2128
+ expect3(await store.tryLockRun("r1", "B", 6e3, 4e3)).toBe(false);
1451
2129
  });
1452
2130
  t("filters listRuns by workflow and by status", async () => {
1453
2131
  await store.createRun(run({
@@ -1465,19 +2143,19 @@ function runStateStoreContract(name, makeStore) {
1465
2143
  workflow: "checkout",
1466
2144
  status: "completed"
1467
2145
  }));
1468
- expect2((await store.listRuns({
2146
+ expect3((await store.listRuns({
1469
2147
  workflow: "checkout"
1470
2148
  })).map((r) => r.id).sort()).toEqual([
1471
2149
  "a",
1472
2150
  "c"
1473
2151
  ]);
1474
- expect2((await store.listRuns({
2152
+ expect3((await store.listRuns({
1475
2153
  status: "running"
1476
2154
  })).map((r) => r.id).sort()).toEqual([
1477
2155
  "a",
1478
2156
  "b"
1479
2157
  ]);
1480
- expect2((await store.listRuns({
2158
+ expect3((await store.listRuns({
1481
2159
  workflow: "checkout",
1482
2160
  status: "running"
1483
2161
  })).map((r) => r.id)).toEqual([
@@ -1501,7 +2179,7 @@ function runStateStoreContract(name, makeStore) {
1501
2179
  id: "d",
1502
2180
  status: "pending"
1503
2181
  }));
1504
- expect2((await store.listRuns({
2182
+ expect3((await store.listRuns({
1505
2183
  statuses: [
1506
2184
  "running",
1507
2185
  "suspended"
@@ -1510,7 +2188,7 @@ function runStateStoreContract(name, makeStore) {
1510
2188
  "a",
1511
2189
  "b"
1512
2190
  ]);
1513
- expect2((await store.listRuns({
2191
+ expect3((await store.listRuns({
1514
2192
  status: "running",
1515
2193
  statuses: [
1516
2194
  "running",
@@ -1519,7 +2197,7 @@ function runStateStoreContract(name, makeStore) {
1519
2197
  })).map((r) => r.id)).toEqual([
1520
2198
  "a"
1521
2199
  ]);
1522
- expect2(await store.listRuns({
2200
+ expect3(await store.listRuns({
1523
2201
  statuses: []
1524
2202
  })).toHaveLength(0);
1525
2203
  });
@@ -1541,21 +2219,21 @@ function runStateStoreContract(name, makeStore) {
1541
2219
  await store.createRun(run({
1542
2220
  id: "c"
1543
2221
  }));
1544
- expect2((await store.getRun("a"))?.tags).toEqual([
2222
+ expect3((await store.getRun("a"))?.tags).toEqual([
1545
2223
  "etl",
1546
2224
  "critical"
1547
2225
  ]);
1548
- expect2((await store.listRuns({
2226
+ expect3((await store.listRuns({
1549
2227
  tag: "etl"
1550
2228
  })).map((r) => r.id)).toEqual([
1551
2229
  "a"
1552
2230
  ]);
1553
- expect2((await store.listRuns({
2231
+ expect3((await store.listRuns({
1554
2232
  tag: "etl-foo"
1555
2233
  })).map((r) => r.id)).toEqual([
1556
2234
  "b"
1557
2235
  ]);
1558
- expect2(await store.listRuns({
2236
+ expect3(await store.listRuns({
1559
2237
  tag: "nope"
1560
2238
  })).toHaveLength(0);
1561
2239
  });
@@ -1571,17 +2249,17 @@ function runStateStoreContract(name, makeStore) {
1571
2249
  await store.createRun(run({
1572
2250
  id: "c"
1573
2251
  }));
1574
- expect2((await store.getRun("a"))?.origin).toBe("@dudousxd/nestjs-catalog-pipeline");
1575
- expect2((await store.getRun("c"))?.origin).toBeUndefined();
1576
- expect2((await store.listRuns({
2252
+ expect3((await store.getRun("a"))?.origin).toBe("@dudousxd/nestjs-catalog-pipeline");
2253
+ expect3((await store.getRun("c"))?.origin).toBeUndefined();
2254
+ expect3((await store.listRuns({
1577
2255
  origin: "@dudousxd/nestjs-catalog-pipeline"
1578
2256
  })).map((r) => r.id)).toEqual([
1579
2257
  "a"
1580
2258
  ]);
1581
- expect2(await store.listRuns({
2259
+ expect3(await store.listRuns({
1582
2260
  origin: "unknown"
1583
2261
  })).toEqual([]);
1584
- expect2((await store.listRuns({})).map((r) => r.id).sort()).toEqual([
2262
+ expect3((await store.listRuns({})).map((r) => r.id).sort()).toEqual([
1585
2263
  "a",
1586
2264
  "b",
1587
2265
  "c"
@@ -1598,7 +2276,7 @@ function runStateStoreContract(name, makeStore) {
1598
2276
  await store.createRun(run({
1599
2277
  id: "c"
1600
2278
  }));
1601
- expect2((await store.listRuns({
2279
+ expect3((await store.listRuns({
1602
2280
  origin: null
1603
2281
  })).map((r) => r.id).sort()).toEqual([
1604
2282
  "b",
@@ -1608,7 +2286,7 @@ function runStateStoreContract(name, makeStore) {
1608
2286
  id: "d",
1609
2287
  status: "dead"
1610
2288
  }));
1611
- expect2((await store.listRuns({
2289
+ expect3((await store.listRuns({
1612
2290
  origin: null,
1613
2291
  status: "dead"
1614
2292
  })).map((r) => r.id)).toEqual([
@@ -1641,22 +2319,22 @@ function runStateStoreContract(name, makeStore) {
1641
2319
  status: "failed"
1642
2320
  }));
1643
2321
  const facets = await store.runFacets({});
1644
- expect2(facets).toContainEqual({
2322
+ expect3(facets).toContainEqual({
1645
2323
  status: "completed",
1646
2324
  origin: "pkg-a",
1647
2325
  count: 2
1648
2326
  });
1649
- expect2(facets).toContainEqual({
2327
+ expect3(facets).toContainEqual({
1650
2328
  status: "failed",
1651
2329
  origin: "pkg-b",
1652
2330
  count: 1
1653
2331
  });
1654
- expect2(facets).toContainEqual({
2332
+ expect3(facets).toContainEqual({
1655
2333
  status: "failed",
1656
2334
  origin: null,
1657
2335
  count: 2
1658
2336
  });
1659
- expect2(facets.reduce((n, f) => n + f.count, 0)).toBe(5);
2337
+ expect3(facets.reduce((n, f) => n + f.count, 0)).toBe(5);
1660
2338
  });
1661
2339
  t("narrows runFacets on the same predicates listRuns pages", async () => {
1662
2340
  if (!store.runFacets) return;
@@ -1670,7 +2348,7 @@ function runStateStoreContract(name, makeStore) {
1670
2348
  status: "failed",
1671
2349
  namespace: "globex"
1672
2350
  }));
1673
- expect2(await store.runFacets({
2351
+ expect3(await store.runFacets({
1674
2352
  namespace: "acme"
1675
2353
  })).toEqual([
1676
2354
  {
@@ -1699,7 +2377,7 @@ function runStateStoreContract(name, makeStore) {
1699
2377
  namespace: "initech",
1700
2378
  workflow: "wc"
1701
2379
  }));
1702
- expect2((await store.listRuns({
2380
+ expect3((await store.listRuns({
1703
2381
  statuses: [
1704
2382
  "failed",
1705
2383
  "dead"
@@ -1708,7 +2386,7 @@ function runStateStoreContract(name, makeStore) {
1708
2386
  "a",
1709
2387
  "b"
1710
2388
  ]);
1711
- expect2((await store.listRuns({
2389
+ expect3((await store.listRuns({
1712
2390
  namespaces: [
1713
2391
  "acme",
1714
2392
  "globex"
@@ -1717,7 +2395,7 @@ function runStateStoreContract(name, makeStore) {
1717
2395
  "a",
1718
2396
  "b"
1719
2397
  ]);
1720
- expect2((await store.listRuns({
2398
+ expect3((await store.listRuns({
1721
2399
  workflows: [
1722
2400
  "wa",
1723
2401
  "wc"
@@ -1739,7 +2417,7 @@ function runStateStoreContract(name, makeStore) {
1739
2417
  await store.createRun(run({
1740
2418
  id: "c"
1741
2419
  }));
1742
- expect2((await store.listRuns({
2420
+ expect3((await store.listRuns({
1743
2421
  origins: [
1744
2422
  "pkg-a",
1745
2423
  null
@@ -1748,7 +2426,7 @@ function runStateStoreContract(name, makeStore) {
1748
2426
  "a",
1749
2427
  "c"
1750
2428
  ]);
1751
- expect2((await store.listRuns({
2429
+ expect3((await store.listRuns({
1752
2430
  origins: [
1753
2431
  "pkg-a",
1754
2432
  "pkg-b"
@@ -1769,7 +2447,7 @@ function runStateStoreContract(name, makeStore) {
1769
2447
  status: "dead",
1770
2448
  namespace: "acme"
1771
2449
  }));
1772
- expect2((await store.listRuns({
2450
+ expect3((await store.listRuns({
1773
2451
  namespaces: [
1774
2452
  "acme"
1775
2453
  ],
@@ -1779,13 +2457,13 @@ function runStateStoreContract(name, makeStore) {
1779
2457
  })).map((r) => r.id)).toEqual([
1780
2458
  "b"
1781
2459
  ]);
1782
- expect2(await store.listRuns({
2460
+ expect3(await store.listRuns({
1783
2461
  namespaces: []
1784
2462
  })).toEqual([]);
1785
- expect2(await store.listRuns({
2463
+ expect3(await store.listRuns({
1786
2464
  statuses: []
1787
2465
  })).toEqual([]);
1788
- expect2(await store.listRuns({
2466
+ expect3(await store.listRuns({
1789
2467
  origins: []
1790
2468
  })).toEqual([]);
1791
2469
  });
@@ -1810,7 +2488,7 @@ function runStateStoreContract(name, makeStore) {
1810
2488
  "adhoc"
1811
2489
  ]
1812
2490
  }));
1813
- expect2((await store.listRuns({
2491
+ expect3((await store.listRuns({
1814
2492
  tags: [
1815
2493
  "etl",
1816
2494
  "nightly"
@@ -1819,7 +2497,7 @@ function runStateStoreContract(name, makeStore) {
1819
2497
  "a",
1820
2498
  "b"
1821
2499
  ]);
1822
- expect2(await store.listRuns({
2500
+ expect3(await store.listRuns({
1823
2501
  tags: []
1824
2502
  })).toEqual([]);
1825
2503
  });
@@ -1860,7 +2538,7 @@ function runStateStoreContract(name, makeStore) {
1860
2538
  }
1861
2539
  ]
1862
2540
  });
1863
- expect2(inSet.map((r) => r.id).sort()).toEqual([
2541
+ expect3(inSet.map((r) => r.id).sort()).toEqual([
1864
2542
  "a",
1865
2543
  "b"
1866
2544
  ]);
@@ -1876,10 +2554,10 @@ function runStateStoreContract(name, makeStore) {
1876
2554
  }
1877
2555
  ]
1878
2556
  });
1879
- expect2(mixed.map((r) => r.id)).toEqual([
2557
+ expect3(mixed.map((r) => r.id)).toEqual([
1880
2558
  "d"
1881
2559
  ]);
1882
- expect2(await store.listRuns({
2560
+ expect3(await store.listRuns({
1883
2561
  attributes: [
1884
2562
  {
1885
2563
  key: "tier",
@@ -1888,7 +2566,7 @@ function runStateStoreContract(name, makeStore) {
1888
2566
  }
1889
2567
  ]
1890
2568
  })).toEqual([]);
1891
- expect2((await store.listRuns({
2569
+ expect3((await store.listRuns({
1892
2570
  attributes: [
1893
2571
  {
1894
2572
  key: "tier",
@@ -1916,7 +2594,7 @@ function runStateStoreContract(name, makeStore) {
1916
2594
  id: "c",
1917
2595
  namespace: "globex"
1918
2596
  }));
1919
- expect2(await store.runValueFacets({
2597
+ expect3(await store.runValueFacets({
1920
2598
  field: "namespace"
1921
2599
  }, {})).toEqual([
1922
2600
  {
@@ -1941,11 +2619,11 @@ function runStateStoreContract(name, makeStore) {
1941
2619
  const values = await store.runValueFacets({
1942
2620
  field: "origin"
1943
2621
  }, {});
1944
- expect2(values).toContainEqual({
2622
+ expect3(values).toContainEqual({
1945
2623
  value: "pkg-a",
1946
2624
  count: 1
1947
2625
  });
1948
- expect2(values).toContainEqual({
2626
+ expect3(values).toContainEqual({
1949
2627
  value: null,
1950
2628
  count: 1
1951
2629
  });
@@ -1967,7 +2645,7 @@ function runStateStoreContract(name, makeStore) {
1967
2645
  "nightly"
1968
2646
  ]
1969
2647
  }));
1970
- expect2(await store.runValueFacets({
2648
+ expect3(await store.runValueFacets({
1971
2649
  field: "tag"
1972
2650
  }, {
1973
2651
  namespace: "acme"
@@ -1999,7 +2677,7 @@ function runStateStoreContract(name, makeStore) {
1999
2677
  tier: "free"
2000
2678
  }
2001
2679
  }));
2002
- expect2(await store.runValueFacets({
2680
+ expect3(await store.runValueFacets({
2003
2681
  field: "tag"
2004
2682
  }, {})).toEqual([
2005
2683
  {
@@ -2011,7 +2689,7 @@ function runStateStoreContract(name, makeStore) {
2011
2689
  count: 1
2012
2690
  }
2013
2691
  ]);
2014
- expect2(await store.runValueFacets({
2692
+ expect3(await store.runValueFacets({
2015
2693
  field: "attributeKey"
2016
2694
  }, {})).toEqual([
2017
2695
  {
@@ -2019,7 +2697,7 @@ function runStateStoreContract(name, makeStore) {
2019
2697
  count: 2
2020
2698
  }
2021
2699
  ]);
2022
- expect2((await store.runValueFacets({
2700
+ expect3((await store.runValueFacets({
2023
2701
  field: "attributeValue",
2024
2702
  key: "tier"
2025
2703
  }, {})).map((r) => r.value).sort()).toEqual([
@@ -2050,18 +2728,18 @@ function runStateStoreContract(name, makeStore) {
2050
2728
  }, {}, {
2051
2729
  search: "acme"
2052
2730
  });
2053
- expect2(matches.map((row) => row.value).sort()).toEqual([
2731
+ expect3(matches.map((row) => row.value).sort()).toEqual([
2054
2732
  "acme-prod",
2055
2733
  "acme-staging"
2056
2734
  ]);
2057
- expect2((await store.runValueFacets({
2735
+ expect3((await store.runValueFacets({
2058
2736
  field: "namespace"
2059
2737
  }, {}, {
2060
2738
  limit: 1
2061
2739
  })).map((r) => r.value)).toEqual([
2062
2740
  "globex"
2063
2741
  ]);
2064
- expect2((await store.runValueFacets({
2742
+ expect3((await store.runValueFacets({
2065
2743
  field: "namespace"
2066
2744
  }, {}, {
2067
2745
  limit: 1,
@@ -2107,7 +2785,7 @@ function runStateStoreContract(name, makeStore) {
2107
2785
  limit: 2,
2108
2786
  offset: 2
2109
2787
  });
2110
- expect2(first).toEqual([
2788
+ expect3(first).toEqual([
2111
2789
  {
2112
2790
  value: "one",
2113
2791
  count: 3
@@ -2117,13 +2795,13 @@ function runStateStoreContract(name, makeStore) {
2117
2795
  count: 2
2118
2796
  }
2119
2797
  ]);
2120
- expect2(second).toEqual([
2798
+ expect3(second).toEqual([
2121
2799
  {
2122
2800
  value: "three",
2123
2801
  count: 1
2124
2802
  }
2125
2803
  ]);
2126
- expect2(new Set([
2804
+ expect3(new Set([
2127
2805
  ...first,
2128
2806
  ...second
2129
2807
  ].map((r) => r.value)).size).toBe(3);
@@ -2151,7 +2829,7 @@ function runStateStoreContract(name, makeStore) {
2151
2829
  "etl"
2152
2830
  ]
2153
2831
  }));
2154
- expect2((await store.runValueFacets({
2832
+ expect3((await store.runValueFacets({
2155
2833
  field: "tag"
2156
2834
  }, {}, {
2157
2835
  search: "type:"
@@ -2159,7 +2837,7 @@ function runStateStoreContract(name, makeStore) {
2159
2837
  "type:mel",
2160
2838
  "type:mvr"
2161
2839
  ]);
2162
- expect2(await store.runValueFacets({
2840
+ expect3(await store.runValueFacets({
2163
2841
  field: "tag"
2164
2842
  }, {}, {
2165
2843
  limit: 1
@@ -2184,7 +2862,7 @@ function runStateStoreContract(name, makeStore) {
2184
2862
  id: "c",
2185
2863
  namespace: "globex"
2186
2864
  }));
2187
- expect2(await store.runValueFacets({
2865
+ expect3(await store.runValueFacets({
2188
2866
  field: "namespace"
2189
2867
  }, {}, {
2190
2868
  limit: 1
@@ -2196,7 +2874,7 @@ function runStateStoreContract(name, makeStore) {
2196
2874
  ]);
2197
2875
  });
2198
2876
  t("countRuns counts the same set listRuns returns, without the paging", async () => {
2199
- expect2(typeof store.countRuns).toBe("function");
2877
+ expect3(typeof store.countRuns).toBe("function");
2200
2878
  await store.createRun(run({
2201
2879
  id: "n1",
2202
2880
  status: "running",
@@ -2226,22 +2904,22 @@ function runStateStoreContract(name, makeStore) {
2226
2904
  "q"
2227
2905
  ]
2228
2906
  }));
2229
- expect2(await store.countRuns?.({})).toBe(4);
2230
- expect2(await store.countRuns?.({
2907
+ expect3(await store.countRuns?.({})).toBe(4);
2908
+ expect3(await store.countRuns?.({
2231
2909
  namespace: "a"
2232
2910
  })).toBe(3);
2233
- expect2(await store.countRuns?.({
2911
+ expect3(await store.countRuns?.({
2234
2912
  namespace: "a",
2235
2913
  statuses: [
2236
2914
  "pending",
2237
2915
  "running"
2238
2916
  ]
2239
2917
  })).toBe(2);
2240
- expect2(await store.countRuns?.({
2918
+ expect3(await store.countRuns?.({
2241
2919
  statuses: []
2242
2920
  })).toBe(0);
2243
2921
  if (supportsTagFilter) {
2244
- expect2(await store.countRuns?.({
2922
+ expect3(await store.countRuns?.({
2245
2923
  tag: "q",
2246
2924
  statuses: [
2247
2925
  "running",
@@ -2268,28 +2946,28 @@ function runStateStoreContract(name, makeStore) {
2268
2946
  await engine.start("q-wait", {}, "q1", {
2269
2947
  concurrency: quota
2270
2948
  });
2271
- expect2((await engine.waitForRun("q1", {
2949
+ expect3((await engine.waitForRun("q1", {
2272
2950
  timeoutMs: 2e4
2273
2951
  })).status).toBe("suspended");
2274
- await expect2(engine.start("q-wait", {}, "q2", {
2952
+ await expect3(engine.start("q-wait", {}, "q2", {
2275
2953
  concurrency: quota
2276
2954
  })).rejects.toThrow(/concurrency limit/);
2277
- expect2(await store.getRun("q2")).toBeNull();
2955
+ expect3(await store.getRun("q2")).toBeNull();
2278
2956
  await engine.start("q-wait", {}, "q3", {
2279
2957
  concurrency: {
2280
2958
  ...quota,
2281
2959
  key: "tenant:b"
2282
2960
  }
2283
2961
  });
2284
- expect2((await engine.waitForRun("q1", {
2962
+ expect3((await engine.waitForRun("q1", {
2285
2963
  timeoutMs: 2e4
2286
2964
  })).status).toBe("suspended");
2287
2965
  await engine.cancel("q1");
2288
- expect2((await store.getRun("q1"))?.status).toBe("cancelled");
2966
+ expect3((await store.getRun("q1"))?.status).toBe("cancelled");
2289
2967
  await engine.start("q-wait", {}, "q4", {
2290
2968
  concurrency: quota
2291
2969
  });
2292
- expect2(await store.getRun("q4")).not.toBeNull();
2970
+ expect3(await store.getRun("q4")).not.toBeNull();
2293
2971
  for (const id of [
2294
2972
  "q3",
2295
2973
  "q4"
@@ -2328,10 +3006,10 @@ function runStateStoreContract(name, makeStore) {
2328
3006
  ...over
2329
3007
  }), "schedule");
2330
3008
  t("saves, reads back, replaces and deletes a schedule", async () => {
2331
- expect2(typeof store.saveSchedule).toBe("function");
3009
+ expect3(typeof store.saveSchedule).toBe("function");
2332
3010
  await store.saveSchedule?.(schedule());
2333
3011
  const loaded = await store.getSchedule?.("s1");
2334
- expect2(loaded).toMatchObject({
3012
+ expect3(loaded).toMatchObject({
2335
3013
  id: "s1",
2336
3014
  namespace: "default",
2337
3015
  workflow: "digest",
@@ -2357,27 +3035,27 @@ function runStateStoreContract(name, makeStore) {
2357
3035
  window: NOW + 6e4
2358
3036
  }
2359
3037
  });
2360
- expect2(loaded?.createdAt.getTime()).toBe(at.getTime());
3038
+ expect3(loaded?.createdAt.getTime()).toBe(at.getTime());
2361
3039
  await store.saveSchedule?.(schedule({
2362
3040
  workflow: "digest2",
2363
3041
  nextFireAt: null,
2364
3042
  tags: void 0
2365
3043
  }));
2366
3044
  const replaced = await store.getSchedule?.("s1");
2367
- expect2(replaced?.workflow).toBe("digest2");
2368
- expect2(replaced?.nextFireAt).toBeNull();
2369
- expect2(replaced?.tags ?? []).toEqual([]);
2370
- expect2(await store.getSchedule?.("nope")).toBeNull();
2371
- expect2(await store.deleteSchedule?.("s1")).toBe(true);
2372
- expect2(await store.deleteSchedule?.("s1")).toBe(false);
2373
- expect2(await store.getSchedule?.("s1")).toBeNull();
3045
+ expect3(replaced?.workflow).toBe("digest2");
3046
+ expect3(replaced?.nextFireAt).toBeNull();
3047
+ expect3(replaced?.tags ?? []).toEqual([]);
3048
+ expect3(await store.getSchedule?.("nope")).toBeNull();
3049
+ expect3(await store.deleteSchedule?.("s1")).toBe(true);
3050
+ expect3(await store.deleteSchedule?.("s1")).toBe(false);
3051
+ expect3(await store.getSchedule?.("s1")).toBeNull();
2374
3052
  });
2375
3053
  t("updateSchedule patches, and compare-and-sets on nextFireAt", async () => {
2376
3054
  await store.saveSchedule?.(schedule());
2377
- expect2(await store.updateSchedule?.("s1", {
3055
+ expect3(await store.updateSchedule?.("s1", {
2378
3056
  paused: true
2379
3057
  })).toBe(true);
2380
- expect2((await store.getSchedule?.("s1"))?.paused).toBe(true);
3058
+ expect3((await store.getSchedule?.("s1"))?.paused).toBe(true);
2381
3059
  const next = {
2382
3060
  nextFireAt: NOW + 12e4,
2383
3061
  state: {
@@ -2385,24 +3063,24 @@ function runStateStoreContract(name, makeStore) {
2385
3063
  fires: 1
2386
3064
  }
2387
3065
  };
2388
- expect2(await store.updateSchedule?.("s1", next, NOW + 6e4)).toBe(true);
2389
- expect2(await store.updateSchedule?.("s1", next, NOW + 6e4)).toBe(false);
3066
+ expect3(await store.updateSchedule?.("s1", next, NOW + 6e4)).toBe(true);
3067
+ expect3(await store.updateSchedule?.("s1", next, NOW + 6e4)).toBe(false);
2390
3068
  const after = await store.getSchedule?.("s1");
2391
- expect2(after?.nextFireAt).toBe(NOW + 12e4);
2392
- expect2(after?.state).toEqual({
3069
+ expect3(after?.nextFireAt).toBe(NOW + 12e4);
3070
+ expect3(after?.state).toEqual({
2393
3071
  window: NOW + 12e4,
2394
3072
  fires: 1
2395
3073
  });
2396
3074
  await store.updateSchedule?.("s1", {
2397
3075
  nextFireAt: null
2398
3076
  });
2399
- expect2(await store.updateSchedule?.("s1", {
3077
+ expect3(await store.updateSchedule?.("s1", {
2400
3078
  nextFireAt: NOW
2401
3079
  }, NOW + 1)).toBe(false);
2402
- expect2(await store.updateSchedule?.("s1", {
3080
+ expect3(await store.updateSchedule?.("s1", {
2403
3081
  nextFireAt: NOW
2404
3082
  }, null)).toBe(true);
2405
- expect2(await store.updateSchedule?.("ghost", {
3083
+ expect3(await store.updateSchedule?.("ghost", {
2406
3084
  paused: true
2407
3085
  })).toBe(false);
2408
3086
  });
@@ -2434,47 +3112,47 @@ function runStateStoreContract(name, makeStore) {
2434
3112
  ]
2435
3113
  }));
2436
3114
  const ids2 = /* @__PURE__ */ __name(async (q) => (await store.listSchedules?.(q) ?? []).map((r) => r.id), "ids");
2437
- expect2(await ids2({})).toEqual([
3115
+ expect3(await ids2({})).toEqual([
2438
3116
  "c",
2439
3117
  "b",
2440
3118
  "a",
2441
3119
  "d",
2442
3120
  "e"
2443
3121
  ]);
2444
- expect2(await ids2({
3122
+ expect3(await ids2({
2445
3123
  dueBy: NOW
2446
3124
  })).toEqual([
2447
3125
  "b",
2448
3126
  "a"
2449
3127
  ]);
2450
- expect2(await ids2({
3128
+ expect3(await ids2({
2451
3129
  dueBy: NOW,
2452
3130
  namespace: "default"
2453
3131
  })).toEqual([
2454
3132
  "a"
2455
3133
  ]);
2456
- expect2(await ids2({
3134
+ expect3(await ids2({
2457
3135
  dueBy: NOW,
2458
3136
  limit: 1
2459
3137
  })).toEqual([
2460
3138
  "b"
2461
3139
  ]);
2462
- expect2(await ids2({
3140
+ expect3(await ids2({
2463
3141
  workflow: "other"
2464
3142
  })).toEqual([
2465
3143
  "d"
2466
3144
  ]);
2467
- expect2(await ids2({
3145
+ expect3(await ids2({
2468
3146
  paused: true
2469
3147
  })).toEqual([
2470
3148
  "c"
2471
3149
  ]);
2472
- if (supportsTagFilter) expect2(await ids2({
3150
+ if (supportsTagFilter) expect3(await ids2({
2473
3151
  tag: "tenant:b"
2474
3152
  })).toEqual([
2475
3153
  "e"
2476
3154
  ]);
2477
- expect2(await ids2({
3155
+ expect3(await ids2({
2478
3156
  limit: 2,
2479
3157
  offset: 1
2480
3158
  })).toEqual([
@@ -2495,18 +3173,18 @@ function runStateStoreContract(name, makeStore) {
2495
3173
  id: "new",
2496
3174
  createdAt: /* @__PURE__ */ new Date("2026-06-11T00:00:02.000Z")
2497
3175
  }));
2498
- expect2((await store.listRuns({})).map((r) => r.id)).toEqual([
3176
+ expect3((await store.listRuns({})).map((r) => r.id)).toEqual([
2499
3177
  "new",
2500
3178
  "mid",
2501
3179
  "old"
2502
3180
  ]);
2503
- expect2((await store.listRuns({
3181
+ expect3((await store.listRuns({
2504
3182
  limit: 2
2505
3183
  })).map((r) => r.id)).toEqual([
2506
3184
  "new",
2507
3185
  "mid"
2508
3186
  ]);
2509
- expect2((await store.listRuns({
3187
+ expect3((await store.listRuns({
2510
3188
  limit: 2,
2511
3189
  offset: 1
2512
3190
  })).map((r) => r.id)).toEqual([
@@ -2536,11 +3214,11 @@ function runStateStoreContract(name, makeStore) {
2536
3214
  tier: "pro"
2537
3215
  }
2538
3216
  }));
2539
- expect2((await store.getRun("b"))?.searchAttributes).toEqual({
3217
+ expect3((await store.getRun("b"))?.searchAttributes).toEqual({
2540
3218
  amount: 200,
2541
3219
  tier: "pro"
2542
3220
  });
2543
- expect2((await store.listRuns({
3221
+ expect3((await store.listRuns({
2544
3222
  attributes: [
2545
3223
  {
2546
3224
  key: "amount",
@@ -2552,7 +3230,7 @@ function runStateStoreContract(name, makeStore) {
2552
3230
  "b",
2553
3231
  "c"
2554
3232
  ]);
2555
- expect2((await store.listRuns({
3233
+ expect3((await store.listRuns({
2556
3234
  attributes: [
2557
3235
  {
2558
3236
  key: "tier",
@@ -2568,7 +3246,7 @@ function runStateStoreContract(name, makeStore) {
2568
3246
  })).map((r) => r.id)).toEqual([
2569
3247
  "b"
2570
3248
  ]);
2571
- expect2((await store.listRuns({
3249
+ expect3((await store.listRuns({
2572
3250
  attributes: [
2573
3251
  {
2574
3252
  key: "tier",
@@ -2600,7 +3278,7 @@ function runStateStoreContract(name, makeStore) {
2600
3278
  other: 1
2601
3279
  }
2602
3280
  }));
2603
- expect2((await store.listRuns({
3281
+ expect3((await store.listRuns({
2604
3282
  attributes: [
2605
3283
  {
2606
3284
  key: "vip",
@@ -2611,7 +3289,7 @@ function runStateStoreContract(name, makeStore) {
2611
3289
  })).map((r) => r.id)).toEqual([
2612
3290
  "a"
2613
3291
  ]);
2614
- expect2((await store.listRuns({
3292
+ expect3((await store.listRuns({
2615
3293
  attributes: [
2616
3294
  {
2617
3295
  key: "vip",
@@ -2638,7 +3316,7 @@ function runStateStoreContract(name, makeStore) {
2638
3316
  "lt",
2639
3317
  "lte"
2640
3318
  ]) {
2641
- expect2(await store.listRuns({
3319
+ expect3(await store.listRuns({
2642
3320
  attributes: [
2643
3321
  {
2644
3322
  key: "missing",
@@ -2657,7 +3335,7 @@ function runStateStoreContract(name, makeStore) {
2657
3335
  amount: 10
2658
3336
  }
2659
3337
  }));
2660
- expect2((await store.listRuns({
3338
+ expect3((await store.listRuns({
2661
3339
  attributes: [
2662
3340
  {
2663
3341
  key: "tier",
@@ -2673,7 +3351,7 @@ function runStateStoreContract(name, makeStore) {
2673
3351
  tier: "pro"
2674
3352
  }
2675
3353
  });
2676
- expect2((await store.listRuns({
3354
+ expect3((await store.listRuns({
2677
3355
  attributes: [
2678
3356
  {
2679
3357
  key: "tier",
@@ -2684,7 +3362,7 @@ function runStateStoreContract(name, makeStore) {
2684
3362
  })).map((r) => r.id)).toEqual([
2685
3363
  "a"
2686
3364
  ]);
2687
- expect2(await store.listRuns({
3365
+ expect3(await store.listRuns({
2688
3366
  attributes: [
2689
3367
  {
2690
3368
  key: "tier",
@@ -2693,7 +3371,7 @@ function runStateStoreContract(name, makeStore) {
2693
3371
  }
2694
3372
  ]
2695
3373
  })).toHaveLength(0);
2696
- expect2(await store.listRuns({
3374
+ expect3(await store.listRuns({
2697
3375
  attributes: [
2698
3376
  {
2699
3377
  key: "amount",
@@ -2736,7 +3414,7 @@ function runStateStoreContract(name, makeStore) {
2736
3414
  ],
2737
3415
  limit: 10
2738
3416
  });
2739
- expect2(res.map((r) => r.id)).toEqual([
3417
+ expect3(res.map((r) => r.id)).toEqual([
2740
3418
  "a"
2741
3419
  ]);
2742
3420
  });
@@ -2756,12 +3434,12 @@ function runStateStoreContract(name, makeStore) {
2756
3434
  runId: "r3",
2757
3435
  seq: 5
2758
3436
  });
2759
- expect2((await store.listSignalWaiters("approve-")).map((w) => w.token).sort()).toEqual([
3437
+ expect3((await store.listSignalWaiters("approve-")).map((w) => w.token).sort()).toEqual([
2760
3438
  "approve-1",
2761
3439
  "approve-2"
2762
3440
  ]);
2763
- expect2((await store.takeSignalWaiter("approve-1"))?.seq).toBe(3);
2764
- expect2(await store.takeSignalWaiter("approve-1")).toBeNull();
3441
+ expect3((await store.takeSignalWaiter("approve-1"))?.seq).toBe(3);
3442
+ expect3(await store.takeSignalWaiter("approve-1")).toBeNull();
2765
3443
  });
2766
3444
  t("round-trips a signal waiter parallelGroup (child-fan tag) through put \u2192 take \u2192 list", async () => {
2767
3445
  await store.putSignalWaiter({
@@ -2776,13 +3454,13 @@ function runStateStoreContract(name, makeStore) {
2776
3454
  seq: 9
2777
3455
  });
2778
3456
  const listed = await store.listSignalWaiters("child:");
2779
- expect2(listed.find((w) => w.token === "child:r.child.0")?.parallelGroup).toBe("gather:0");
2780
- expect2(listed.find((w) => w.token === "child:r.child.9")?.parallelGroup).toBeUndefined();
2781
- expect2((await store.takeSignalWaiter("child:r.child.0"))?.parallelGroup).toBe("gather:0");
2782
- expect2((await store.takeSignalWaiter("child:r.child.9"))?.parallelGroup).toBeUndefined();
3457
+ expect3(listed.find((w) => w.token === "child:r.child.0")?.parallelGroup).toBe("gather:0");
3458
+ expect3(listed.find((w) => w.token === "child:r.child.9")?.parallelGroup).toBeUndefined();
3459
+ expect3((await store.takeSignalWaiter("child:r.child.0"))?.parallelGroup).toBe("gather:0");
3460
+ expect3((await store.takeSignalWaiter("child:r.child.9"))?.parallelGroup).toBeUndefined();
2783
3461
  });
2784
3462
  t("registerChildWaits writes every waiter and placeholder, and upserts on repeat", async () => {
2785
- expect2(store.registerChildWaits).toBeTypeOf("function");
3463
+ expect3(store.registerChildWaits).toBeTypeOf("function");
2786
3464
  await store.createRun(run({
2787
3465
  id: "p"
2788
3466
  }));
@@ -2808,24 +3486,24 @@ function runStateStoreContract(name, makeStore) {
2808
3486
  }, (_, i) => entry(i, "running"));
2809
3487
  await store.registerChildWaits?.(entries);
2810
3488
  const waiters = await store.listSignalWaiters("child:p.all.0.");
2811
- expect2(waiters).toHaveLength(250);
2812
- expect2(waiters.find((w) => w.token === "child:p.all.0.7")).toEqual(entries[7]?.waiter);
3489
+ expect3(waiters).toHaveLength(250);
3490
+ expect3(waiters.find((w) => w.token === "child:p.all.0.7")).toEqual(entries[7]?.waiter);
2813
3491
  const cps = await store.listCheckpoints("p");
2814
- expect2(cps).toHaveLength(250);
2815
- expect2(cps[7]).toMatchObject({
3492
+ expect3(cps).toHaveLength(250);
3493
+ expect3(cps[7]).toMatchObject({
2816
3494
  name: "signal:child:p.all.0.7",
2817
3495
  status: "running"
2818
3496
  });
2819
- expect2(cps[7]?.parallelGroup).toBe("all:0");
3497
+ expect3(cps[7]?.parallelGroup).toBe("all:0");
2820
3498
  await store.registerChildWaits?.([
2821
3499
  entry(7, "completed")
2822
3500
  ]);
2823
- expect2((await store.getCheckpoint("p", 7))?.status).toBe("completed");
2824
- expect2(await store.listCheckpoints("p")).toHaveLength(250);
2825
- await expect2(store.registerChildWaits?.([])).resolves.toBeUndefined();
3501
+ expect3((await store.getCheckpoint("p", 7))?.status).toBe("completed");
3502
+ expect3(await store.listCheckpoints("p")).toHaveLength(250);
3503
+ await expect3(store.registerChildWaits?.([])).resolves.toBeUndefined();
2826
3504
  });
2827
3505
  t("compactCheckpoints replaces a seq range with one checkpoint, atomically", async () => {
2828
- expect2(store.compactCheckpoints).toBeTypeOf("function");
3506
+ expect3(store.compactCheckpoints).toBeTypeOf("function");
2829
3507
  await store.createRun(run({
2830
3508
  id: "r"
2831
3509
  }));
@@ -2864,18 +3542,18 @@ function runStateStoreContract(name, makeStore) {
2864
3542
  });
2865
3543
  await store.compactCheckpoints?.("r", 2, 7, into);
2866
3544
  const left = await store.listCheckpoints("r");
2867
- expect2(left.map((cp) => cp.seq)).toEqual([
3545
+ expect3(left.map((cp2) => cp2.seq)).toEqual([
2868
3546
  0,
2869
3547
  1,
2870
3548
  2,
2871
3549
  8,
2872
3550
  9
2873
3551
  ]);
2874
- expect2(left[2]).toMatchObject({
3552
+ expect3(left[2]).toMatchObject({
2875
3553
  name: "fan:r.all.2.",
2876
3554
  parallelGroup: "all:2"
2877
3555
  });
2878
- expect2(left[2]?.output).toEqual({
3556
+ expect3(left[2]?.output).toEqual({
2879
3557
  from: 0,
2880
3558
  values: [
2881
3559
  {
@@ -2885,10 +3563,10 @@ function runStateStoreContract(name, makeStore) {
2885
3563
  null
2886
3564
  ]
2887
3565
  });
2888
- expect2(await store.listCheckpoints("other")).toHaveLength(1);
3566
+ expect3(await store.listCheckpoints("other")).toHaveLength(1);
2889
3567
  });
2890
3568
  t("listSignalWaitersByRun returns only the given runs' waiters", async () => {
2891
- expect2(store.listSignalWaitersByRun).toBeTypeOf("function");
3569
+ expect3(store.listSignalWaitersByRun).toBeTypeOf("function");
2892
3570
  await store.putSignalWaiter({
2893
3571
  token: "child:a.all.0.0",
2894
3572
  runId: "a",
@@ -2911,7 +3589,7 @@ function runStateStoreContract(name, makeStore) {
2911
3589
  seq: 0
2912
3590
  });
2913
3591
  const tokens = /* @__PURE__ */ __name(async (ids2) => (await store.listSignalWaitersByRun?.(ids2) ?? []).map((w) => w.token).sort(), "tokens");
2914
- expect2(await tokens([
3592
+ expect3(await tokens([
2915
3593
  "a",
2916
3594
  "b"
2917
3595
  ])).toEqual([
@@ -2919,11 +3597,11 @@ function runStateStoreContract(name, makeStore) {
2919
3597
  "approve-b",
2920
3598
  "child:a.all.0.0"
2921
3599
  ]);
2922
- expect2(await tokens([
3600
+ expect3(await tokens([
2923
3601
  "missing"
2924
3602
  ])).toEqual([]);
2925
- expect2(await tokens([])).toEqual([]);
2926
- expect2((await store.listSignalWaitersByRun?.([
3603
+ expect3(await tokens([])).toEqual([]);
3604
+ expect3((await store.listSignalWaitersByRun?.([
2927
3605
  "a"
2928
3606
  ]))?.find((w) => w.seq === 0)).toEqual({
2929
3607
  token: "child:a.all.0.0",
@@ -2933,7 +3611,7 @@ function runStateStoreContract(name, makeStore) {
2933
3611
  });
2934
3612
  });
2935
3613
  t("hasSignalWaiter answers by run and exact token prefix", async () => {
2936
- expect2(store.hasSignalWaiter).toBeTypeOf("function");
3614
+ expect3(store.hasSignalWaiter).toBeTypeOf("function");
2937
3615
  const has = /* @__PURE__ */ __name((runId, prefix) => store.hasSignalWaiter?.(runId, prefix), "has");
2938
3616
  await store.putSignalWaiter({
2939
3617
  token: "child:p_1.all.3.0",
@@ -2951,13 +3629,13 @@ function runStateStoreContract(name, makeStore) {
2951
3629
  runId: "p_1",
2952
3630
  seq: 9
2953
3631
  });
2954
- expect2(await has("p_1", "child:p_1.all.3.")).toBe(true);
2955
- expect2(await has("p_1", "child:p_1.all.4.")).toBe(false);
2956
- expect2(await has("other", "child:p_1.all.3.")).toBe(false);
2957
- expect2(await has("p_1", "child:p%.all.3.")).toBe(false);
2958
- expect2(await has("p_1", "CHILD:p_1.all.3.")).toBe(false);
3632
+ expect3(await has("p_1", "child:p_1.all.3.")).toBe(true);
3633
+ expect3(await has("p_1", "child:p_1.all.4.")).toBe(false);
3634
+ expect3(await has("other", "child:p_1.all.3.")).toBe(false);
3635
+ expect3(await has("p_1", "child:p%.all.3.")).toBe(false);
3636
+ expect3(await has("p_1", "CHILD:p_1.all.3.")).toBe(false);
2959
3637
  await store.takeSignalWaiter("child:p_1.all.3.0");
2960
- expect2(await has("p_1", "child:p_1.all.3.")).toBe(false);
3638
+ expect3(await has("p_1", "child:p_1.all.3.")).toBe(false);
2961
3639
  });
2962
3640
  t("removeSignalWaiter deletes only the exact (token, runId, seq) row, never a different run's", async () => {
2963
3641
  await store.putSignalWaiter({
@@ -2975,7 +3653,7 @@ function runStateStoreContract(name, makeStore) {
2975
3653
  runId: "r1",
2976
3654
  seq: 3
2977
3655
  });
2978
- expect2((await store.listSignalWaiters("approve-")).map((w) => w.runId)).toEqual([
3656
+ expect3((await store.listSignalWaiters("approve-")).map((w) => w.runId)).toEqual([
2979
3657
  "r2"
2980
3658
  ]);
2981
3659
  await store.removeSignalWaiter({
@@ -2983,7 +3661,7 @@ function runStateStoreContract(name, makeStore) {
2983
3661
  runId: "r2",
2984
3662
  seq: 999
2985
3663
  });
2986
- expect2((await store.listSignalWaiters("approve-")).map((w) => w.runId)).toEqual([
3664
+ expect3((await store.listSignalWaiters("approve-")).map((w) => w.runId)).toEqual([
2987
3665
  "r2"
2988
3666
  ]);
2989
3667
  await store.removeSignalWaiter({
@@ -2991,7 +3669,7 @@ function runStateStoreContract(name, makeStore) {
2991
3669
  runId: "r2",
2992
3670
  seq: 7
2993
3671
  });
2994
- expect2(await store.listSignalWaiters("approve-")).toEqual([]);
3672
+ expect3(await store.listSignalWaiters("approve-")).toEqual([]);
2995
3673
  await store.removeSignalWaiter({
2996
3674
  token: "never-registered",
2997
3675
  runId: "r1",
@@ -3008,18 +3686,18 @@ function runStateStoreContract(name, makeStore) {
3008
3686
  await store.bufferSignal("other", {
3009
3687
  n: 9
3010
3688
  });
3011
- expect2(await store.takeBufferedSignal("sig")).toEqual({
3689
+ expect3(await store.takeBufferedSignal("sig")).toEqual({
3012
3690
  payload: {
3013
3691
  n: 1
3014
3692
  }
3015
3693
  });
3016
- expect2(await store.takeBufferedSignal("sig")).toEqual({
3694
+ expect3(await store.takeBufferedSignal("sig")).toEqual({
3017
3695
  payload: {
3018
3696
  n: 2
3019
3697
  }
3020
3698
  });
3021
- expect2(await store.takeBufferedSignal("sig")).toBeNull();
3022
- expect2(await store.takeBufferedSignal("other")).toEqual({
3699
+ expect3(await store.takeBufferedSignal("sig")).toBeNull();
3700
+ expect3(await store.takeBufferedSignal("other")).toEqual({
3023
3701
  payload: {
3024
3702
  n: 9
3025
3703
  }
@@ -3051,7 +3729,7 @@ function runStateStoreContract(name, makeStore) {
3051
3729
  publishedAt: 50
3052
3730
  });
3053
3731
  const listed = await store.listBufferedEvents("order.paid", 10);
3054
- expect2(listed.map((e) => e.payload)).toEqual([
3732
+ expect3(listed.map((e) => e.payload)).toEqual([
3055
3733
  {
3056
3734
  n: 1
3057
3735
  },
@@ -3059,13 +3737,13 @@ function runStateStoreContract(name, makeStore) {
3059
3737
  n: 2
3060
3738
  }
3061
3739
  ]);
3062
- expect2(listed.map((e) => e.id)).toEqual([
3740
+ expect3(listed.map((e) => e.id)).toEqual([
3063
3741
  "e1",
3064
3742
  "e2"
3065
3743
  ]);
3066
- expect2(listed[0]?.publishedAt).toBe(100);
3067
- expect2(await store.listBufferedEvents("order.paid", 10)).toHaveLength(2);
3068
- expect2(await store.listBufferedEvents("other.event", 10)).toEqual([
3744
+ expect3(listed[0]?.publishedAt).toBe(100);
3745
+ expect3(await store.listBufferedEvents("order.paid", 10)).toHaveLength(2);
3746
+ expect3(await store.listBufferedEvents("other.event", 10)).toEqual([
3069
3747
  {
3070
3748
  id: "e3",
3071
3749
  payload: {
@@ -3094,7 +3772,7 @@ function runStateStoreContract(name, makeStore) {
3094
3772
  id: "c",
3095
3773
  publishedAt: 3
3096
3774
  });
3097
- expect2(await store.listBufferedEvents("evt", 2)).toHaveLength(2);
3775
+ expect3(await store.listBufferedEvents("evt", 2)).toHaveLength(2);
3098
3776
  });
3099
3777
  t("removeBufferedEvent atomically deletes by id \u2014 true iff a row existed, false on a repeat/absent id", async () => {
3100
3778
  await store.bufferEvent({
@@ -3105,10 +3783,10 @@ function runStateStoreContract(name, makeStore) {
3105
3783
  id: "x1",
3106
3784
  publishedAt: 1
3107
3785
  });
3108
- expect2(await store.removeBufferedEvent("x1")).toBe(true);
3109
- expect2(await store.listBufferedEvents("evt", 10)).toEqual([]);
3110
- expect2(await store.removeBufferedEvent("x1")).toBe(false);
3111
- expect2(await store.removeBufferedEvent("never-buffered")).toBe(false);
3786
+ expect3(await store.removeBufferedEvent("x1")).toBe(true);
3787
+ expect3(await store.listBufferedEvents("evt", 10)).toEqual([]);
3788
+ expect3(await store.removeBufferedEvent("x1")).toBe(false);
3789
+ expect3(await store.removeBufferedEvent("never-buffered")).toBe(false);
3112
3790
  });
3113
3791
  t("transaction commits the checkpoint atomically and returns the work result", async () => {
3114
3792
  if (!store.transaction) return;
@@ -3124,10 +3802,10 @@ function runStateStoreContract(name, makeStore) {
3124
3802
  }));
3125
3803
  return "ok";
3126
3804
  });
3127
- expect2(result).toBe("ok");
3128
- const cp = await store.getCheckpoint("r1", 7);
3129
- expect2(cp?.name).toBe("tx-step");
3130
- expect2(cp?.output).toEqual({
3805
+ expect3(result).toBe("ok");
3806
+ const cp2 = await store.getCheckpoint("r1", 7);
3807
+ expect3(cp2?.name).toBe("tx-step");
3808
+ expect3(cp2?.output).toEqual({
3131
3809
  paid: true
3132
3810
  });
3133
3811
  });
@@ -3154,11 +3832,11 @@ function runStateStoreContract(name, makeStore) {
3154
3832
  await engine.start("wf", {
3155
3833
  x: 1
3156
3834
  }, "run1");
3157
- expect2((await engine.waitForRun("run1")).status).toBe("failed");
3835
+ expect3((await engine.waitForRun("run1")).status).toBe("failed");
3158
3836
  const resumed = await engine.resume("run1");
3159
- expect2(resumed.status).toBe("completed");
3160
- expect2(resumed.output).toBe(15);
3161
- expect2(aRuns).toBe(1);
3837
+ expect3(resumed.status).toBe("completed");
3838
+ expect3(resumed.output).toBe(15);
3839
+ expect3(aRuns).toBe(1);
3162
3840
  });
3163
3841
  t("starts the version the caller pinned, and refuses one that is not registered", async () => {
3164
3842
  const engine = new WorkflowEngine3({
@@ -3179,19 +3857,19 @@ function runStateStoreContract(name, makeStore) {
3179
3857
  const pinned = await engine.waitForRun("pinned-run", {
3180
3858
  timeoutMs: 2e4
3181
3859
  });
3182
- expect2(pinned.output).toBe("v1-output");
3183
- expect2(ran).toEqual([
3860
+ expect3(pinned.output).toBe("v1-output");
3861
+ expect3(ran).toEqual([
3184
3862
  "v1"
3185
3863
  ]);
3186
- expect2((await store.getRun("pinned-run"))?.workflowVersion).toBe("1");
3864
+ expect3((await store.getRun("pinned-run"))?.workflowVersion).toBe("1");
3187
3865
  await engine.start("vwf", {}, "newest-run");
3188
- expect2((await engine.waitForRun("newest-run", {
3866
+ expect3((await engine.waitForRun("newest-run", {
3189
3867
  timeoutMs: 2e4
3190
3868
  })).output).toBe("v2-output");
3191
- await expect2(engine.start("vwf", {}, "ghost-run", {
3869
+ await expect3(engine.start("vwf", {}, "ghost-run", {
3192
3870
  version: "9"
3193
3871
  })).rejects.toThrow(/vwf@9 is not registered/);
3194
- expect2(await store.getRun("ghost-run")).toBeNull();
3872
+ expect3(await store.getRun("ghost-run")).toBeNull();
3195
3873
  });
3196
3874
  t("cancels a timed-out run\u2019s live child subtree, not just the run itself", async () => {
3197
3875
  const engine = new WorkflowEngine3({
@@ -3214,16 +3892,16 @@ function runStateStoreContract(name, makeStore) {
3214
3892
  "tc",
3215
3893
  "tgc"
3216
3894
  ]) {
3217
- expect2((await engine.waitForRun(id, {
3895
+ expect3((await engine.waitForRun(id, {
3218
3896
  timeoutMs: 2e4
3219
3897
  })).status).toBe("suspended");
3220
3898
  }
3221
3899
  await engine.sweepTimeouts(Date.now() + 37e5);
3222
3900
  const parent = await store.getRun("tp");
3223
- expect2(parent?.status).toBe("cancelled");
3224
- expect2(parent?.error?.code).toBe("execution_timeout");
3225
- expect2((await store.getRun("tc"))?.status).toBe("cancelled");
3226
- expect2((await store.getRun("tgc"))?.status).toBe("cancelled");
3901
+ expect3(parent?.status).toBe("cancelled");
3902
+ expect3(parent?.error?.code).toBe("execution_timeout");
3903
+ expect3((await store.getRun("tc"))?.status).toBe("cancelled");
3904
+ expect3((await store.getRun("tgc"))?.status).toBe("cancelled");
3227
3905
  });
3228
3906
  });
3229
3907
  }
@@ -3295,6 +3973,7 @@ export {
3295
3973
  DURABLE_CANONICAL_COLUMNS,
3296
3974
  MutableClock,
3297
3975
  StateStoreUnavailableError,
3976
+ aggregationFixture,
3298
3977
  assertDurableColumns,
3299
3978
  assertOutput,
3300
3979
  assertReplayable,
@@ -3307,6 +3986,7 @@ export {
3307
3986
  failTimes,
3308
3987
  preserveColumnExpectation,
3309
3988
  recordedSteps,
3989
+ registerCheckpointAggregationCases,
3310
3990
  runAdmissionBackendContract,
3311
3991
  runStateStoreContract
3312
3992
  };