@rotorsoft/act-tck 1.30.5 → 1.32.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.
@@ -82,6 +82,22 @@ export type StoreCapabilities = {
82
82
  * to InMemory/PG for full regex claim sources.
83
83
  */
84
84
  readonly rejects_nonportable_claim_source?: boolean;
85
+ /**
86
+ * Adapter honors the {@link SubscribeInput.correlated_at} **work mark**
87
+ * (#1485): `subscribe` applies it as `GREATEST(correlated_at, N)` and
88
+ * `claim` serves a marked stream from the subscription row alone
89
+ * (`at < correlated_at`) instead of probing the event log. When `true`,
90
+ * the TCK runs the work-set suite — mark-then-claim, monotonicity
91
+ * across positive/zero/negative values, `ack` retiring a stream from
92
+ * the claimable set and a later mark re-adding it, and the operator
93
+ * surfaces (`reset`, `unblock`, `defer`, `prioritize`) leaving the mark
94
+ * intact.
95
+ *
96
+ * An adapter that ignores the field keeps working through the legacy
97
+ * has-work probe and leaves this `false`. The flag disappears once the
98
+ * legacy arm is deleted and the mark becomes the only eligibility rule.
99
+ */
100
+ readonly work_set?: boolean;
85
101
  };
86
102
  /**
87
103
  * Options for {@link runStoreTck}.
@@ -1 +1 @@
1
- {"version":3,"file":"store-tck.d.ts","sourceRoot":"","sources":["../../src/store-tck.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAQV,KAAK,EAGN,MAAM,sBAAsB,CAAC;AAc9B;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;;;;;;;OASG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC;;;;;;;;OAQG;IACH,QAAQ,CAAC,gCAAgC,CAAC,EAAE,OAAO,CAAC;CACrD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/C;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACxD;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAC3C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,eAAO,MAAM,WAAW,YAAa,eAAe,KAAG,IA48ItD,CAAC"}
1
+ {"version":3,"file":"store-tck.d.ts","sourceRoot":"","sources":["../../src/store-tck.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAQV,KAAK,EAGN,MAAM,sBAAsB,CAAC;AAc9B;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC;;;;;;;;;OASG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC;;;;;;;;OAQG;IACH,QAAQ,CAAC,gCAAgC,CAAC,EAAE,OAAO,CAAC;IACpD;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/C;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACxD;;OAEG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAC3C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,eAAO,MAAM,WAAW,YAAa,eAAe,KAAG,IAypJtD,CAAC"}
package/dist/index.cjs CHANGED
@@ -1806,6 +1806,146 @@ var runStoreTck = (options) => {
1806
1806
  await store.subscribe([{ stream: s }]);
1807
1807
  (0, import_vitest9.expect)(await read()).toBe(0);
1808
1808
  });
1809
+ (0, import_vitest9.describe)("correlate checkpoint", () => {
1810
+ const peek = async () => (await store.subscribe([])).correlated_at;
1811
+ (0, import_vitest9.it)("round-trips an advance through subscribe", async () => {
1812
+ const base = await peek();
1813
+ (0, import_vitest9.expect)((await store.subscribe([], base + 10)).correlated_at).toBe(
1814
+ base + 10
1815
+ );
1816
+ (0, import_vitest9.expect)(await peek()).toBe(base + 10);
1817
+ });
1818
+ (0, import_vitest9.it)("persists only when greater than the stored value", async () => {
1819
+ const base = await peek();
1820
+ await store.subscribe([], base - 5);
1821
+ (0, import_vitest9.expect)(await peek()).toBe(base);
1822
+ await store.subscribe([], base);
1823
+ (0, import_vitest9.expect)(await peek()).toBe(base);
1824
+ await store.subscribe([], base + 3);
1825
+ (0, import_vitest9.expect)(await peek()).toBe(base + 3);
1826
+ });
1827
+ (0, import_vitest9.it)("is left untouched when subscribe omits it", async () => {
1828
+ const base = await peek();
1829
+ await store.subscribe([]);
1830
+ (0, import_vitest9.expect)(await peek()).toBe(base);
1831
+ });
1832
+ (0, import_vitest9.it)("advances in the same call that registers discovered targets", async () => {
1833
+ const base = await peek();
1834
+ const s = `cp-sub-${uid()}`;
1835
+ const { subscribed, correlated_at } = await store.subscribe(
1836
+ [{ stream: s }],
1837
+ base + 7
1838
+ );
1839
+ (0, import_vitest9.expect)(subscribed).toBe(1);
1840
+ (0, import_vitest9.expect)(correlated_at).toBe(base + 7);
1841
+ });
1842
+ (0, import_vitest9.it)("is invisible to every stream-scoped surface", async () => {
1843
+ const seen = [];
1844
+ await store.query_streams((p) => seen.push(p.stream), {});
1845
+ (0, import_vitest9.expect)(seen.some((n) => n.startsWith("__correlate"))).toBe(false);
1846
+ (0, import_vitest9.expect)(seen).not.toContain("correlated");
1847
+ });
1848
+ });
1849
+ import_vitest9.describe.skipIf(!caps.work_set)("subscription work set", () => {
1850
+ const claimable = async (stream) => {
1851
+ const leased = await store.claim(100, 0, `w-${uid()}`, 1);
1852
+ const mine = leased.find((l) => l.stream === stream);
1853
+ if (mine) await store.ack([{ ...mine, at: mine.at }]);
1854
+ return mine !== void 0;
1855
+ };
1856
+ (0, import_vitest9.it)("claims a marked stream without probing the event log", async () => {
1857
+ const s = `ws-mark-${uid()}`;
1858
+ await store.subscribe([{ stream: s, source: `ws-src-${uid()}` }]);
1859
+ (0, import_vitest9.expect)(await claimable(s)).toBe(false);
1860
+ await store.subscribe([{ stream: s, correlated_at: 7 }]);
1861
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1862
+ const s2 = `ws-mark-nosrc-${uid()}`;
1863
+ await store.subscribe([{ stream: s2, correlated_at: 7 }]);
1864
+ (0, import_vitest9.expect)(await claimable(s2)).toBe(true);
1865
+ });
1866
+ (0, import_vitest9.it)("never regresses the mark, for every value on the number line", async () => {
1867
+ const s = `ws-mono-${uid()}`;
1868
+ await store.subscribe([
1869
+ { stream: s, source: `ws-none-${uid()}`, correlated_at: 10 }
1870
+ ]);
1871
+ const leased = await store.claim(100, 0, `w-${uid()}`, 1e4);
1872
+ await store.ack([
1873
+ { ...leased.find((l) => l.stream === s), at: 5 }
1874
+ ]);
1875
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1876
+ await store.subscribe([{ stream: s, correlated_at: 4 }]);
1877
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1878
+ await store.subscribe([{ stream: s, correlated_at: 5 }]);
1879
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1880
+ await store.subscribe([{ stream: s, correlated_at: -3 }]);
1881
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1882
+ await store.subscribe([{ stream: s, correlated_at: 0 }]);
1883
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1884
+ const leased2 = await store.claim(100, 0, `w-${uid()}`, 1e4);
1885
+ await store.ack([
1886
+ { ...leased2.find((l) => l.stream === s), at: 10 }
1887
+ ]);
1888
+ (0, import_vitest9.expect)(await claimable(s)).toBe(false);
1889
+ await store.subscribe([{ stream: s, correlated_at: 11 }]);
1890
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1891
+ });
1892
+ (0, import_vitest9.it)("retires a stream when ack catches the watermark up to the mark", async () => {
1893
+ const s = `ws-retire-${uid()}`;
1894
+ await store.subscribe([
1895
+ { stream: s, source: `ws-none-${uid()}`, correlated_at: 5 }
1896
+ ]);
1897
+ const leased = await store.claim(100, 0, `w-${uid()}`, 1e4);
1898
+ const mine = leased.find((l) => l.stream === s);
1899
+ (0, import_vitest9.expect)(mine).toBeDefined();
1900
+ await store.ack([{ ...mine, at: 5 }]);
1901
+ (0, import_vitest9.expect)(await claimable(s)).toBe(false);
1902
+ await store.subscribe([{ stream: s, correlated_at: 6 }]);
1903
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1904
+ });
1905
+ (0, import_vitest9.it)("keeps the mark across reset, so a rebuild is claimable", async () => {
1906
+ const s = `ws-reset-${uid()}`;
1907
+ await store.subscribe([
1908
+ { stream: s, source: `ws-none-${uid()}`, correlated_at: 3 }
1909
+ ]);
1910
+ const leased = await store.claim(100, 0, `w-${uid()}`, 1e4);
1911
+ await store.ack([
1912
+ { ...leased.find((l) => l.stream === s), at: 3 }
1913
+ ]);
1914
+ (0, import_vitest9.expect)(await claimable(s)).toBe(false);
1915
+ await store.reset([s]);
1916
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1917
+ });
1918
+ (0, import_vitest9.it)("keeps the mark across unblock, defer, and prioritize", async () => {
1919
+ const s = `ws-ops-${uid()}`;
1920
+ await store.subscribe([
1921
+ { stream: s, source: `ws-none-${uid()}`, correlated_at: 9 }
1922
+ ]);
1923
+ const leased = await store.claim(100, 0, `w-${uid()}`, 1e4);
1924
+ const mine = leased.find((l) => l.stream === s);
1925
+ await store.block([{ ...mine, error: "poison" }]);
1926
+ (0, import_vitest9.expect)(await claimable(s)).toBe(false);
1927
+ (0, import_vitest9.expect)(await store.unblock([s])).toBe(1);
1928
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1929
+ await store.defer([s], Date.now() + 6e4);
1930
+ (0, import_vitest9.expect)(await claimable(s)).toBe(false);
1931
+ await store.defer([s], Date.now() - 1);
1932
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1933
+ await store.prioritize({ stream: s, stream_exact: true }, 5);
1934
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1935
+ });
1936
+ (0, import_vitest9.it)("falls back to the legacy probe for an unmarked stream", async () => {
1937
+ const s = `ws-legacy-${uid()}`;
1938
+ const src = `ws-legacy-src-${uid()}`;
1939
+ await store.subscribe([{ stream: s, source: src }]);
1940
+ (0, import_vitest9.expect)(await claimable(s)).toBe(false);
1941
+ await store.commit(
1942
+ src,
1943
+ [inc(1)],
1944
+ make_meta({ stream: src })
1945
+ );
1946
+ (0, import_vitest9.expect)(await claimable(s)).toBe(true);
1947
+ });
1948
+ });
1809
1949
  (0, import_vitest9.it)("claims a subscribed stream and ack releases the lease", async () => {
1810
1950
  const s = `claim-${uid()}`;
1811
1951
  await store.subscribe([{ stream: s }]);