@rotorsoft/act 1.32.20 → 1.32.21
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/internal/correlate-cycle.d.ts +11 -0
- package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
- package/dist/@types/internal/defer-timer.d.ts +15 -5
- package/dist/@types/internal/defer-timer.d.ts.map +1 -1
- package/dist/@types/internal/drain-cycle.d.ts +3 -0
- package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
- package/dist/index.cjs +67 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +67 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1839,6 +1839,8 @@ var CorrelateCycle = class {
|
|
|
1839
1839
|
priority: carried.priority,
|
|
1840
1840
|
lane: carried.lane,
|
|
1841
1841
|
upgraded,
|
|
1842
|
+
missed: !recorded,
|
|
1843
|
+
handler: reaction.handler.name,
|
|
1842
1844
|
correlated_at: void 0
|
|
1843
1845
|
};
|
|
1844
1846
|
const seen_in_scan = correlated.has(resolved.target);
|
|
@@ -1857,6 +1859,7 @@ var CorrelateCycle = class {
|
|
|
1857
1859
|
entry.priority = carried.priority;
|
|
1858
1860
|
entry.lane = carried.lane;
|
|
1859
1861
|
entry.upgraded = upgraded;
|
|
1862
|
+
entry.handler = reaction.handler.name;
|
|
1860
1863
|
}
|
|
1861
1864
|
if (this._in_fetch_window(resolved.source, event.stream))
|
|
1862
1865
|
entry.correlated_at = event.id;
|
|
@@ -1870,6 +1873,7 @@ var CorrelateCycle = class {
|
|
|
1870
1873
|
// actor-less, so plaintext here would be un-gated disclosure.
|
|
1871
1874
|
{ ...query, after, with_pii: false }
|
|
1872
1875
|
);
|
|
1876
|
+
if (this._declared_lanes.size > 1) await this._recall(correlated);
|
|
1873
1877
|
const streams = [];
|
|
1874
1878
|
for (const [stream, entry] of correlated) {
|
|
1875
1879
|
if (entry.upgraded || entry.correlated_at !== void 0)
|
|
@@ -1908,6 +1912,50 @@ var CorrelateCycle = class {
|
|
|
1908
1912
|
this._armed = found === query.limit;
|
|
1909
1913
|
return { subscribed: 0, last_id, marked: 0, scanned: true };
|
|
1910
1914
|
}
|
|
1915
|
+
/**
|
|
1916
|
+
* Give each target this scan had no record of the record its row holds.
|
|
1917
|
+
*
|
|
1918
|
+
* A target with no record is either new or forgotten. Its row, when it
|
|
1919
|
+
* has one, says what lane and priority it was subscribed at; a resolution
|
|
1920
|
+
* that doesn't beat that priority carries the row's values, exactly as if
|
|
1921
|
+
* the record had never been evicted. One read per target with no record,
|
|
1922
|
+
* and only when more than one lane is declared: with one lane there is no
|
|
1923
|
+
* lane to lose, and the store already keeps the higher priority.
|
|
1924
|
+
*/
|
|
1925
|
+
async _recall(correlated) {
|
|
1926
|
+
const missed = [...correlated].filter(([, entry]) => entry.missed);
|
|
1927
|
+
await Promise.all(
|
|
1928
|
+
missed.map(async ([stream, entry]) => {
|
|
1929
|
+
let row;
|
|
1930
|
+
await store().query_streams(
|
|
1931
|
+
(position) => {
|
|
1932
|
+
row = position;
|
|
1933
|
+
},
|
|
1934
|
+
{ stream, stream_exact: true, limit: 1 }
|
|
1935
|
+
);
|
|
1936
|
+
if (!row) return;
|
|
1937
|
+
this._dynamic_subscriptions.set(stream, {
|
|
1938
|
+
floor: row.priority,
|
|
1939
|
+
priority: row.priority,
|
|
1940
|
+
lane: row.lane
|
|
1941
|
+
});
|
|
1942
|
+
if (entry.priority > row.priority) return;
|
|
1943
|
+
const held_lane = row.lane ?? DEFAULT_LANE;
|
|
1944
|
+
const resolved_lane = entry.lane ?? DEFAULT_LANE;
|
|
1945
|
+
if (entry.priority === row.priority && held_lane !== resolved_lane)
|
|
1946
|
+
report_lane_conflict(
|
|
1947
|
+
this._reported,
|
|
1948
|
+
entry.handler,
|
|
1949
|
+
stream,
|
|
1950
|
+
held_lane,
|
|
1951
|
+
resolved_lane
|
|
1952
|
+
);
|
|
1953
|
+
entry.priority = row.priority;
|
|
1954
|
+
entry.lane = row.lane;
|
|
1955
|
+
entry.upgraded = false;
|
|
1956
|
+
})
|
|
1957
|
+
);
|
|
1958
|
+
}
|
|
1911
1959
|
/**
|
|
1912
1960
|
* Hand the correlation lease back early.
|
|
1913
1961
|
*
|
|
@@ -2067,9 +2115,8 @@ var DeferTimer = class {
|
|
|
2067
2115
|
_timer;
|
|
2068
2116
|
_on_wake;
|
|
2069
2117
|
/**
|
|
2070
|
-
* @param on_wake - invoked once each time the earliest due-time elapses
|
|
2071
|
-
*
|
|
2072
|
-
* for whatever is still parked.
|
|
2118
|
+
* @param on_wake - invoked once each time the earliest due-time elapses.
|
|
2119
|
+
* The consumer re-schedules for whatever is still parked.
|
|
2073
2120
|
*/
|
|
2074
2121
|
constructor(on_wake) {
|
|
2075
2122
|
this._on_wake = on_wake;
|
|
@@ -2099,6 +2146,16 @@ var DeferTimer = class {
|
|
|
2099
2146
|
delete(stream) {
|
|
2100
2147
|
this._due.delete(stream);
|
|
2101
2148
|
}
|
|
2149
|
+
/**
|
|
2150
|
+
* Drop every entry due at or before `before`. The drain calls it when a
|
|
2151
|
+
* pass that started at `before` claimed nothing: whatever was due by then
|
|
2152
|
+
* was handled elsewhere (another worker) or has no work left, so waking
|
|
2153
|
+
* for it again would spin.
|
|
2154
|
+
*/
|
|
2155
|
+
prune(before) {
|
|
2156
|
+
for (const [stream, at] of this._due)
|
|
2157
|
+
if (at <= before) this._due.delete(stream);
|
|
2158
|
+
}
|
|
2102
2159
|
/**
|
|
2103
2160
|
* (Re)schedule the wake timer at the earliest pending due-time. Idempotent
|
|
2104
2161
|
* — collapses many parked streams into a single timer. A no-op clears any
|
|
@@ -2121,9 +2178,6 @@ var DeferTimer = class {
|
|
|
2121
2178
|
);
|
|
2122
2179
|
this._timer = setTimeout(() => {
|
|
2123
2180
|
this._timer = void 0;
|
|
2124
|
-
const now = Date.now();
|
|
2125
|
-
for (const [stream, at] of this._due)
|
|
2126
|
-
if (at <= now) this._due.delete(stream);
|
|
2127
2181
|
this._on_wake();
|
|
2128
2182
|
}, delay);
|
|
2129
2183
|
this._timer.unref();
|
|
@@ -2892,6 +2946,9 @@ var DrainController = class {
|
|
|
2892
2946
|
* schedule itself is persisted in the store; this runs the drain at the
|
|
2893
2947
|
* earliest pending visit. A parked stream already carries its mark, so
|
|
2894
2948
|
* the drain alone finds it, and on an idle app nothing else would.
|
|
2949
|
+
* Every drain re-aims it when it ends, and a due entry stays until a pass
|
|
2950
|
+
* handles it or a pass that started after it came due claims nothing, so
|
|
2951
|
+
* the wake keeps draining until every due stream is reached.
|
|
2895
2952
|
* `stop()` cancels the timer and a stopped drain never re-schedules it,
|
|
2896
2953
|
* so a wake never runs after a stop.
|
|
2897
2954
|
*/
|
|
@@ -2989,15 +3046,16 @@ var DrainController = class {
|
|
|
2989
3046
|
const streamLimit = d.streamLimit ?? options.streamLimit ?? DEFAULT_STREAM_LIMIT;
|
|
2990
3047
|
const eventLimit = d.eventLimit ?? options.eventLimit ?? DEFAULT_EVENT_LIMIT;
|
|
2991
3048
|
const leaseMillis = d.leaseMillis ?? options.leaseMillis ?? DEFAULT_LEASE_MILLIS;
|
|
3049
|
+
if (this._deps.breaker.state(Date.now()) === "open")
|
|
3050
|
+
return EMPTY_DRAIN;
|
|
2992
3051
|
try {
|
|
2993
|
-
if (this._deps.breaker.state(Date.now()) === "open")
|
|
2994
|
-
return EMPTY_DRAIN;
|
|
2995
3052
|
this._locked = true;
|
|
2996
3053
|
this._inflight = new Promise((done) => {
|
|
2997
3054
|
this._inflight_done = done;
|
|
2998
3055
|
});
|
|
2999
3056
|
const lagging = Math.ceil(streamLimit * this._ratio);
|
|
3000
3057
|
const leading = streamLimit - lagging;
|
|
3058
|
+
const started = Date.now();
|
|
3001
3059
|
const cycle = await run_drain_cycle(this._deps, {
|
|
3002
3060
|
lagging,
|
|
3003
3061
|
leading,
|
|
@@ -3007,6 +3065,7 @@ var DrainController = class {
|
|
|
3007
3065
|
store_failing: this._deps.breaker.failing
|
|
3008
3066
|
});
|
|
3009
3067
|
if (!cycle) {
|
|
3068
|
+
this._defer.prune(started);
|
|
3010
3069
|
this._deps.breaker.passed();
|
|
3011
3070
|
this._armed = false;
|
|
3012
3071
|
return EMPTY_DRAIN;
|