@rotorsoft/act 0.30.0 → 0.31.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/README.md +1 -3
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/act.d.ts +43 -5
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/adapters/InMemoryStore.d.ts +7 -1
- package/dist/@types/adapters/InMemoryStore.d.ts.map +1 -1
- package/dist/@types/types/ports.d.ts +129 -4
- package/dist/@types/types/ports.d.ts.map +1 -1
- package/dist/@types/types/reaction.d.ts +4 -1
- package/dist/@types/types/reaction.d.ts.map +1 -1
- package/dist/index.cjs +110 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +110 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -323,6 +323,21 @@ var InMemoryStream = class {
|
|
|
323
323
|
get at() {
|
|
324
324
|
return this._at;
|
|
325
325
|
}
|
|
326
|
+
get retry() {
|
|
327
|
+
return this._retry;
|
|
328
|
+
}
|
|
329
|
+
get blocked() {
|
|
330
|
+
return this._blocked;
|
|
331
|
+
}
|
|
332
|
+
get error() {
|
|
333
|
+
return this._error;
|
|
334
|
+
}
|
|
335
|
+
get leased_by() {
|
|
336
|
+
return this._leased_by;
|
|
337
|
+
}
|
|
338
|
+
get leased_until() {
|
|
339
|
+
return this._leased_until;
|
|
340
|
+
}
|
|
326
341
|
/**
|
|
327
342
|
* Attempt to lease this stream for processing.
|
|
328
343
|
* @param lease - The lease request.
|
|
@@ -603,6 +618,49 @@ var InMemoryStore = class {
|
|
|
603
618
|
}
|
|
604
619
|
return count;
|
|
605
620
|
}
|
|
621
|
+
/**
|
|
622
|
+
* Streams registered subscription positions to the callback, ordered by
|
|
623
|
+
* stream name. Returns the highest event id in the store and the count
|
|
624
|
+
* of positions emitted.
|
|
625
|
+
*/
|
|
626
|
+
async query_streams(callback, query) {
|
|
627
|
+
await sleep();
|
|
628
|
+
const limit = query?.limit ?? 100;
|
|
629
|
+
const after = query?.after;
|
|
630
|
+
const blocked = query?.blocked;
|
|
631
|
+
const streamRe = query?.stream && !query.stream_exact ? new RegExp(`^${query.stream}$`) : void 0;
|
|
632
|
+
const sourceRe = query?.source && !query.source_exact ? new RegExp(`^${query.source}$`) : void 0;
|
|
633
|
+
const sorted = [...this._streams.values()].sort(
|
|
634
|
+
(a, b) => a.stream.localeCompare(b.stream)
|
|
635
|
+
);
|
|
636
|
+
let count = 0;
|
|
637
|
+
for (const s of sorted) {
|
|
638
|
+
if (after !== void 0 && s.stream <= after) continue;
|
|
639
|
+
if (query?.stream !== void 0) {
|
|
640
|
+
if (query.stream_exact ? s.stream !== query.stream : !streamRe.test(s.stream))
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (query?.source !== void 0) {
|
|
644
|
+
if (s.source === void 0) continue;
|
|
645
|
+
if (query.source_exact ? s.source !== query.source : !sourceRe.test(s.source))
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
if (blocked !== void 0 && s.blocked !== blocked) continue;
|
|
649
|
+
callback({
|
|
650
|
+
stream: s.stream,
|
|
651
|
+
source: s.source,
|
|
652
|
+
at: s.at,
|
|
653
|
+
retry: s.retry,
|
|
654
|
+
blocked: s.blocked,
|
|
655
|
+
error: s.error,
|
|
656
|
+
leased_by: s.leased_by,
|
|
657
|
+
leased_until: s.leased_until
|
|
658
|
+
});
|
|
659
|
+
count++;
|
|
660
|
+
if (count >= limit) break;
|
|
661
|
+
}
|
|
662
|
+
return { maxEventId: this._events.length - 1, count };
|
|
663
|
+
}
|
|
606
664
|
/**
|
|
607
665
|
* Atomically truncates streams and seeds each with a snapshot or tombstone.
|
|
608
666
|
* @param targets - Streams to truncate with optional snapshot state and meta.
|
|
@@ -1622,6 +1680,46 @@ var Act = class {
|
|
|
1622
1680
|
this._settle_timer = void 0;
|
|
1623
1681
|
}
|
|
1624
1682
|
}
|
|
1683
|
+
/**
|
|
1684
|
+
* Reset reaction stream watermarks and request a drain on the next
|
|
1685
|
+
* `drain()` / `settle()` cycle.
|
|
1686
|
+
*
|
|
1687
|
+
* Use this to replay events through projections (or other reaction targets)
|
|
1688
|
+
* after changing handler logic. Equivalent to calling `store().reset(streams)`
|
|
1689
|
+
* directly, but also raises the orchestrator's internal "needs drain" flag —
|
|
1690
|
+
* `store().reset(...)` alone leaves the flag untouched, so a settled app
|
|
1691
|
+
* would short-circuit and skip the replay.
|
|
1692
|
+
*
|
|
1693
|
+
* Pair with `app.settle()` (or a single `app.drain()` for small streams).
|
|
1694
|
+
* `settle()` loops correlate→drain until no progress is made, so one call
|
|
1695
|
+
* fully catches up paginated streams without forcing callers to roll
|
|
1696
|
+
* their own loop.
|
|
1697
|
+
*
|
|
1698
|
+
* @param streams - Reaction target streams (e.g., projection names) to reset
|
|
1699
|
+
* @returns Count of streams that were actually reset
|
|
1700
|
+
*
|
|
1701
|
+
* @example Rebuild a projection (production)
|
|
1702
|
+
* ```typescript
|
|
1703
|
+
* await app.reset(["my-projection"]);
|
|
1704
|
+
* app.settle({ eventLimit: 1000 }); // emits "settled" when fully replayed
|
|
1705
|
+
* ```
|
|
1706
|
+
*
|
|
1707
|
+
* @example Rebuild a projection (tests / scripts)
|
|
1708
|
+
* ```typescript
|
|
1709
|
+
* await app.reset(["my-projection"]);
|
|
1710
|
+
* await app.drain({ eventLimit: 1000 }); // small streams: one pass is enough
|
|
1711
|
+
* ```
|
|
1712
|
+
*
|
|
1713
|
+
* @see {@link Store.reset} for the underlying store primitive
|
|
1714
|
+
* @see {@link settle} for the debounced full-catch-up loop
|
|
1715
|
+
*/
|
|
1716
|
+
async reset(streams) {
|
|
1717
|
+
const count = await store().reset(streams);
|
|
1718
|
+
if (count > 0 && this._reactive_events.size > 0) {
|
|
1719
|
+
this._needs_drain = true;
|
|
1720
|
+
}
|
|
1721
|
+
return count;
|
|
1722
|
+
}
|
|
1625
1723
|
/**
|
|
1626
1724
|
* Close the books — guard, archive, truncate, and optionally restart streams.
|
|
1627
1725
|
*
|
|
@@ -1789,15 +1887,19 @@ var Act = class {
|
|
|
1789
1887
|
/**
|
|
1790
1888
|
* Debounced, non-blocking correlate→drain cycle.
|
|
1791
1889
|
*
|
|
1792
|
-
* Call this after `app.do()` to schedule a background
|
|
1793
|
-
* calls within the debounce window are coalesced
|
|
1794
|
-
* correlate→drain in a loop until
|
|
1795
|
-
*
|
|
1890
|
+
* Call this after `app.do()` (or `app.reset()`) to schedule a background
|
|
1891
|
+
* drain. Multiple rapid calls within the debounce window are coalesced
|
|
1892
|
+
* into a single cycle. Runs correlate→drain in a loop until a pass makes
|
|
1893
|
+
* no progress — no new subscriptions, no acks, no blocks — then emits
|
|
1894
|
+
* the `"settled"` lifecycle event. This means a single `settle()` call
|
|
1895
|
+
* fully catches up paginated streams (e.g. after `reset()` on a long
|
|
1896
|
+
* projection) without forcing callers to loop.
|
|
1796
1897
|
*
|
|
1797
1898
|
* @param options - Settle configuration options
|
|
1798
1899
|
* @param options.debounceMs - Debounce window in milliseconds (default: 10)
|
|
1799
1900
|
* @param options.correlate - Query filter for correlation scans (default: `{ after: -1, limit: 100 }`)
|
|
1800
|
-
* @param options.maxPasses -
|
|
1901
|
+
* @param options.maxPasses - Cap on correlate→drain loops (default: `Infinity`).
|
|
1902
|
+
* Early-exit on no-progress means the cap only matters in pathological cases.
|
|
1801
1903
|
* @param options.streamLimit - Maximum streams per drain cycle (default: 10)
|
|
1802
1904
|
* @param options.eventLimit - Maximum events per stream (default: 10)
|
|
1803
1905
|
* @param options.leaseMillis - Lease duration in milliseconds (default: 10000)
|
|
@@ -1819,7 +1921,7 @@ var Act = class {
|
|
|
1819
1921
|
const {
|
|
1820
1922
|
debounceMs = 10,
|
|
1821
1923
|
correlate: correlateQuery = { after: -1, limit: 100 },
|
|
1822
|
-
maxPasses =
|
|
1924
|
+
maxPasses = Infinity,
|
|
1823
1925
|
...drainOptions
|
|
1824
1926
|
} = options;
|
|
1825
1927
|
if (this._settle_timer) clearTimeout(this._settle_timer);
|
|
@@ -1835,9 +1937,9 @@ var Act = class {
|
|
|
1835
1937
|
...correlateQuery,
|
|
1836
1938
|
after: this._correlation_checkpoint
|
|
1837
1939
|
});
|
|
1838
|
-
if (subscribed === 0 && i > 0) break;
|
|
1839
1940
|
lastDrain = await this.drain(drainOptions);
|
|
1840
|
-
|
|
1941
|
+
const made_progress = subscribed > 0 || lastDrain.acked.length > 0 || lastDrain.blocked.length > 0;
|
|
1942
|
+
if (!made_progress) break;
|
|
1841
1943
|
}
|
|
1842
1944
|
if (lastDrain) this.emit("settled", lastDrain);
|
|
1843
1945
|
})().catch((err) => logger3.error(err)).finally(() => {
|