@rotorsoft/act 1.31.11 → 1.31.13
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 +5 -2
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/internal/correlate-cycle.d.ts +20 -3
- package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
- package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
- package/dist/@types/internal/report-once.d.ts +12 -1
- package/dist/@types/internal/report-once.d.ts.map +1 -1
- package/dist/index.cjs +44 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +44 -19
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1420,18 +1420,18 @@ var registry_key = (events) => {
|
|
|
1420
1420
|
return createHash("sha256").update(JSON.stringify(shape)).digest("hex").slice(0, 32);
|
|
1421
1421
|
};
|
|
1422
1422
|
var PATTERN_CACHE_SIZE = 32;
|
|
1423
|
-
function report_undeclared_lane(seen, target, lane, declared) {
|
|
1423
|
+
function report_undeclared_lane(seen, handler, target, lane, declared) {
|
|
1424
1424
|
report_once(
|
|
1425
1425
|
seen,
|
|
1426
|
-
`lane|${
|
|
1427
|
-
`Reaction
|
|
1426
|
+
`lane|${handler}|${lane}`,
|
|
1427
|
+
`Reaction "${handler}" resolved onto undeclared lane "${lane}" \u2014 for example target "${target}". Declared lanes: ${[...declared].map((l) => `"${l}"`).join(", ")}. No controller claims it, so the stream would never drain \u2014 running it on "default" instead. The equivalent static \`.to({ lane })\` is rejected at build; a dynamic resolver's lane is only knowable here.`
|
|
1428
1428
|
);
|
|
1429
1429
|
}
|
|
1430
|
-
function report_lane_conflict(seen, target, kept, dropped) {
|
|
1430
|
+
function report_lane_conflict(seen, handler, target, kept, dropped) {
|
|
1431
1431
|
report_once(
|
|
1432
1432
|
seen,
|
|
1433
|
-
`conflict|${
|
|
1434
|
-
`
|
|
1433
|
+
`conflict|${handler}|${kept}|${dropped}`,
|
|
1434
|
+
`Reaction "${handler}" resolved lane "${dropped}" for a stream already on "${kept}" \u2014 for example "${target}". These are conflicting lane assignments from two dynamic resolutions at equal priority. Keeping "${kept}", the lane it was first discovered on \u2014 re-laning a live stream would move it out from under a worker holding its lease. The reaction resolving "${dropped}" runs inside the "${kept}" lane's budget, and a process restricted to "${dropped}" via onlyLanes never runs it. The equivalent static declaration is rejected at build; align the resolvers, or split the target.`
|
|
1435
1435
|
);
|
|
1436
1436
|
}
|
|
1437
1437
|
var CorrelateCycle = class {
|
|
@@ -1480,13 +1480,33 @@ var CorrelateCycle = class {
|
|
|
1480
1480
|
/** In-flight init, memoized for single-flight and cleared on failure. */
|
|
1481
1481
|
_init_promise;
|
|
1482
1482
|
_timer = void 0;
|
|
1483
|
-
//
|
|
1483
|
+
// Dynamically discovered targets → what each was last subscribed at,
|
|
1484
|
+
// bounded by `maxSubscribedStreams`. The static half lives in
|
|
1485
|
+
// `_static_subscriptions` below, which is deliberately not evictable.
|
|
1486
|
+
//
|
|
1487
|
+
// Every scan re-subscribes the
|
|
1484
1488
|
// targets it resolved (that is how the work mark lands), so this no longer
|
|
1485
1489
|
// decides *whether* a target is sent — it decides *what* is sent with it:
|
|
1486
1490
|
// a resolution raises priority/lane only when it beats the recorded floor,
|
|
1487
1491
|
// and otherwise re-sends the row's own values so the mark changes nothing
|
|
1488
1492
|
// else. See {@link Subscription}.
|
|
1489
|
-
|
|
1493
|
+
_dynamic_subscriptions;
|
|
1494
|
+
/**
|
|
1495
|
+
* What each static target was subscribed at by `init`. A plain map, never
|
|
1496
|
+
* evicted: the collection is the build-time `_static_targets` list, so it
|
|
1497
|
+
* is already bounded by the registry and costs nothing the registry does
|
|
1498
|
+
* not already hold.
|
|
1499
|
+
*
|
|
1500
|
+
* Keeping these out of the LRU is what makes the `+Infinity` floor an
|
|
1501
|
+
* invariant rather than a race (#1582). Sharing the bounded map meant a
|
|
1502
|
+
* churn of dynamic targets could evict a static record, and the next
|
|
1503
|
+
* dynamic resolution to that target found no record, took the
|
|
1504
|
+
* first-discovery branch, and re-subscribed the target with its own
|
|
1505
|
+
* priority and lane — silently re-laning a stream whose lane the
|
|
1506
|
+
* build-time subscribe owns, and starving it wherever `onlyLanes` had
|
|
1507
|
+
* provisioned a worker for the declared lane.
|
|
1508
|
+
*/
|
|
1509
|
+
_static_subscriptions = /* @__PURE__ */ new Map();
|
|
1490
1510
|
/** Compiled pattern sources, bounded by {@link PATTERN_CACHE_SIZE}. */
|
|
1491
1511
|
_patterns = new LruMap(PATTERN_CACHE_SIZE);
|
|
1492
1512
|
_registry;
|
|
@@ -1539,7 +1559,7 @@ var CorrelateCycle = class {
|
|
|
1539
1559
|
}) {
|
|
1540
1560
|
this._lease_millis = lease_millis;
|
|
1541
1561
|
this._key = registry_key(registry.events);
|
|
1542
|
-
this.
|
|
1562
|
+
this._dynamic_subscriptions = new LruMap(max_subscribed_streams);
|
|
1543
1563
|
this._registry = registry;
|
|
1544
1564
|
this._declared_lanes = declared_lanes;
|
|
1545
1565
|
this._static_targets = static_targets;
|
|
@@ -1589,7 +1609,7 @@ var CorrelateCycle = class {
|
|
|
1589
1609
|
this._checkpoint = correlated_at >= 0 ? correlated_at : Math.max(-1, watermark - this._cold_start_back_scan);
|
|
1590
1610
|
this._on_init?.();
|
|
1591
1611
|
for (const { stream, priority = 0, lane } of this._static_targets) {
|
|
1592
|
-
this.
|
|
1612
|
+
this._static_subscriptions.set(stream, {
|
|
1593
1613
|
floor: Number.POSITIVE_INFINITY,
|
|
1594
1614
|
priority,
|
|
1595
1615
|
lane
|
|
@@ -1608,14 +1628,12 @@ var CorrelateCycle = class {
|
|
|
1608
1628
|
* the documented per-aggregate shape `.to(e => ({target: e.stream}))`
|
|
1609
1629
|
* makes those two namespaces collide by construction (#1398).
|
|
1610
1630
|
*
|
|
1611
|
-
* Static targets are left alone:
|
|
1612
|
-
*
|
|
1631
|
+
* Static targets are left alone: their record lives in
|
|
1632
|
+
* `_static_subscriptions`, which this never touches, so they stay pinned
|
|
1633
|
+
* at +Infinity and the dynamic path never re-opens them.
|
|
1613
1634
|
*/
|
|
1614
1635
|
forget_subscribed(streams) {
|
|
1615
|
-
const
|
|
1616
|
-
for (const stream of streams) {
|
|
1617
|
-
if (!statics.has(stream)) this._subscribed.delete(stream);
|
|
1618
|
-
}
|
|
1636
|
+
for (const stream of streams) this._dynamic_subscriptions.delete(stream);
|
|
1619
1637
|
}
|
|
1620
1638
|
/**
|
|
1621
1639
|
* Would an event from `stream` be fetched for a target subscribed with
|
|
@@ -1684,13 +1702,14 @@ var CorrelateCycle = class {
|
|
|
1684
1702
|
if (lane !== void 0 && !this._declared_lanes.has(lane)) {
|
|
1685
1703
|
report_undeclared_lane(
|
|
1686
1704
|
this._reported,
|
|
1705
|
+
reaction.handler.name,
|
|
1687
1706
|
resolved.target,
|
|
1688
1707
|
lane,
|
|
1689
1708
|
this._declared_lanes
|
|
1690
1709
|
);
|
|
1691
1710
|
lane = void 0;
|
|
1692
1711
|
}
|
|
1693
|
-
const recorded = this.
|
|
1712
|
+
const recorded = this._static_subscriptions.get(resolved.target) ?? this._dynamic_subscriptions.get(resolved.target);
|
|
1694
1713
|
const priority = resolved.priority ?? 0;
|
|
1695
1714
|
const upgraded = !recorded || priority > recorded.floor;
|
|
1696
1715
|
const carried = upgraded ? { priority, lane } : { priority: recorded.priority, lane: recorded.lane };
|
|
@@ -1703,7 +1722,13 @@ var CorrelateCycle = class {
|
|
|
1703
1722
|
};
|
|
1704
1723
|
const held = correlated.has(resolved.target) ? entry.lane : recorded?.lane;
|
|
1705
1724
|
if (held !== void 0 && lane !== void 0 && held !== lane && priority === entry.priority)
|
|
1706
|
-
report_lane_conflict(
|
|
1725
|
+
report_lane_conflict(
|
|
1726
|
+
this._reported,
|
|
1727
|
+
reaction.handler.name,
|
|
1728
|
+
resolved.target,
|
|
1729
|
+
held,
|
|
1730
|
+
lane
|
|
1731
|
+
);
|
|
1707
1732
|
if (carried.priority > entry.priority) {
|
|
1708
1733
|
entry.priority = carried.priority;
|
|
1709
1734
|
entry.lane = carried.lane;
|
|
@@ -1743,7 +1768,7 @@ var CorrelateCycle = class {
|
|
|
1743
1768
|
this._checkpoint = last_id;
|
|
1744
1769
|
for (const { stream, priority, lane } of streams) {
|
|
1745
1770
|
if (correlated.get(stream)?.upgraded)
|
|
1746
|
-
this.
|
|
1771
|
+
this._dynamic_subscriptions.set(stream, {
|
|
1747
1772
|
floor: priority,
|
|
1748
1773
|
priority,
|
|
1749
1774
|
lane
|