@rotorsoft/act 1.32.11 → 1.32.12
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/.tsbuildinfo +1 -1
- package/dist/@types/act.d.ts +30 -60
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/internal/correlate-cycle.d.ts +1 -19
- package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
- package/dist/index.cjs +44 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +44 -110
- package/dist/index.js.map +1 -1
- package/package.json +2 -6
package/dist/index.js
CHANGED
|
@@ -1589,7 +1589,6 @@ var CorrelateCycle = class {
|
|
|
1589
1589
|
_armed = true;
|
|
1590
1590
|
/** In-flight init, memoized for single-flight and cleared on failure. */
|
|
1591
1591
|
_init_promise;
|
|
1592
|
-
_timer = void 0;
|
|
1593
1592
|
// Dynamically discovered targets → what each was last subscribed at,
|
|
1594
1593
|
// bounded by `maxSubscribedStreams`. The static half lives in
|
|
1595
1594
|
// `_static_subscriptions` below, which is deliberately not evictable.
|
|
@@ -1633,14 +1632,6 @@ var CorrelateCycle = class {
|
|
|
1633
1632
|
* guarantee without a second gate on the Act side.
|
|
1634
1633
|
*/
|
|
1635
1634
|
_on_init_async;
|
|
1636
|
-
/**
|
|
1637
|
-
* Scope runner (#1191). The periodic `start_polling` timer fires
|
|
1638
|
-
* outside any caller frame, so its `correlate()` must be re-wrapped in
|
|
1639
|
-
* the Act's `_scoped` bag or `store()`/`cache()` resolve to the
|
|
1640
|
-
* singleton for a scoped Act. The orchestrator always threads its
|
|
1641
|
-
* `_scoped` (identity for a non-scoped Act), so it's required.
|
|
1642
|
-
*/
|
|
1643
|
-
_run_scoped;
|
|
1644
1635
|
/**
|
|
1645
1636
|
* Tail re-scan window applied to the cold-start checkpoint (ACT-1207).
|
|
1646
1637
|
* See {@link DEFAULT_COLD_START_BACK_SCAN}. Constructor arg (not a
|
|
@@ -1661,7 +1652,6 @@ var CorrelateCycle = class {
|
|
|
1661
1652
|
cd,
|
|
1662
1653
|
max_subscribed_streams,
|
|
1663
1654
|
declared_lanes,
|
|
1664
|
-
run_scoped,
|
|
1665
1655
|
on_init,
|
|
1666
1656
|
on_init_async,
|
|
1667
1657
|
cold_start_back_scan = DEFAULT_COLD_START_BACK_SCAN,
|
|
@@ -1675,7 +1665,6 @@ var CorrelateCycle = class {
|
|
|
1675
1665
|
this._static_targets = static_targets;
|
|
1676
1666
|
this._cd = cd;
|
|
1677
1667
|
this._on_init = on_init;
|
|
1678
|
-
this._run_scoped = run_scoped;
|
|
1679
1668
|
this._on_init_async = on_init_async;
|
|
1680
1669
|
this._cold_start_back_scan = cold_start_back_scan;
|
|
1681
1670
|
}
|
|
@@ -1923,33 +1912,6 @@ var CorrelateCycle = class {
|
|
|
1923
1912
|
this._armed = found === query.limit;
|
|
1924
1913
|
return { subscribed: 0, last_id, marked: 0, scanned: true };
|
|
1925
1914
|
}
|
|
1926
|
-
/**
|
|
1927
|
-
* Start a periodic correlation worker. Returns false if one is already
|
|
1928
|
-
* running. Errors from `correlate()` are routed through `log()` so they
|
|
1929
|
-
* land in the configured logger (the timer keeps running on failure).
|
|
1930
|
-
*/
|
|
1931
|
-
start_polling(query = {}, frequency = 1e4, callback) {
|
|
1932
|
-
if (this._timer) return false;
|
|
1933
|
-
const limit = query.limit || 100;
|
|
1934
|
-
this._timer = setInterval(
|
|
1935
|
-
() => this._run_scoped(() => {
|
|
1936
|
-
this.arm();
|
|
1937
|
-
return this.correlate(
|
|
1938
|
-
{
|
|
1939
|
-
...query,
|
|
1940
|
-
after: this._checkpoint,
|
|
1941
|
-
limit
|
|
1942
|
-
},
|
|
1943
|
-
true
|
|
1944
|
-
);
|
|
1945
|
-
}).then((result) => {
|
|
1946
|
-
if (callback && result.subscribed) callback(result.subscribed);
|
|
1947
|
-
}).catch((err) => log().error(err)),
|
|
1948
|
-
frequency
|
|
1949
|
-
);
|
|
1950
|
-
return true;
|
|
1951
|
-
}
|
|
1952
|
-
/** Stop the periodic correlation worker. Idempotent. */
|
|
1953
1915
|
/**
|
|
1954
1916
|
* Hand the correlation lease back early.
|
|
1955
1917
|
*
|
|
@@ -1980,12 +1942,6 @@ var CorrelateCycle = class {
|
|
|
1980
1942
|
);
|
|
1981
1943
|
}
|
|
1982
1944
|
}
|
|
1983
|
-
stop_polling() {
|
|
1984
|
-
if (this._timer) {
|
|
1985
|
-
clearInterval(this._timer);
|
|
1986
|
-
this._timer = void 0;
|
|
1987
|
-
}
|
|
1988
|
-
}
|
|
1989
1945
|
};
|
|
1990
1946
|
|
|
1991
1947
|
// src/internal/correlator.ts
|
|
@@ -3488,6 +3444,10 @@ var Act = class {
|
|
|
3488
3444
|
_correlate;
|
|
3489
3445
|
/** Debounced correlate→drain catch-up loop. */
|
|
3490
3446
|
_settle;
|
|
3447
|
+
/** Timer behind {@link start_correlations}. */
|
|
3448
|
+
_poll;
|
|
3449
|
+
/** The deprecated `start_correlations` callback, while the poll runs. */
|
|
3450
|
+
_on_discovered;
|
|
3491
3451
|
/**
|
|
3492
3452
|
* Disposer for the cross-process notify subscription, set up eagerly
|
|
3493
3453
|
* during construction. Held as a promise because the subscription
|
|
@@ -3897,9 +3857,6 @@ var Act = class {
|
|
|
3897
3857
|
on_init: () => {
|
|
3898
3858
|
if (this._drain && this._reactive_events.size > 0) this._arm_all();
|
|
3899
3859
|
},
|
|
3900
|
-
// Re-scope the background `start_correlations` timer so its
|
|
3901
|
-
// correlate resolves the scoped ports, not the singleton (#1191).
|
|
3902
|
-
run_scoped: this._scoped,
|
|
3903
3860
|
// Cold-start defer re-seed (#1221). Skipped on writer-only instances
|
|
3904
3861
|
// (`drain: false`) — they run no local controllers to re-arm.
|
|
3905
3862
|
on_init_async: this._drain ? () => this._seed_persisted_defers() : void 0
|
|
@@ -4489,86 +4446,63 @@ var Act = class {
|
|
|
4489
4446
|
const { subscribed, last_id, marked, scanned } = await this._correlate.correlate(query, lease);
|
|
4490
4447
|
if ((subscribed > 0 || marked > 0) && this._reactive_events.size > 0)
|
|
4491
4448
|
this._arm_all();
|
|
4449
|
+
if (subscribed > 0) this._on_discovered?.(subscribed);
|
|
4492
4450
|
return { subscribed, last_id, scanned };
|
|
4493
4451
|
});
|
|
4494
4452
|
}
|
|
4495
4453
|
/**
|
|
4496
|
-
* Starts
|
|
4454
|
+
* Starts a background poll that settles on a timer: each tick looks for
|
|
4455
|
+
* new events, subscribes the streams their reactions target, and drains
|
|
4456
|
+
* them.
|
|
4457
|
+
*
|
|
4458
|
+
* Use it when this process can miss commits — another process writes to a
|
|
4459
|
+
* store without `notify`, or a notification is lost. It is the safety net
|
|
4460
|
+
* under `notify`: a missed wakeup costs at most one `frequency` of latency.
|
|
4461
|
+
*
|
|
4462
|
+
* Only one poll runs per Act instance. On a writer-only instance
|
|
4463
|
+
* (`drain: false`) each tick is a no-op, like `settle()`.
|
|
4464
|
+
*
|
|
4465
|
+
* @param query - Only `limit` is used: the most events each correlate pass
|
|
4466
|
+
* reads (default 100). The scan always starts at the correlation
|
|
4467
|
+
* checkpoint, so `after` is ignored.
|
|
4468
|
+
* @param frequency - Milliseconds between ticks (default: 10000)
|
|
4469
|
+
* @param callback - Called with the number of newly subscribed streams
|
|
4470
|
+
* after each correlate pass that found some.
|
|
4471
|
+
* @deprecated Listen to the `"settled"` lifecycle event instead.
|
|
4472
|
+
* @returns `true` if the poll started, `false` if one is already running
|
|
4497
4473
|
*
|
|
4498
|
-
*
|
|
4499
|
-
* new target streams based on reaction resolvers. It maintains a sliding window that
|
|
4500
|
-
* advances with each scan, ensuring all events are eventually correlated.
|
|
4501
|
-
*
|
|
4502
|
-
* This is useful for dynamic stream creation patterns where you don't know all streams
|
|
4503
|
-
* upfront - they're discovered as events arrive.
|
|
4504
|
-
*
|
|
4505
|
-
* **Note:** Only one correlation worker can run at a time per Act instance.
|
|
4506
|
-
*
|
|
4507
|
-
* @param query - Query filter for correlation scans — see {@link Query}
|
|
4508
|
-
* (typically `{ after: -1, limit: 100 }`)
|
|
4509
|
-
* @param frequency - Correlation frequency in milliseconds (default: 10000)
|
|
4510
|
-
* @param callback - Optional callback invoked with newly discovered streams
|
|
4511
|
-
* @returns `true` if worker started, `false` if already running
|
|
4512
|
-
*
|
|
4513
|
-
* @example Start automatic correlation
|
|
4474
|
+
* @example
|
|
4514
4475
|
* ```typescript
|
|
4515
|
-
*
|
|
4516
|
-
*
|
|
4517
|
-
* { after: 0, limit: 100 },
|
|
4518
|
-
* 5000,
|
|
4519
|
-
* (leased) => {
|
|
4520
|
-
* console.log(`Discovered ${leased.length} new streams`);
|
|
4521
|
-
* }
|
|
4522
|
-
* );
|
|
4523
|
-
*
|
|
4524
|
-
* // Later, stop it
|
|
4476
|
+
* app.start_correlations({ limit: 100 }, 5000);
|
|
4477
|
+
* // later
|
|
4525
4478
|
* app.stop_correlations();
|
|
4526
4479
|
* ```
|
|
4527
4480
|
*
|
|
4528
|
-
* @
|
|
4529
|
-
*
|
|
4530
|
-
* // Load last checkpoint
|
|
4531
|
-
* const lastId = await loadCheckpoint();
|
|
4532
|
-
*
|
|
4533
|
-
* app.start_correlations(
|
|
4534
|
-
* { after: lastId, limit: 100 },
|
|
4535
|
-
* 10000,
|
|
4536
|
-
* async (leased) => {
|
|
4537
|
-
* // Save checkpoint for next restart
|
|
4538
|
-
* if (leased.length) {
|
|
4539
|
-
* const maxId = Math.max(...leased.map(l => l.at));
|
|
4540
|
-
* await saveCheckpoint(maxId);
|
|
4541
|
-
* }
|
|
4542
|
-
* }
|
|
4543
|
-
* );
|
|
4544
|
-
* ```
|
|
4545
|
-
*
|
|
4546
|
-
* @see {@link correlate} for manual one-time correlation
|
|
4547
|
-
* @see {@link stop_correlations} to stop the worker
|
|
4481
|
+
* @see {@link settle} for what each tick runs
|
|
4482
|
+
* @see {@link stop_correlations} to stop the poll
|
|
4548
4483
|
*/
|
|
4549
4484
|
start_correlations(query = {}, frequency = 1e4, callback) {
|
|
4550
|
-
|
|
4551
|
-
|
|
4485
|
+
if (this._poll) return false;
|
|
4486
|
+
this._on_discovered = callback;
|
|
4487
|
+
const correlate = { limit: query.limit || 100 };
|
|
4488
|
+
this._poll = setInterval(() => {
|
|
4489
|
+
this._correlate.arm();
|
|
4490
|
+
this.settle({ debounceMs: 0, correlate });
|
|
4491
|
+
}, frequency);
|
|
4492
|
+
return true;
|
|
4552
4493
|
}
|
|
4553
4494
|
/**
|
|
4554
|
-
* Stops the
|
|
4555
|
-
*
|
|
4556
|
-
* Call this to stop the background correlation worker started by {@link start_correlations}.
|
|
4557
|
-
* This is automatically called when the Act instance is disposed.
|
|
4558
|
-
*
|
|
4559
|
-
* @example
|
|
4560
|
-
* ```typescript
|
|
4561
|
-
* // Start correlation
|
|
4562
|
-
* app.start_correlations();
|
|
4563
|
-
*
|
|
4564
|
-
* // Later, stop it
|
|
4565
|
-
* app.stop_correlations();
|
|
4566
|
-
* ```
|
|
4495
|
+
* Stops the poll started by {@link start_correlations}. Idempotent, and
|
|
4496
|
+
* called by `shutdown()`.
|
|
4567
4497
|
*
|
|
4568
4498
|
* @see {@link start_correlations}
|
|
4569
4499
|
*/
|
|
4570
4500
|
stop_correlations() {
|
|
4571
|
-
this.
|
|
4501
|
+
if (this._poll) {
|
|
4502
|
+
clearInterval(this._poll);
|
|
4503
|
+
this._poll = void 0;
|
|
4504
|
+
}
|
|
4505
|
+
this._on_discovered = void 0;
|
|
4572
4506
|
void this._scoped(() => this._correlate.release_correlation());
|
|
4573
4507
|
}
|
|
4574
4508
|
/**
|