@dudousxd/nestjs-durable-testing 0.6.0 → 0.7.1

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
@@ -5,6 +5,170 @@ var __export = (target, all) => {
5
5
  __defProp(target, name, { get: all[name], enumerable: true });
6
6
  };
7
7
 
8
+ // src/admission-backend-conformance.ts
9
+ import { describe, expect, it } from "vitest";
10
+ function runAdmissionBackendContract(name, makeBackend) {
11
+ describe(`AdmissionBackend contract: ${name}`, () => {
12
+ let now = 1e6;
13
+ const make = /* @__PURE__ */ __name((config) => {
14
+ now = 1e6;
15
+ const backend = makeBackend(() => now);
16
+ backend.register(config);
17
+ return backend;
18
+ }, "make");
19
+ it("caps concurrency: a second call blocks until the first releases", async () => {
20
+ const b = make({
21
+ name: "q",
22
+ concurrency: 1
23
+ });
24
+ expect((await b.tryAdmit("q", {
25
+ waiterId: "a"
26
+ })).ok).toBe(true);
27
+ expect((await b.tryAdmit("q", {
28
+ waiterId: "b"
29
+ })).ok).toBe(false);
30
+ await b.release("q", "a");
31
+ expect((await b.tryAdmit("q", {
32
+ waiterId: "b"
33
+ })).ok).toBe(true);
34
+ });
35
+ it("enforces a fixed-window rate limit", async () => {
36
+ const b = make({
37
+ name: "q",
38
+ rateLimit: {
39
+ limit: 2,
40
+ periodMs: 1e3
41
+ }
42
+ });
43
+ expect((await b.tryAdmit("q", {
44
+ waiterId: "1"
45
+ })).ok).toBe(true);
46
+ expect((await b.tryAdmit("q", {
47
+ waiterId: "2"
48
+ })).ok).toBe(true);
49
+ expect((await b.tryAdmit("q", {
50
+ waiterId: "3"
51
+ })).ok).toBe(false);
52
+ now += 1001;
53
+ expect((await b.tryAdmit("q", {
54
+ waiterId: "4"
55
+ })).ok).toBe(true);
56
+ });
57
+ it("admits the highest-priority waiter first when a slot frees", async () => {
58
+ const b = make({
59
+ name: "q",
60
+ concurrency: 1
61
+ });
62
+ expect((await b.tryAdmit("q", {
63
+ waiterId: "holder"
64
+ })).ok).toBe(true);
65
+ expect((await b.tryAdmit("q", {
66
+ waiterId: "low",
67
+ priority: 1
68
+ })).ok).toBe(false);
69
+ expect((await b.tryAdmit("q", {
70
+ waiterId: "high",
71
+ priority: 9
72
+ })).ok).toBe(false);
73
+ await b.release("q", "holder");
74
+ expect((await b.tryAdmit("q", {
75
+ waiterId: "low",
76
+ priority: 1
77
+ })).ok).toBe(false);
78
+ expect((await b.tryAdmit("q", {
79
+ waiterId: "high",
80
+ priority: 9
81
+ })).ok).toBe(true);
82
+ });
83
+ it("orders plain-concurrency waiters by arrival (FIFO) \u2014 no priority/fairness configured", async () => {
84
+ const b = make({
85
+ name: "q",
86
+ concurrency: 1
87
+ });
88
+ expect((await b.tryAdmit("q", {
89
+ waiterId: "holder"
90
+ })).ok).toBe(true);
91
+ expect((await b.tryAdmit("q", {
92
+ waiterId: "first"
93
+ })).ok).toBe(false);
94
+ expect((await b.tryAdmit("q", {
95
+ waiterId: "second"
96
+ })).ok).toBe(false);
97
+ await b.release("q", "holder");
98
+ expect((await b.tryAdmit("q", {
99
+ waiterId: "second"
100
+ })).ok).toBe(false);
101
+ expect((await b.tryAdmit("q", {
102
+ waiterId: "first"
103
+ })).ok).toBe(true);
104
+ });
105
+ it("admits the most-recent arrival first when order is LIFO", async () => {
106
+ const b = make({
107
+ name: "q",
108
+ concurrency: 1,
109
+ order: "lifo"
110
+ });
111
+ expect((await b.tryAdmit("q", {
112
+ waiterId: "holder"
113
+ })).ok).toBe(true);
114
+ expect((await b.tryAdmit("q", {
115
+ waiterId: "first"
116
+ })).ok).toBe(false);
117
+ expect((await b.tryAdmit("q", {
118
+ waiterId: "second"
119
+ })).ok).toBe(false);
120
+ await b.release("q", "holder");
121
+ expect((await b.tryAdmit("q", {
122
+ waiterId: "first"
123
+ })).ok).toBe(false);
124
+ expect((await b.tryAdmit("q", {
125
+ waiterId: "second"
126
+ })).ok).toBe(true);
127
+ });
128
+ it("round-robins a contended slot across fairness keys", async () => {
129
+ const b = make({
130
+ name: "q",
131
+ concurrency: 1,
132
+ fairness: "key"
133
+ });
134
+ expect((await b.tryAdmit("q", {
135
+ waiterId: "a0",
136
+ key: "A"
137
+ })).ok).toBe(true);
138
+ expect((await b.tryAdmit("q", {
139
+ waiterId: "a1",
140
+ key: "A"
141
+ })).ok).toBe(false);
142
+ expect((await b.tryAdmit("q", {
143
+ waiterId: "b0",
144
+ key: "B"
145
+ })).ok).toBe(false);
146
+ await b.release("q", "a0");
147
+ expect((await b.tryAdmit("q", {
148
+ waiterId: "a1",
149
+ key: "A"
150
+ })).ok).toBe(false);
151
+ expect((await b.tryAdmit("q", {
152
+ waiterId: "b0",
153
+ key: "B"
154
+ })).ok).toBe(true);
155
+ });
156
+ it("leaves an unregistered queue ungated", async () => {
157
+ const b = make({
158
+ name: "q",
159
+ concurrency: 1
160
+ });
161
+ expect((await b.tryAdmit("other", {
162
+ waiterId: "x"
163
+ })).ok).toBe(true);
164
+ expect((await b.tryAdmit("other", {
165
+ waiterId: "y"
166
+ })).ok).toBe(true);
167
+ });
168
+ });
169
+ }
170
+ __name(runAdmissionBackendContract, "runAdmissionBackendContract");
171
+
8
172
  // src/assertions.ts
