@rotorsoft/act 1.23.31 → 1.23.33
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.map +1 -1
- package/dist/@types/internal/close-cycle.d.ts.map +1 -1
- package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
- package/dist/index.cjs +34 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +34 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1311,6 +1311,19 @@ async function run_close_cycle(targets, deps) {
|
|
|
1311
1311
|
if (!full.length) return { truncated: windowed_result, skipped };
|
|
1312
1312
|
const streams = full.map((t) => t.stream);
|
|
1313
1313
|
const stream_info = await scan_stream_heads(streams);
|
|
1314
|
+
for (const target of full) {
|
|
1315
|
+
if (!target.restart) continue;
|
|
1316
|
+
const info = stream_info.get(target.stream);
|
|
1317
|
+
if (!info) continue;
|
|
1318
|
+
const owner = deps.event_to_state.get(info.last_event_name);
|
|
1319
|
+
if (owner?.pii_aware) {
|
|
1320
|
+
deps.logger.error(
|
|
1321
|
+
`Refusing to close "${target.stream}" with restart: state "${owner.name}" carries sensitive fields, so a restart seed would persist redacted values while deleting the originals. Close it without restart to retire the stream, or leave it open.`
|
|
1322
|
+
);
|
|
1323
|
+
skipped.push(target.stream);
|
|
1324
|
+
stream_info.delete(target.stream);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1314
1327
|
const safe = await partition_by_safety(
|
|
1315
1328
|
stream_info,
|
|
1316
1329
|
deps.reactive_events_size,
|
|
@@ -1417,14 +1430,19 @@ async function scan_stream_heads(streams) {
|
|
|
1417
1430
|
const stats = await store().query_stats(streams, {
|
|
1418
1431
|
exclude: [SNAP_EVENT]
|
|
1419
1432
|
});
|
|
1433
|
+
const domain_heads = await store().query_stats(streams, {
|
|
1434
|
+
exclude: [SNAP_EVENT, TOMBSTONE_EVENT]
|
|
1435
|
+
});
|
|
1420
1436
|
const true_heads = await store().query_stats(streams, {});
|
|
1421
1437
|
const out = /* @__PURE__ */ new Map();
|
|
1422
|
-
for (const [stream, { head }] of
|
|
1423
|
-
|
|
1438
|
+
for (const [stream, { head }] of domain_heads) {
|
|
1439
|
+
const marker_head = stats.get(stream)?.head;
|
|
1440
|
+
const interrupted = marker_head?.name === TOMBSTONE_EVENT;
|
|
1424
1441
|
out.set(stream, {
|
|
1425
1442
|
max_id: head.id,
|
|
1426
1443
|
version: true_heads.get(stream).head.version,
|
|
1427
|
-
last_event_name: head.name
|
|
1444
|
+
last_event_name: head.name,
|
|
1445
|
+
...interrupted ? { resumed_guard: { id: marker_head.id } } : {}
|
|
1428
1446
|
});
|
|
1429
1447
|
}
|
|
1430
1448
|
return out;
|
|
@@ -1473,6 +1491,11 @@ async function guard_with_tombstones(safe, stream_info, correlation, tombstone2,
|
|
|
1473
1491
|
await Promise.all(
|
|
1474
1492
|
safe.map(async (stream) => {
|
|
1475
1493
|
const info = stream_info.get(stream);
|
|
1494
|
+
if (info.resumed_guard) {
|
|
1495
|
+
guarded.push(stream);
|
|
1496
|
+
guard_events.set(stream, { id: info.resumed_guard.id, stream });
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1476
1499
|
const committed = await tombstone2(stream, info.version, correlation);
|
|
1477
1500
|
if (committed) {
|
|
1478
1501
|
guarded.push(stream);
|
|
@@ -2542,13 +2565,6 @@ var contain = (logger, sink, fn) => {
|
|
|
2542
2565
|
logger.error(error, `${sink} listener threw`);
|
|
2543
2566
|
}
|
|
2544
2567
|
};
|
|
2545
|
-
var contain_async = async (logger, sink, fn) => {
|
|
2546
|
-
try {
|
|
2547
|
-
await fn();
|
|
2548
|
-
} catch (error) {
|
|
2549
|
-
logger.error(error, `${sink} listener threw`);
|
|
2550
|
-
}
|
|
2551
|
-
};
|
|
2552
2568
|
var DrainController = class {
|
|
2553
2569
|
_armed = false;
|
|
2554
2570
|
_locked = false;
|
|
@@ -2660,8 +2676,8 @@ var DrainController = class {
|
|
|
2660
2676
|
(b) => contain(this._deps.logger, "blocked", () => this._deps.on_blocked(b)),
|
|
2661
2677
|
this._deps.lane
|
|
2662
2678
|
);
|
|
2663
|
-
this._deps.breaker.passed();
|
|
2664
2679
|
if (!cycle) {
|
|
2680
|
+
this._deps.breaker.passed();
|
|
2665
2681
|
this._armed = false;
|
|
2666
2682
|
return EMPTY_DRAIN;
|
|
2667
2683
|
}
|
|
@@ -2677,12 +2693,8 @@ var DrainController = class {
|
|
|
2677
2693
|
if (this._defer.size > 0) this._defer.schedule();
|
|
2678
2694
|
if (acked.length)
|
|
2679
2695
|
contain(this._deps.logger, "acked", () => this._deps.on_acked(acked));
|
|
2680
|
-
if (closeable.length)
|
|
2681
|
-
|
|
2682
|
-
this._deps.logger,
|
|
2683
|
-
"close",
|
|
2684
|
-
() => this._deps.on_close(closeable)
|
|
2685
|
-
);
|
|
2696
|
+
if (closeable.length) await this._deps.on_close(closeable);
|
|
2697
|
+
this._deps.breaker.passed();
|
|
2686
2698
|
const has_errors = handled.some(({ error }) => error);
|
|
2687
2699
|
if (!acked.length && !blocked.length && !has_errors) this._armed = false;
|
|
2688
2700
|
return { fetched, leased, acked, blocked };
|
|
@@ -3274,7 +3286,11 @@ var Act = class {
|
|
|
3274
3286
|
correlation: close_correlation(this._correlator, close_actor),
|
|
3275
3287
|
with_stream_lock: (stream, work) => this._with_close_lock(stream, work)
|
|
3276
3288
|
});
|
|
3277
|
-
|
|
3289
|
+
try {
|
|
3290
|
+
this.emit("closed", result);
|
|
3291
|
+
} catch (err) {
|
|
3292
|
+
this._logger.error(err, "closed listener threw");
|
|
3293
|
+
}
|
|
3278
3294
|
},
|
|
3279
3295
|
breaker: this._breaker,
|
|
3280
3296
|
// Re-scope the per-lane worker's auto-start ticks so their drain
|