@dudousxd/nestjs-durable-testing 0.18.0 → 0.19.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
@@ -1324,6 +1324,9 @@ function runStateStoreContract(name, makeStore) {
1324
1324
  engine.register("p-other", "1", async () => "done");
1325
1325
  await engine.start("p-root", {}, "pr");
1326
1326
  await engine.start("p-other", {}, "po");
1327
+ expect3((await engine.waitForRun("pr", {
1328
+ timeoutMs: 2e4
1329
+ })).status).toBe("suspended");
1327
1330
  expect3((await engine.waitForRun("pc", {
1328
1331
  timeoutMs: 2e4
1329
1332
  })).status).toBe("suspended");
@@ -1495,6 +1498,171 @@ function runStateStoreContract(name, makeStore) {
1495
1498
  expect3(await store.countCheckpoints("r1", 0, 4, [])).toBe(0);
1496
1499
  });
1497
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 with an empty patch is a pure compare: never throws, writes nothing", async () => {
1618
+ expect3(store.updateRunIf).toBeDefined();
1619
+ if (!store.updateRunIf) return;
1620
+ await store.createRun(run({
1621
+ output: {
1622
+ kept: true
1623
+ }
1624
+ }));
1625
+ expect3(await store.updateRunIf("r1", [
1626
+ "running"
1627
+ ], {})).toBe(true);
1628
+ expect3(await store.updateRunIf("r1", [
1629
+ "suspended"
1630
+ ], {})).toBe(false);
1631
+ expect3(await store.updateRunIf("missing", [
1632
+ "running"
1633
+ ], {})).toBe(false);
1634
+ const current = await store.getRun("r1");
1635
+ expect3(current?.status).toBe("running");
1636
+ expect3(current?.output).toEqual({
1637
+ kept: true
1638
+ });
1639
+ });
1640
+ t("updateRunIf settling a run terminal drops its singleton admission like updateRun", async () => {
1641
+ expect3(store.updateRunIf).toBeDefined();
1642
+ if (!store.updateRunIf) return;
1643
+ await store.createRun(run({
1644
+ tags: [
1645
+ "singleton:k",
1646
+ SINGLETON_ADMITTED_TAG
1647
+ ]
1648
+ }));
1649
+ expect3(await store.updateRunIf("r1", [
1650
+ "running"
1651
+ ], {
1652
+ status: "completed",
1653
+ output: {
1654
+ ok: true
1655
+ }
1656
+ })).toBe(true);
1657
+ const settled = await store.getRun("r1");
1658
+ expect3(settled?.status).toBe("completed");
1659
+ expect3(settled?.output).toEqual({
1660
+ ok: true
1661
+ });
1662
+ expect3(settled?.tags).toEqual([
1663
+ "singleton:k"
1664
+ ]);
1665
+ });
1498
1666
  t("saveCheckpointIfPending writes over a pending row only", async () => {
1499
1667
  expect3(store.saveCheckpointIfPending).toBeDefined();
1500
1668
  if (!store.saveCheckpointIfPending) return;