9
173
  async function requireRun(store, runId) {
10
174
  const run2 = await store.getRun(runId);
@@ -200,7 +364,7 @@ __name(assertReplayable, "assertReplayable");
200
364
 
201
365
  // src/state-store-conformance.ts
202
366
  import { WorkflowEngine as WorkflowEngine3 } from "@dudousxd/nestjs-durable-core";
203
- import { beforeEach, describe, expect, it } from "vitest";
367
+ import { beforeEach, describe as describe2, expect as expect2, it as it2 } from "vitest";
204
368
  var StateStoreUnavailableError = class extends Error {
205
369
  static {
206
370
  __name(this, "StateStoreUnavailableError");
@@ -245,7 +409,7 @@ var checkpoint = /* @__PURE__ */ __name((over = {}) => ({
245
409
  ...over
246
410
  }), "checkpoint");
247
411
  function runStateStoreContract(name, makeStore) {
248
- describe(`StateStore contract: ${name}`, () => {
412
+ describe2(`StateStore contract: ${name}`, () => {
249
413
  let store;
250
414
  let cleanup;
251
415
  let supportsAsyncTransaction = true;
@@ -276,7 +440,7 @@ function runStateStoreContract(name, makeStore) {
276
440
  };
277
441
  });
278
442
  const t = /* @__PURE__ */ __name((label, fn) => {
279
- it(label, async () => {
443
+ it2(label, async () => {
280
444
  if (skipReason) return;
281
445
  await fn();
282
446
  });
@@ -284,13 +448,13 @@ function runStateStoreContract(name, makeStore) {
284
448
  t("creates a run and reads it back with its JSON input", async () => {
285
449
  await store.createRun(run());
286
450
  const loaded = await store.getRun("r1");
287
- expect(loaded?.workflow).toBe("checkout");
288
- expect(loaded?.input).toEqual({
451
+ expect2(loaded?.workflow).toBe("checkout");
452
+ expect2(loaded?.input).toEqual({
289
453
  orderId: "o1"
290
454
  });
291
455
  });
292
456
  t("returns null for a missing run", async () => {
293
- expect(await store.getRun("nope")).toBeNull();
457
+ expect2(await store.getRun("nope")).toBeNull();
294
458
  });
295
459
  t("updates a run (status/output) and round-trips recoveryAttempts + dead status", async () => {
296
460
  await store.createRun(run({
@@ -304,18 +468,29 @@ function runStateStoreContract(name, makeStore) {
304
468
  updatedAt: at
305
469
  });
306
470
  const done = await store.getRun("r1");
307
- expect(done?.status).toBe("completed");
308
- expect(done?.output).toEqual({
471
+ expect2(done?.status).toBe("completed");
472
+ expect2(done?.output).toEqual({
309
473
  total: 42
310
474
  });
311
- expect(done?.recoveryAttempts).toBe(3);
475
+ expect2(done?.recoveryAttempts).toBe(3);
312
476
  await store.updateRun("r1", {
313
477
  status: "dead",
314
478
  recoveryAttempts: 4
315
479
  });
316
480
  const dead = await store.getRun("r1");
317
- expect(dead?.status).toBe("dead");
318
- expect(dead?.recoveryAttempts).toBe(4);
481
+ expect2(dead?.status).toBe("dead");
482
+ expect2(dead?.recoveryAttempts).toBe(4);
483
+ });
484
+ t("round-trips a run dispatch priority", async () => {
485
+ await store.createRun(run({
486
+ id: "withprio",
487
+ priority: 7
488
+ }));
489
+ await store.createRun(run({
490
+ id: "noprio"
491
+ }));
492
+ expect2((await store.getRun("withprio"))?.priority).toBe(7);
493
+ expect2((await store.getRun("noprio"))?.priority).toBeUndefined();
319
494
  });
320
495
  t("deleteRun removes the run and all its rows (checkpoints, waiters, attributes)", async () => {
321
496
  await store.createRun(run({
@@ -330,10 +505,10 @@ function runStateStoreContract(name, makeStore) {
330
505
  seq: 0
331
506
  });
332
507
  await store.deleteRun("r1");
333
- expect(await store.getRun("r1")).toBeNull();
334
- expect(await store.listCheckpoints("r1")).toEqual([]);
335
- expect(await store.listSignalWaiters("approve-")).toEqual([]);
336
- expect(await store.listRuns({
508
+ expect2(await store.getRun("r1")).toBeNull();
509
+ expect2(await store.listCheckpoints("r1")).toEqual([]);
510
+ expect2(await store.listSignalWaiters("approve-")).toEqual([]);
511
+ expect2(await store.listRuns({
337
512
  attributes: [
338
513
  {
339
514
  key: "tier",
@@ -344,7 +519,7 @@ function runStateStoreContract(name, makeStore) {
344
519
  })).toEqual([]);
345
520
  });
346
521
  t("deleteRun is a no-op for a missing run", async () => {
347
- await expect(store.deleteRun("nope")).resolves.toBeUndefined();
522
+ await expect2(store.deleteRun("nope")).resolves.toBeUndefined();
348
523
  });
349
524
  t("updateRun maps every patchable field \u2014 clears error and patches tags/lockedBy/input/timers", async () => {
350
525
  await store.createRun(run({
@@ -376,21 +551,21 @@ function runStateStoreContract(name, makeStore) {
376
551
  updatedAt: at
377
552
  });
378
553
  const r = await store.getRun("r1");
379
- expect(r?.status).toBe("completed");
380
- expect(r?.output).toEqual({
554
+ expect2(r?.status).toBe("completed");
555
+ expect2(r?.output).toEqual({
381
556
  ok: true
382
557
  });
383
- expect(r?.error).toBeUndefined();
384
- expect(r?.input).toEqual({
558
+ expect2(r?.error).toBeUndefined();
559
+ expect2(r?.input).toEqual({
385
560
  orderId: "o2"
386
561
  });
387
- expect(r?.tags).toEqual([
562
+ expect2(r?.tags).toEqual([
388
563
  "x",
389
564
  "y"
390
565
  ]);
391
- expect(r?.lockedBy).toBe("owner-2");
392
- expect(r?.wakeAt).toBe(123456);
393
- expect(r?.lockedUntil).toBe(222222);
566
+ expect2(r?.lockedBy).toBe("owner-2");
567
+ expect2(r?.wakeAt).toBe(123456);
568
+ expect2(r?.lockedUntil).toBe(222222);
394
569
  });
395
570
  t("upserts checkpoints, reads them by (runId, seq), and lists them ordered by seq", async () => {
396
571
  await store.createRun(run());
@@ -408,13 +583,13 @@ function runStateStoreContract(name, makeStore) {
408
583
  again: true
409
584
  }
410
585
  }));
411
- expect((await store.getCheckpoint("r1", 0))?.output).toEqual({
586
+ expect2((await store.getCheckpoint("r1", 0))?.output).toEqual({
412
587
  ok: true,
413
588
  again: true
414
589
  });
415
- expect((await store.getCheckpoint("r1", 1))?.name).toBe("charge");
590
+ expect2((await store.getCheckpoint("r1", 1))?.name).toBe("charge");
416
591
  const list = await store.listCheckpoints("r1");
417
- expect(list.map((c) => c.seq)).toEqual([
592
+ expect2(list.map((c) => c.seq)).toEqual([
418
593
  0,
419
594
  1
420
595
  ]);
@@ -450,14 +625,14 @@ function runStateStoreContract(name, makeStore) {
450
625
  }
451
626
  }));
452
627
  const getLatestCheckpointByName = store.getLatestCheckpointByName;
453
- expect(getLatestCheckpointByName).toBeDefined();
628
+ expect2(getLatestCheckpointByName).toBeDefined();
454
629
  if (!getLatestCheckpointByName) return;
455
630
  const latest = await getLatestCheckpointByName.call(store, "r1", "event:progress");
456
- expect(latest?.seq).toBe(3);
457
- expect(latest?.output).toEqual({
631
+ expect2(latest?.seq).toBe(3);
632
+ expect2(latest?.output).toEqual({
458
633
  pct: 90
459
634
  });
460
- expect(await getLatestCheckpointByName.call(store, "r1", "event:missing")).toBeUndefined();
635
+ expect2(await getLatestCheckpointByName.call(store, "r1", "event:missing")).toBeUndefined();
461
636
  });
462
637
  t("listCheckpointsByNamePrefix returns prefix matches ordered by seq (empty => none)", async () => {
463
638
  await store.createRun(run());
@@ -484,18 +659,18 @@ function runStateStoreContract(name, makeStore) {
484
659
  output: "child-b"
485
660
  }));
486
661
  const listCheckpointsByNamePrefix = store.listCheckpointsByNamePrefix;
487
- expect(listCheckpointsByNamePrefix).toBeDefined();
662
+ expect2(listCheckpointsByNamePrefix).toBeDefined();
488
663
  if (!listCheckpointsByNamePrefix) return;
489
664
  const matches = await listCheckpointsByNamePrefix.call(store, "r1", [
490
665
  "signal:child:",
491
666
  "spawn:"
492
667
  ]);
493
- expect(matches.map((c) => c.name)).toEqual([
668
+ expect2(matches.map((c) => c.name)).toEqual([
494
669
  "spawn:0",
495
670
  "signal:child:c2",
496
671
  "spawn:1"
497
672
  ]);
498
- expect(await listCheckpointsByNamePrefix.call(store, "r1", [])).toEqual([]);
673
+ expect2(await listCheckpointsByNamePrefix.call(store, "r1", [])).toEqual([]);
499
674
  });
500
675
  t("round-trips checkpoint events and reads back a missing checkpoint as null", async () => {
501
676
  await store.createRun(run());
@@ -510,7 +685,7 @@ function runStateStoreContract(name, makeStore) {
510
685
  }
511
686
  ]
512
687
  }));
513
- expect((await store.getCheckpoint("r1", 0))?.events).toEqual([
688
+ expect2((await store.getCheckpoint("r1", 0))?.events).toEqual([
514
689
  {
515
690
  at: 1,
516
691
  level: "error",
@@ -519,7 +694,7 @@ function runStateStoreContract(name, makeStore) {
519
694
  status: "failed"
520
695
  }
521
696
  ]);
522
- expect(await store.getCheckpoint("r1", 99)).toBeNull();
697
+ expect2(await store.getCheckpoint("r1", 99)).toBeNull();
523
698
  });
524
699
  t("lists incomplete runs, pending runs (FIFO), and due timers", async () => {
525
700
  await store.createRun(run({
@@ -545,39 +720,39 @@ function runStateStoreContract(name, makeStore) {
545
720
  status: "pending",
546
721
  createdAt: /* @__PURE__ */ new Date("2026-06-11T00:00:01.000Z")
547
722
  }));
548
- expect((await store.listIncompleteRuns()).map((r) => r.id)).toEqual([
723
+ expect2((await store.listIncompleteRuns()).map((r) => r.id)).toEqual([
549
724
  "running1"
550
725
  ]);
551
- expect((await store.listPendingRuns(10)).map((r) => r.id)).toEqual([
726
+ expect2((await store.listPendingRuns(10)).map((r) => r.id)).toEqual([
552
727
  "pending1",
553
728
  "pending2"
554
729
  ]);
555
- expect((await store.listPendingRuns(1)).map((r) => r.id)).toEqual([
730
+ expect2((await store.listPendingRuns(1)).map((r) => r.id)).toEqual([
556
731
  "pending1"
557
732
  ]);
558
- expect((await store.listDueTimers(1e4)).map((r) => r.id)).toEqual([
733
+ expect2((await store.listDueTimers(1e4)).map((r) => r.id)).toEqual([
559
734
  "suspended1"
560
735
  ]);
561
- expect(await store.listDueTimers(1e3)).toHaveLength(0);
736
+ expect2(await store.listDueTimers(1e3)).toHaveLength(0);
562
737
  });
563
738
  t("tryLockRun is atomic and respects lease expiry", async () => {
564
739
  await store.createRun(run({
565
740
  id: "r1"
566
741
  }));
567
- expect(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
568
- expect(await store.tryLockRun("r1", "B", 3e3, 1500)).toBe(false);
569
- expect(await store.tryLockRun("r1", "B", 4e3, 2500)).toBe(true);
742
+ expect2(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
743
+ expect2(await store.tryLockRun("r1", "B", 3e3, 1500)).toBe(false);
744
+ expect2(await store.tryLockRun("r1", "B", 4e3, 2500)).toBe(true);
570
745
  await store.releaseRunLock("r1");
571
- expect(await store.tryLockRun("r1", "C", 9e3, 2600)).toBe(true);
746
+ expect2(await store.tryLockRun("r1", "C", 9e3, 2600)).toBe(true);
572
747
  });
573
748
  t("renewRunLock only succeeds for the current owner", async () => {
574
749
  await store.createRun(run({
575
750
  id: "r1"
576
751
  }));
577
- expect(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
578
- expect(await store.renewRunLock("r1", "A", 5e3)).toBe(true);
579
- expect(await store.renewRunLock("r1", "B", 9e3)).toBe(false);
580
- expect(await store.tryLockRun("r1", "B", 6e3, 4e3)).toBe(false);
752
+ expect2(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
753
+ expect2(await store.renewRunLock("r1", "A", 5e3)).toBe(true);
754
+ expect2(await store.renewRunLock("r1", "B", 9e3)).toBe(false);
755
+ expect2(await store.tryLockRun("r1", "B", 6e3, 4e3)).toBe(false);
581
756
  });
582
757
  t("filters listRuns by workflow and by status", async () => {
583
758
  await store.createRun(run({
@@ -595,19 +770,19 @@ function runStateStoreContract(name, makeStore) {
595
770
  workflow: "checkout",
596
771
  status: "completed"
597
772
  }));
598
- expect((await store.listRuns({
773
+ expect2((await store.listRuns({
599
774
  workflow: "checkout"
600
775
  })).map((r) => r.id).sort()).toEqual([
601
776
  "a",
602
777
  "c"
603
778
  ]);
604
- expect((await store.listRuns({
779
+ expect2((await store.listRuns({
605
780
  status: "running"
606
781
  })).map((r) => r.id).sort()).toEqual([
607
782
  "a",
608
783
  "b"
609
784
  ]);
610
- expect((await store.listRuns({
785
+ expect2((await store.listRuns({
611
786
  workflow: "checkout",
612
787
  status: "running"
613
788
  })).map((r) => r.id)).toEqual([
@@ -631,7 +806,7 @@ function runStateStoreContract(name, makeStore) {
631
806
  id: "d",
632
807
  status: "pending"
633
808
  }));
634
- expect((await store.listRuns({
809
+ expect2((await store.listRuns({
635
810
  statuses: [
636
811
  "running",
637
812
  "suspended"
@@ -640,7 +815,7 @@ function runStateStoreContract(name, makeStore) {
640
815
  "a",
641
816
  "b"
642
817
  ]);
643
- expect((await store.listRuns({
818
+ expect2((await store.listRuns({
644
819
  status: "running",
645
820
  statuses: [
646
821
  "running",
@@ -649,7 +824,7 @@ function runStateStoreContract(name, makeStore) {
649
824
  })).map((r) => r.id)).toEqual([
650
825
  "a"
651
826
  ]);
652
- expect(await store.listRuns({
827
+ expect2(await store.listRuns({
653
828
  statuses: []
654
829
  })).toHaveLength(0);
655
830
  });
@@ -671,21 +846,21 @@ function runStateStoreContract(name, makeStore) {
671
846
  await store.createRun(run({
672
847
  id: "c"
673
848
  }));
674
- expect((await store.getRun("a"))?.tags).toEqual([
849
+ expect2((await store.getRun("a"))?.tags).toEqual([
675
850
  "etl",
676
851
  "critical"
677
852
  ]);
678
- expect((await store.listRuns({
853
+ expect2((await store.listRuns({
679
854
  tag: "etl"
680
855
  })).map((r) => r.id)).toEqual([
681
856
  "a"
682
857
  ]);
683
- expect((await store.listRuns({
858
+ expect2((await store.listRuns({
684
859
  tag: "etl-foo"
685
860
  })).map((r) => r.id)).toEqual([
686
861
  "b"
687
862
  ]);
688
- expect(await store.listRuns({
863
+ expect2(await store.listRuns({
689
864
  tag: "nope"
690
865
  })).toHaveLength(0);
691
866
  });
@@ -702,18 +877,18 @@ function runStateStoreContract(name, makeStore) {
702
877
  id: "new",
703
878
  createdAt: /* @__PURE__ */ new Date("2026-06-11T00:00:02.000Z")
704
879
  }));
705
- expect((await store.listRuns({})).map((r) => r.id)).toEqual([
880
+ expect2((await store.listRuns({})).map((r) => r.id)).toEqual([
706
881
  "new",
707
882
  "mid",
708
883
  "old"
709
884
  ]);
710
- expect((await store.listRuns({
885
+ expect2((await store.listRuns({
711
886
  limit: 2
712
887
  })).map((r) => r.id)).toEqual([
713
888
  "new",
714
889
  "mid"
715
890
  ]);
716
- expect((await store.listRuns({
891
+ expect2((await store.listRuns({
717
892
  limit: 2,
718
893
  offset: 1
719
894
  })).map((r) => r.id)).toEqual([
@@ -743,11 +918,11 @@ function runStateStoreContract(name, makeStore) {
743
918
  tier: "pro"
744
919
  }
745
920
  }));
746
- expect((await store.getRun("b"))?.searchAttributes).toEqual({
921
+ expect2((await store.getRun("b"))?.searchAttributes).toEqual({
747
922
  amount: 200,
748
923
  tier: "pro"
749
924
  });
750
- expect((await store.listRuns({
925
+ expect2((await store.listRuns({
751
926
  attributes: [
752
927
  {
753
928
  key: "amount",
@@ -759,7 +934,7 @@ function runStateStoreContract(name, makeStore) {
759
934
  "b",
760
935
  "c"
761
936
  ]);
762
- expect((await store.listRuns({
937
+ expect2((await store.listRuns({
763
938
  attributes: [
764
939
  {
765
940
  key: "tier",
@@ -775,7 +950,7 @@ function runStateStoreContract(name, makeStore) {
775
950
  })).map((r) => r.id)).toEqual([
776
951
  "b"
777
952
  ]);
778
- expect((await store.listRuns({
953
+ expect2((await store.listRuns({
779
954
  attributes: [
780
955
  {
781
956
  key: "tier",
@@ -807,7 +982,7 @@ function runStateStoreContract(name, makeStore) {
807
982
  other: 1
808
983
  }
809
984
  }));
810
- expect((await store.listRuns({
985
+ expect2((await store.listRuns({
811
986
  attributes: [
812
987
  {
813
988
  key: "vip",
@@ -818,7 +993,7 @@ function runStateStoreContract(name, makeStore) {
818
993
  })).map((r) => r.id)).toEqual([
819
994
  "a"
820
995
  ]);
821
- expect((await store.listRuns({
996
+ expect2((await store.listRuns({
822
997
  attributes: [
823
998
  {
824
999
  key: "vip",
@@ -845,7 +1020,7 @@ function runStateStoreContract(name, makeStore) {
845
1020
  "lt",
846
1021
  "lte"
847
1022
  ]) {
848
- expect(await store.listRuns({
1023
+ expect2(await store.listRuns({
849
1024
  attributes: [
850
1025
  {
851
1026
  key: "missing",
@@ -864,7 +1039,7 @@ function runStateStoreContract(name, makeStore) {
864
1039
  amount: 10
865
1040
  }
866
1041
  }));
867
- expect((await store.listRuns({
1042
+ expect2((await store.listRuns({
868
1043
  attributes: [
869
1044
  {
870
1045
  key: "tier",
@@ -880,7 +1055,7 @@ function runStateStoreContract(name, makeStore) {
880
1055
  tier: "pro"
881
1056
  }
882
1057
  });
883
- expect((await store.listRuns({
1058
+ expect2((await store.listRuns({
884
1059
  attributes: [
885
1060
  {
886
1061
  key: "tier",
@@ -891,7 +1066,7 @@ function runStateStoreContract(name, makeStore) {
891
1066
  })).map((r) => r.id)).toEqual([
892
1067
  "a"
893
1068
  ]);
894
- expect(await store.listRuns({
1069
+ expect2(await store.listRuns({
895
1070
  attributes: [
896
1071
  {
897
1072
  key: "tier",
@@ -900,7 +1075,7 @@ function runStateStoreContract(name, makeStore) {
900
1075
  }
901
1076
  ]
902
1077
  })).toHaveLength(0);
903
- expect(await store.listRuns({
1078
+ expect2(await store.listRuns({
904
1079
  attributes: [
905
1080
  {
906
1081
  key: "amount",
@@ -943,7 +1118,7 @@ function runStateStoreContract(name, makeStore) {
943
1118
  ],
944
1119
  limit: 10
945
1120
  });
946
- expect(res.map((r) => r.id)).toEqual([
1121
+ expect2(res.map((r) => r.id)).toEqual([
947
1122
  "a"
948
1123
  ]);
949
1124
  });
@@ -963,12 +1138,30 @@ function runStateStoreContract(name, makeStore) {
963
1138
  runId: "r3",
964
1139
  seq: 5
965
1140
  });
966
- expect((await store.listSignalWaiters("approve-")).map((w) => w.token).sort()).toEqual([
1141
+ expect2((await store.listSignalWaiters("approve-")).map((w) => w.token).sort()).toEqual([
967
1142
  "approve-1",
968
1143
  "approve-2"
969
1144
  ]);
970
- expect((await store.takeSignalWaiter("approve-1"))?.seq).toBe(3);
971
- expect(await store.takeSignalWaiter("approve-1")).toBeNull();
1145
+ expect2((await store.takeSignalWaiter("approve-1"))?.seq).toBe(3);
1146
+ expect2(await store.takeSignalWaiter("approve-1")).toBeNull();
1147
+ });
1148
+ t("round-trips a signal waiter parallelGroup (child-fan tag) through put \u2192 take \u2192 list", async () => {
1149
+ await store.putSignalWaiter({
1150
+ token: "child:r.child.0",
1151
+ runId: "r",
1152
+ seq: 0,
1153
+ parallelGroup: "gather:0"
1154
+ });
1155
+ await store.putSignalWaiter({
1156
+ token: "child:r.child.9",
1157
+ runId: "r",
1158
+ seq: 9
1159
+ });
1160
+ const listed = await store.listSignalWaiters("child:");
1161
+ expect2(listed.find((w) => w.token === "child:r.child.0")?.parallelGroup).toBe("gather:0");
1162
+ expect2(listed.find((w) => w.token === "child:r.child.9")?.parallelGroup).toBeUndefined();
1163
+ expect2((await store.takeSignalWaiter("child:r.child.0"))?.parallelGroup).toBe("gather:0");
1164
+ expect2((await store.takeSignalWaiter("child:r.child.9"))?.parallelGroup).toBeUndefined();
972
1165
  });
973
1166
  t("buffers signals and takes them FIFO per token", async () => {
974
1167
  await store.bufferSignal("sig", {
@@ -980,18 +1173,18 @@ function runStateStoreContract(name, makeStore) {
980
1173
  await store.bufferSignal("other", {
981
1174
  n: 9
982
1175
  });
983
- expect(await store.takeBufferedSignal("sig")).toEqual({
1176
+ expect2(await store.takeBufferedSignal("sig")).toEqual({
984
1177
  payload: {
985
1178
  n: 1
986
1179
  }
987
1180
  });
988
- expect(await store.takeBufferedSignal("sig")).toEqual({
1181
+ expect2(await store.takeBufferedSignal("sig")).toEqual({
989
1182
  payload: {
990
1183
  n: 2
991
1184
  }
992
1185
  });
993
- expect(await store.takeBufferedSignal("sig")).toBeNull();
994
- expect(await store.takeBufferedSignal("other")).toEqual({
1186
+ expect2(await store.takeBufferedSignal("sig")).toBeNull();
1187
+ expect2(await store.takeBufferedSignal("other")).toEqual({
995
1188
  payload: {
996
1189
  n: 9
997
1190
  }
@@ -1011,10 +1204,10 @@ function runStateStoreContract(name, makeStore) {
1011
1204
  }));
1012
1205
  return "ok";
1013
1206
  });
1014
- expect(result).toBe("ok");
1207
+ expect2(result).toBe("ok");
1015
1208
  const cp = await store.getCheckpoint("r1", 7);
1016
- expect(cp?.name).toBe("tx-step");
1017
- expect(cp?.output).toEqual({
1209
+ expect2(cp?.name).toBe("tx-step");
1210
+ expect2(cp?.output).toEqual({
1018
1211
  paid: true
1019
1212
  });
1020
1213
  });
@@ -1041,11 +1234,11 @@ function runStateStoreContract(name, makeStore) {
1041
1234
  await engine.start("wf", {
1042
1235
  x: 1
1043
1236
  }, "run1");
1044
- expect((await engine.waitForRun("run1")).status).toBe("failed");
1237
+ expect2((await engine.waitForRun("run1")).status).toBe("failed");
1045
1238
  const resumed = await engine.resume("run1");
1046
- expect(resumed.status).toBe("completed");
1047
- expect(resumed.output).toBe(15);
1048
- expect(aRuns).toBe(1);
1239
+ expect2(resumed.status).toBe("completed");
1240
+ expect2(resumed.output).toBe(15);
1241
+ expect2(aRuns).toBe(1);
1049
1242
  });
1050
1243
  });
1051
1244
  }
@@ -5590,6 +5783,7 @@ export {
5590
5783
  failTimes,
5591
5784
  preserveColumnExpectation,
5592
5785
  recordedSteps,
5786
+ runAdmissionBackendContract,
5593
5787
  runStateStoreContract
5594
5788
  };
5595
5789
  //# sourceMappingURL=index.js.map