@rotorsoft/act 1.33.11 → 1.33.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 +6 -7
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/adapters/in-memory-store.d.ts +1 -1
- package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
- package/dist/@types/internal/config.d.ts +1 -1
- package/dist/@types/internal/correlate-cycle.d.ts +4 -3
- package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
- package/dist/@types/internal/drain-cycle.d.ts +6 -3
- package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
- package/dist/@types/internal/settle.d.ts +2 -3
- package/dist/@types/internal/settle.d.ts.map +1 -1
- package/dist/@types/types/ports.d.ts +4 -6
- package/dist/@types/types/ports.d.ts.map +1 -1
- package/dist/@types/types/reaction.d.ts +2 -1
- package/dist/@types/types/reaction.d.ts.map +1 -1
- package/dist/{chunk-2FOO4S2J.js → chunk-CAL4XEVN.js} +1 -1
- package/dist/chunk-CAL4XEVN.js.map +1 -0
- package/dist/{chunk-F4F7CYBN.js → chunk-MSD67APM.js} +61 -72
- package/dist/chunk-MSD67APM.js.map +1 -0
- package/dist/{chunk-KB7D46CC.cjs → chunk-PMS6BMIU.cjs} +1 -1
- package/dist/chunk-PMS6BMIU.cjs.map +1 -0
- package/dist/{chunk-HKC663W4.cjs → chunk-U54EW4DX.cjs} +82 -93
- package/dist/chunk-U54EW4DX.cjs.map +1 -0
- package/dist/index.cjs +252 -263
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -73
- package/dist/index.js.map +1 -1
- package/dist/test/index.cjs +4 -4
- package/dist/test/index.js +2 -2
- package/dist/types/index.cjs +2 -2
- package/dist/types/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2FOO4S2J.js.map +0 -1
- package/dist/chunk-F4F7CYBN.js.map +0 -1
- package/dist/chunk-HKC663W4.cjs.map +0 -1
- package/dist/chunk-KB7D46CC.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
sleep,
|
|
41
41
|
store,
|
|
42
42
|
validate
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-MSD67APM.js";
|
|
44
44
|
import {
|
|
45
45
|
ActorSchema,
|
|
46
46
|
CausationEventSchema,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
pii_fields,
|
|
71
71
|
pii_schemas,
|
|
72
72
|
sensitive
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-CAL4XEVN.js";
|
|
74
74
|
|
|
75
75
|
// src/signals.ts
|
|
76
76
|
process.once("SIGINT", async (arg) => {
|
|
@@ -1156,7 +1156,6 @@ function report_lane_conflict(seen, handler, target, kept, dropped) {
|
|
|
1156
1156
|
}
|
|
1157
1157
|
var CorrelateCycle = class {
|
|
1158
1158
|
_checkpoint = -1;
|
|
1159
|
-
_initialized = false;
|
|
1160
1159
|
/** Lease holder id; per instance, so a restart never inherits a stale claim. */
|
|
1161
1160
|
_by = randomUUID();
|
|
1162
1161
|
_key;
|
|
@@ -1210,16 +1209,12 @@ var CorrelateCycle = class {
|
|
|
1210
1209
|
arm() {
|
|
1211
1210
|
this._raised++;
|
|
1212
1211
|
}
|
|
1213
|
-
async
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
throw error;
|
|
1219
|
-
});
|
|
1220
|
-
}
|
|
1212
|
+
async _init() {
|
|
1213
|
+
this._init_promise ??= this._run_init().catch((error) => {
|
|
1214
|
+
this._init_promise = void 0;
|
|
1215
|
+
throw error;
|
|
1216
|
+
});
|
|
1221
1217
|
await this._init_promise;
|
|
1222
|
-
this._initialized = true;
|
|
1223
1218
|
}
|
|
1224
1219
|
async _run_init() {
|
|
1225
1220
|
const { watermark, correlated_at } = await this._cd.subscribe([
|
|
@@ -1237,7 +1232,6 @@ var CorrelateCycle = class {
|
|
|
1237
1232
|
}
|
|
1238
1233
|
/** After `restore` replaced the log: forget everything and cold-start again. */
|
|
1239
1234
|
restart() {
|
|
1240
|
-
this._initialized = false;
|
|
1241
1235
|
this._init_promise = void 0;
|
|
1242
1236
|
this._checkpoint = -1;
|
|
1243
1237
|
this._dynamic_subscriptions.clear();
|
|
@@ -1261,12 +1255,13 @@ var CorrelateCycle = class {
|
|
|
1261
1255
|
return pattern.test(stream);
|
|
1262
1256
|
}
|
|
1263
1257
|
/** Scan past the checkpoint, subscribe new targets and raise their work marks. */
|
|
1264
|
-
async correlate(query
|
|
1265
|
-
await this.
|
|
1258
|
+
async correlate(query, lease = false) {
|
|
1259
|
+
await this._init();
|
|
1266
1260
|
const epoch = this._epoch;
|
|
1267
1261
|
const idle = () => ({
|
|
1268
1262
|
subscribed: 0,
|
|
1269
1263
|
last_id: this._checkpoint,
|
|
1264
|
+
read: false,
|
|
1270
1265
|
marked: 0,
|
|
1271
1266
|
scanned: false
|
|
1272
1267
|
});
|
|
@@ -1360,6 +1355,7 @@ var CorrelateCycle = class {
|
|
|
1360
1355
|
{ ...query, after, with_pii: false }
|
|
1361
1356
|
);
|
|
1362
1357
|
if (this._declared_lanes.size > 1) await this._recall(correlated);
|
|
1358
|
+
const read = last_id > after;
|
|
1363
1359
|
if (this._epoch !== epoch) return idle();
|
|
1364
1360
|
const streams = [];
|
|
1365
1361
|
for (const [stream, entry] of correlated) {
|
|
@@ -1393,11 +1389,11 @@ var CorrelateCycle = class {
|
|
|
1393
1389
|
lane
|
|
1394
1390
|
});
|
|
1395
1391
|
}
|
|
1396
|
-
return { subscribed, last_id, marked, scanned: true };
|
|
1392
|
+
return { subscribed, last_id, read, marked, scanned: true };
|
|
1397
1393
|
}
|
|
1398
1394
|
this._checkpoint = last_id;
|
|
1399
1395
|
if (!stopped && found !== query.limit) this._lowered = raised;
|
|
1400
|
-
return { subscribed: 0, last_id, marked: 0, scanned: true };
|
|
1396
|
+
return { subscribed: 0, last_id, read, marked: 0, scanned: true };
|
|
1401
1397
|
}
|
|
1402
1398
|
/**
|
|
1403
1399
|
* Read the row of each target this scan had no record of (new or evicted),
|
|
@@ -2354,6 +2350,14 @@ var EMPTY_DRAIN = {
|
|
|
2354
2350
|
acked: [],
|
|
2355
2351
|
blocked: []
|
|
2356
2352
|
};
|
|
2353
|
+
function merge_drains(drains) {
|
|
2354
|
+
return {
|
|
2355
|
+
fetched: drains.flatMap((d) => d.fetched),
|
|
2356
|
+
leased: drains.flatMap((d) => d.leased),
|
|
2357
|
+
acked: drains.flatMap((d) => d.acked),
|
|
2358
|
+
blocked: drains.flatMap((d) => d.blocked)
|
|
2359
|
+
};
|
|
2360
|
+
}
|
|
2357
2361
|
var RETRY = "";
|
|
2358
2362
|
var DrainController = class {
|
|
2359
2363
|
/**
|
|
@@ -2380,9 +2384,8 @@ var DrainController = class {
|
|
|
2380
2384
|
_worker;
|
|
2381
2385
|
_misrouted = /* @__PURE__ */ new Set();
|
|
2382
2386
|
_stopped = false;
|
|
2383
|
-
/** Never rejects; graceful shutdown waits on it. */
|
|
2387
|
+
/** The pass in flight. Never rejects; graceful shutdown waits on it. */
|
|
2384
2388
|
_inflight;
|
|
2385
|
-
_inflight_done;
|
|
2386
2389
|
_deps;
|
|
2387
2390
|
constructor(deps) {
|
|
2388
2391
|
this._deps = deps;
|
|
@@ -2438,10 +2441,17 @@ var DrainController = class {
|
|
|
2438
2441
|
const leaseMillis = d.leaseMillis ?? options.leaseMillis ?? DEFAULT_LEASE_MILLIS;
|
|
2439
2442
|
if (this._deps.breaker.state(Date.now()) === "open")
|
|
2440
2443
|
return EMPTY_DRAIN;
|
|
2444
|
+
const pass = this._pass(streamLimit, eventLimit, leaseMillis).finally(
|
|
2445
|
+
() => {
|
|
2446
|
+
this._inflight = void 0;
|
|
2447
|
+
}
|
|
2448
|
+
);
|
|
2449
|
+
this._inflight = pass;
|
|
2450
|
+
return pass;
|
|
2451
|
+
}
|
|
2452
|
+
/** One claim → fetch → handle → ack pass. Never throws. */
|
|
2453
|
+
async _pass(streamLimit, eventLimit, leaseMillis) {
|
|
2441
2454
|
try {
|
|
2442
|
-
this._inflight = new Promise((done) => {
|
|
2443
|
-
this._inflight_done = done;
|
|
2444
|
-
});
|
|
2445
2455
|
const lagging = Math.ceil(streamLimit * this._ratio);
|
|
2446
2456
|
const leading = streamLimit - lagging;
|
|
2447
2457
|
const started = Date.now();
|
|
@@ -2482,9 +2492,6 @@ var DrainController = class {
|
|
|
2482
2492
|
return EMPTY_DRAIN;
|
|
2483
2493
|
} finally {
|
|
2484
2494
|
if (!this._stopped) this._defer.schedule();
|
|
2485
|
-
this._inflight = void 0;
|
|
2486
|
-
this._inflight_done?.();
|
|
2487
|
-
this._inflight_done = void 0;
|
|
2488
2495
|
}
|
|
2489
2496
|
}
|
|
2490
2497
|
};
|
|
@@ -2852,32 +2859,23 @@ var SettleLoop = class {
|
|
|
2852
2859
|
this._timer = void 0;
|
|
2853
2860
|
const {
|
|
2854
2861
|
debounceMs: _,
|
|
2855
|
-
|
|
2862
|
+
// Every pass scans from correlation's own checkpoint.
|
|
2863
|
+
correlate: { after: _after, ...correlate_query } = {},
|
|
2856
2864
|
maxPasses = Infinity,
|
|
2857
2865
|
...drain_options
|
|
2858
2866
|
} = this._next ?? {};
|
|
2859
2867
|
this._next = void 0;
|
|
2860
2868
|
this._inflight = (async () => {
|
|
2861
|
-
|
|
2862
|
-
let settled_drain;
|
|
2869
|
+
const passes = [];
|
|
2863
2870
|
for (let i = 0; i < maxPasses && !this._stopped; i++) {
|
|
2864
|
-
const
|
|
2865
|
-
const { subscribed, last_id, scanned } = await this._deps.correlate({
|
|
2866
|
-
...correlate_query,
|
|
2867
|
-
after: after_before
|
|
2868
|
-
});
|
|
2871
|
+
const { subscribed, read, scanned } = await this._deps.correlate(correlate_query);
|
|
2869
2872
|
if (scanned) this._deps.breaker.passed();
|
|
2870
2873
|
const drain = await this._deps.drain(drain_options);
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
leased: [...settled_drain.leased, ...drain.leased],
|
|
2874
|
-
acked: [...settled_drain.acked, ...drain.acked],
|
|
2875
|
-
blocked: [...settled_drain.blocked, ...drain.blocked]
|
|
2876
|
-
} : drain;
|
|
2877
|
-
const made_progress = subscribed > 0 || drain.leased.length > 0 || last_id > after_before;
|
|
2874
|
+
passes.push(drain);
|
|
2875
|
+
const made_progress = subscribed > 0 || drain.leased.length > 0 || read;
|
|
2878
2876
|
if (!made_progress) break;
|
|
2879
2877
|
}
|
|
2880
|
-
if (
|
|
2878
|
+
if (passes.length) this._deps.on_settled(merge_drains(passes));
|
|
2881
2879
|
})().catch((err) => {
|
|
2882
2880
|
this._deps.breaker.failed(Date.now(), err);
|
|
2883
2881
|
}).finally(() => {
|
|
@@ -3182,8 +3180,6 @@ var Act = class {
|
|
|
3182
3180
|
_build_settle(options) {
|
|
3183
3181
|
return new SettleLoop(
|
|
3184
3182
|
{
|
|
3185
|
-
init: () => this._scoped(() => this._correlate.init()),
|
|
3186
|
-
checkpoint: () => this._correlate.checkpoint,
|
|
3187
3183
|
correlate: (q) => this._correlate_scanned(
|
|
3188
3184
|
{ ...q, limit: q.limit ?? this._poll_limit ?? 100 },
|
|
3189
3185
|
true
|
|
@@ -3199,9 +3195,10 @@ var Act = class {
|
|
|
3199
3195
|
}
|
|
3200
3196
|
_shutdown_promise;
|
|
3201
3197
|
/**
|
|
3202
|
-
* Per-instance teardown: stops scheduling,
|
|
3203
|
-
* to `graceMs` to reach their
|
|
3204
|
-
* until it expires), then
|
|
3198
|
+
* Per-instance teardown: stops scheduling, removes the notify
|
|
3199
|
+
* subscription, gives the cycles in flight up to `graceMs` to reach their
|
|
3200
|
+
* `ack` (an abandoned handler holds its lease until it expires), then
|
|
3201
|
+
* hands back the correlation lease and removes listeners.
|
|
3205
3202
|
* The budget is a ceiling, not a delay.
|
|
3206
3203
|
*
|
|
3207
3204
|
* Idempotent: repeated calls return the same promise, with the first
|
|
@@ -3513,27 +3510,20 @@ var Act = class {
|
|
|
3513
3510
|
}
|
|
3514
3511
|
/** In parallel, so a slow lane never holds up a fast one. */
|
|
3515
3512
|
async _drain_all(options) {
|
|
3516
|
-
const
|
|
3517
|
-
|
|
3513
|
+
const merged = merge_drains(
|
|
3514
|
+
await Promise.all(
|
|
3515
|
+
[...this._drain_controllers.values()].map((c) => c.drain(options))
|
|
3516
|
+
)
|
|
3518
3517
|
);
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
(e) => this.registry.query_gate(e.name)(e)
|
|
3529
|
-
)
|
|
3530
|
-
}))
|
|
3531
|
-
);
|
|
3532
|
-
leased.push(...r.leased);
|
|
3533
|
-
acked.push(...r.acked);
|
|
3534
|
-
blocked.push(...r.blocked);
|
|
3535
|
-
}
|
|
3536
|
-
return { fetched, leased, acked, blocked };
|
|
3518
|
+
return {
|
|
3519
|
+
...merged,
|
|
3520
|
+
fetched: merged.fetched.map((f) => ({
|
|
3521
|
+
...f,
|
|
3522
|
+
events: f.events.map(
|
|
3523
|
+
(e) => this.registry.query_gate(e.name)(e)
|
|
3524
|
+
)
|
|
3525
|
+
}))
|
|
3526
|
+
};
|
|
3537
3527
|
}
|
|
3538
3528
|
/**
|
|
3539
3529
|
* Scans committed events from the correlation checkpoint, subscribes the
|
|
@@ -3557,11 +3547,12 @@ var Act = class {
|
|
|
3557
3547
|
}
|
|
3558
3548
|
/** `correlate` plus `scanned`, which settle needs for the breaker. */
|
|
3559
3549
|
async _correlate_scanned(query, lease = false) {
|
|
3560
|
-
if (!this._drain)
|
|
3550
|
+
if (!this._drain)
|
|
3551
|
+
return { subscribed: 0, last_id: -1, read: false, scanned: false };
|
|
3561
3552
|
return this._scoped(async () => {
|
|
3562
|
-
const { subscribed, last_id, marked, scanned } = await this._correlate.correlate(query, lease);
|
|
3553
|
+
const { subscribed, last_id, read, marked, scanned } = await this._correlate.correlate(query, lease);
|
|
3563
3554
|
if (subscribed > 0 || marked > 0) this._arm_all();
|
|
3564
|
-
return { subscribed, last_id, scanned };
|
|
3555
|
+
return { subscribed, last_id, read, scanned };
|
|
3565
3556
|
});
|
|
3566
3557
|
}
|
|
3567
3558
|
/**
|
|
@@ -3885,10 +3876,8 @@ var Act = class {
|
|
|
3885
3876
|
* A local change that frees reaction work (a commit, `reset()`,
|
|
3886
3877
|
* `unblock()`, `restore()`) schedules this on its own unless the app
|
|
3887
3878
|
* sets `autoSettle: false`. Call it at startup, to run what was pending
|
|
3888
|
-
* before a restart, or with options for the next pass
|
|
3889
|
-
*
|
|
3890
|
-
* `debounceMs` brings it forward), and a call during a running cycle
|
|
3891
|
-
* queues one more pass after it. Runs correlate→drain in a loop until a pass makes no
|
|
3879
|
+
* before a restart, or with options for the next pass; the scheduling
|
|
3880
|
+
* rule is in the event-sourcing docs (§ settle). Runs correlate→drain in a loop until a pass makes no
|
|
3892
3881
|
* progress — no new subscriptions, no events read, no streams leased —
|
|
3893
3882
|
* then emits the `"settled"` lifecycle event, so one call fully catches
|
|
3894
3883
|
* up paginated streams without forcing callers to loop.
|