@rotorsoft/act 1.23.1 → 1.23.3
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 +18 -0
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
- package/dist/@types/internal/close-cycle.d.ts +16 -0
- package/dist/@types/internal/close-cycle.d.ts.map +1 -1
- package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
- package/dist/{chunk-4HYYZOEH.js → chunk-5YIRFU4Y.js} +17 -4
- package/dist/chunk-5YIRFU4Y.js.map +1 -0
- package/dist/index.cjs +78 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +63 -15
- package/dist/index.js.map +1 -1
- package/dist/test/index.cjs +16 -3
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-4HYYZOEH.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
sleep,
|
|
21
21
|
store,
|
|
22
22
|
validate
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-5YIRFU4Y.js";
|
|
24
24
|
import {
|
|
25
25
|
ActorSchema,
|
|
26
26
|
CausationEventSchema,
|
|
@@ -1216,21 +1216,37 @@ async function run_windowed_closes(windowed, deps, skipped) {
|
|
|
1216
1216
|
windowed.map((t) => t.stream),
|
|
1217
1217
|
deps.probe_page_size ?? SAFETY_PROBE_PAGE_SIZE
|
|
1218
1218
|
) : /* @__PURE__ */ new Map();
|
|
1219
|
+
const with_lock = deps.with_stream_lock ?? ((_stream, work) => work());
|
|
1220
|
+
const truncated = /* @__PURE__ */ new Map();
|
|
1219
1221
|
for (const t of windowed) {
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
if (
|
|
1222
|
+
const entry = await with_lock(t.stream, async () => {
|
|
1223
|
+
const max_id = min_at.get(t.stream);
|
|
1224
|
+
if (!await windowed_prune_pending(t.stream, t.before, max_id))
|
|
1225
|
+
return void 0;
|
|
1226
|
+
if (t.archive) await t.archive();
|
|
1227
|
+
const result = await store().truncate([
|
|
1228
|
+
{ stream: t.stream, before: t.before, max_id }
|
|
1229
|
+
]);
|
|
1230
|
+
return result.get(t.stream);
|
|
1231
|
+
});
|
|
1232
|
+
if (entry) truncated.set(t.stream, entry);
|
|
1233
|
+
else skipped.push(t.stream);
|
|
1231
1234
|
}
|
|
1232
1235
|
return truncated;
|
|
1233
1236
|
}
|
|
1237
|
+
async function windowed_prune_pending(stream, before, max_id) {
|
|
1238
|
+
let boundary_id;
|
|
1239
|
+
let min_id;
|
|
1240
|
+
await store().query(
|
|
1241
|
+
(event) => {
|
|
1242
|
+
if (min_id === void 0 || event.id < min_id) min_id = event.id;
|
|
1243
|
+
if (event.name === SNAP_EVENT && event.created < before && (max_id === void 0 || event.id <= max_id) && (boundary_id === void 0 || event.id > boundary_id))
|
|
1244
|
+
boundary_id = event.id;
|
|
1245
|
+
},
|
|
1246
|
+
{ stream, stream_exact: true, with_snaps: true, after: -1 }
|
|
1247
|
+
);
|
|
1248
|
+
return boundary_id !== void 0 && min_id < boundary_id;
|
|
1249
|
+
}
|
|
1234
1250
|
async function probe_min_watermarks(streams, page_size) {
|
|
1235
1251
|
const min_at = /* @__PURE__ */ new Map();
|
|
1236
1252
|
const source_regex = /* @__PURE__ */ new Map();
|
|
@@ -1505,8 +1521,10 @@ var CorrelateCycle = class {
|
|
|
1505
1521
|
lane: resolved.lane,
|
|
1506
1522
|
payloads: []
|
|
1507
1523
|
};
|
|
1508
|
-
if (incoming_priority > entry.priority)
|
|
1524
|
+
if (incoming_priority > entry.priority) {
|
|
1509
1525
|
entry.priority = incoming_priority;
|
|
1526
|
+
entry.lane = resolved.lane;
|
|
1527
|
+
}
|
|
1510
1528
|
entry.payloads.push({
|
|
1511
1529
|
...reaction,
|
|
1512
1530
|
source: resolved.source,
|
|
@@ -2911,6 +2929,34 @@ var Act = class {
|
|
|
2911
2929
|
_handle_batch;
|
|
2912
2930
|
/** Declared drain lanes (ACT-1103). */
|
|
2913
2931
|
_lanes;
|
|
2932
|
+
/**
|
|
2933
|
+
* Per-stream close serialization tails (#1222). Chains each stream's
|
|
2934
|
+
* windowed-close work behind the previous one so a manual
|
|
2935
|
+
* `app.close([{stream, before}])` and an autoclose windowed close for
|
|
2936
|
+
* the same stream never run their guard-free prune concurrently — the
|
|
2937
|
+
* manual path bypasses the `__autoclose__:X` drain lease that would
|
|
2938
|
+
* otherwise exclude them, so without this both closers archive the
|
|
2939
|
+
* same prefix. Process-local: both racers run on the same Act
|
|
2940
|
+
* instance. Entries are dropped once their tail resolves so the map
|
|
2941
|
+
* doesn't grow with distinct stream names.
|
|
2942
|
+
*/
|
|
2943
|
+
_close_locks = /* @__PURE__ */ new Map();
|
|
2944
|
+
/**
|
|
2945
|
+
* Run `work` under the per-stream close lock (#1222). Serializes
|
|
2946
|
+
* windowed-close critical sections for the same stream while letting
|
|
2947
|
+
* different streams proceed in parallel.
|
|
2948
|
+
*/
|
|
2949
|
+
_with_close_lock(stream, work) {
|
|
2950
|
+
const prev = this._close_locks.get(stream) ?? Promise.resolve();
|
|
2951
|
+
const next = prev.then(work, work);
|
|
2952
|
+
this._close_locks.set(stream, next);
|
|
2953
|
+
const cleanup = () => {
|
|
2954
|
+
if (this._close_locks.get(stream) === next)
|
|
2955
|
+
this._close_locks.delete(stream);
|
|
2956
|
+
};
|
|
2957
|
+
next.then(cleanup, cleanup);
|
|
2958
|
+
return next;
|
|
2959
|
+
}
|
|
2914
2960
|
/** Drain lanes declared via `.withLane(...)`. Implicit default not included. */
|
|
2915
2961
|
get lanes() {
|
|
2916
2962
|
return this._lanes;
|
|
@@ -3032,7 +3078,8 @@ var Act = class {
|
|
|
3032
3078
|
load: this._es.load,
|
|
3033
3079
|
tombstone: this._es.tombstone,
|
|
3034
3080
|
logger: this._logger,
|
|
3035
|
-
correlation: close_correlation(this._correlator, close_actor)
|
|
3081
|
+
correlation: close_correlation(this._correlator, close_actor),
|
|
3082
|
+
with_stream_lock: (stream, work) => this._with_close_lock(stream, work)
|
|
3036
3083
|
});
|
|
3037
3084
|
this.emit("closed", result);
|
|
3038
3085
|
},
|
|
@@ -4022,7 +4069,8 @@ var Act = class {
|
|
|
4022
4069
|
load: this._es.load,
|
|
4023
4070
|
tombstone: this._es.tombstone,
|
|
4024
4071
|
logger: this._logger,
|
|
4025
|
-
correlation: close_correlation(this._correlator, close_actor)
|
|
4072
|
+
correlation: close_correlation(this._correlator, close_actor),
|
|
4073
|
+
with_stream_lock: (stream, work) => this._with_close_lock(stream, work)
|
|
4026
4074
|
});
|
|
4027
4075
|
this.emit("closed", result);
|
|
4028
4076
|
return result;
|