@rotorsoft/act 1.33.12 → 1.33.14
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 +2 -2
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/internal/correlate-cycle.d.ts +21 -9
- 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 +3 -7
- package/dist/@types/internal/settle.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-URF33KO3.js → chunk-CAL4XEVN.js} +1 -1
- package/dist/{chunk-URF33KO3.js.map → chunk-CAL4XEVN.js.map} +1 -1
- package/dist/{chunk-YZ2NKMVS.js → chunk-MSD67APM.js} +2 -2
- package/dist/{chunk-AVXVMZ4B.cjs → chunk-PMS6BMIU.cjs} +1 -1
- package/dist/{chunk-AVXVMZ4B.cjs.map → chunk-PMS6BMIU.cjs.map} +1 -1
- package/dist/{chunk-P3B7HVFD.cjs → chunk-U54EW4DX.cjs} +13 -13
- package/dist/{chunk-P3B7HVFD.cjs.map → chunk-U54EW4DX.cjs.map} +1 -1
- package/dist/index.cjs +261 -269
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +71 -79
- 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-YZ2NKMVS.js.map → chunk-MSD67APM.js.map} +0 -0
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,14 +1255,12 @@ 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
|
-
|
|
1269
|
-
last_id: this._checkpoint
|
|
1270
|
-
marked: 0,
|
|
1271
|
-
scanned: false
|
|
1262
|
+
kind: "idle",
|
|
1263
|
+
last_id: this._checkpoint
|
|
1272
1264
|
});
|
|
1273
1265
|
if (this._raised === this._lowered) return idle();
|
|
1274
1266
|
const raised = this._raised;
|
|
@@ -1360,6 +1352,7 @@ var CorrelateCycle = class {
|
|
|
1360
1352
|
{ ...query, after, with_pii: false }
|
|
1361
1353
|
);
|
|
1362
1354
|
if (this._declared_lanes.size > 1) await this._recall(correlated);
|
|
1355
|
+
const read = last_id > after;
|
|
1363
1356
|
if (this._epoch !== epoch) return idle();
|
|
1364
1357
|
const streams = [];
|
|
1365
1358
|
for (const [stream, entry] of correlated) {
|
|
@@ -1393,11 +1386,11 @@ var CorrelateCycle = class {
|
|
|
1393
1386
|
lane
|
|
1394
1387
|
});
|
|
1395
1388
|
}
|
|
1396
|
-
return {
|
|
1389
|
+
return { kind: "scanned", last_id, subscribed, marked, read };
|
|
1397
1390
|
}
|
|
1398
1391
|
this._checkpoint = last_id;
|
|
1399
1392
|
if (!stopped && found !== query.limit) this._lowered = raised;
|
|
1400
|
-
return {
|
|
1393
|
+
return { kind: "scanned", last_id, subscribed: 0, marked: 0, read };
|
|
1401
1394
|
}
|
|
1402
1395
|
/**
|
|
1403
1396
|
* Read the row of each target this scan had no record of (new or evicted),
|
|
@@ -2354,6 +2347,14 @@ var EMPTY_DRAIN = {
|
|
|
2354
2347
|
acked: [],
|
|
2355
2348
|
blocked: []
|
|
2356
2349
|
};
|
|
2350
|
+
function merge_drains(drains) {
|
|
2351
|
+
return {
|
|
2352
|
+
fetched: drains.flatMap((d) => d.fetched),
|
|
2353
|
+
leased: drains.flatMap((d) => d.leased),
|
|
2354
|
+
acked: drains.flatMap((d) => d.acked),
|
|
2355
|
+
blocked: drains.flatMap((d) => d.blocked)
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2357
2358
|
var RETRY = "";
|
|
2358
2359
|
var DrainController = class {
|
|
2359
2360
|
/**
|
|
@@ -2380,9 +2381,8 @@ var DrainController = class {
|
|
|
2380
2381
|
_worker;
|
|
2381
2382
|
_misrouted = /* @__PURE__ */ new Set();
|
|
2382
2383
|
_stopped = false;
|
|
2383
|
-
/** Never rejects; graceful shutdown waits on it. */
|
|
2384
|
+
/** The pass in flight. Never rejects; graceful shutdown waits on it. */
|
|
2384
2385
|
_inflight;
|
|
2385
|
-
_inflight_done;
|
|
2386
2386
|
_deps;
|
|
2387
2387
|
constructor(deps) {
|
|
2388
2388
|
this._deps = deps;
|
|
@@ -2438,10 +2438,17 @@ var DrainController = class {
|
|
|
2438
2438
|
const leaseMillis = d.leaseMillis ?? options.leaseMillis ?? DEFAULT_LEASE_MILLIS;
|
|
2439
2439
|
if (this._deps.breaker.state(Date.now()) === "open")
|
|
2440
2440
|
return EMPTY_DRAIN;
|
|
2441
|
+
const pass = this._pass(streamLimit, eventLimit, leaseMillis).finally(
|
|
2442
|
+
() => {
|
|
2443
|
+
this._inflight = void 0;
|
|
2444
|
+
}
|
|
2445
|
+
);
|
|
2446
|
+
this._inflight = pass;
|
|
2447
|
+
return pass;
|
|
2448
|
+
}
|
|
2449
|
+
/** One claim → fetch → handle → ack pass. Never throws. */
|
|
2450
|
+
async _pass(streamLimit, eventLimit, leaseMillis) {
|
|
2441
2451
|
try {
|
|
2442
|
-
this._inflight = new Promise((done) => {
|
|
2443
|
-
this._inflight_done = done;
|
|
2444
|
-
});
|
|
2445
2452
|
const lagging = Math.ceil(streamLimit * this._ratio);
|
|
2446
2453
|
const leading = streamLimit - lagging;
|
|
2447
2454
|
const started = Date.now();
|
|
@@ -2482,9 +2489,6 @@ var DrainController = class {
|
|
|
2482
2489
|
return EMPTY_DRAIN;
|
|
2483
2490
|
} finally {
|
|
2484
2491
|
if (!this._stopped) this._defer.schedule();
|
|
2485
|
-
this._inflight = void 0;
|
|
2486
|
-
this._inflight_done?.();
|
|
2487
|
-
this._inflight_done = void 0;
|
|
2488
2492
|
}
|
|
2489
2493
|
}
|
|
2490
2494
|
};
|
|
@@ -2852,32 +2856,24 @@ var SettleLoop = class {
|
|
|
2852
2856
|
this._timer = void 0;
|
|
2853
2857
|
const {
|
|
2854
2858
|
debounceMs: _,
|
|
2855
|
-
|
|
2859
|
+
// Every pass scans from correlation's own checkpoint.
|
|
2860
|
+
correlate: { after: _after, ...correlate_query } = {},
|
|
2856
2861
|
maxPasses = Infinity,
|
|
2857
2862
|
...drain_options
|
|
2858
2863
|
} = this._next ?? {};
|
|
2859
2864
|
this._next = void 0;
|
|
2860
2865
|
this._inflight = (async () => {
|
|
2861
|
-
|
|
2862
|
-
let settled_drain;
|
|
2866
|
+
const passes = [];
|
|
2863
2867
|
for (let i = 0; i < maxPasses && !this._stopped; i++) {
|
|
2864
|
-
const
|
|
2865
|
-
const
|
|
2866
|
-
...correlate_query,
|
|
2867
|
-
after: after_before
|
|
2868
|
-
});
|
|
2868
|
+
const pass = await this._deps.correlate(correlate_query);
|
|
2869
|
+
const scanned = pass.kind === "scanned";
|
|
2869
2870
|
if (scanned) this._deps.breaker.passed();
|
|
2870
2871
|
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;
|
|
2872
|
+
passes.push(drain);
|
|
2873
|
+
const made_progress = drain.leased.length > 0 || scanned && (pass.subscribed > 0 || pass.read);
|
|
2878
2874
|
if (!made_progress) break;
|
|
2879
2875
|
}
|
|
2880
|
-
if (
|
|
2876
|
+
if (passes.length) this._deps.on_settled(merge_drains(passes));
|
|
2881
2877
|
})().catch((err) => {
|
|
2882
2878
|
this._deps.breaker.failed(Date.now(), err);
|
|
2883
2879
|
}).finally(() => {
|
|
@@ -3182,9 +3178,7 @@ var Act = class {
|
|
|
3182
3178
|
_build_settle(options) {
|
|
3183
3179
|
return new SettleLoop(
|
|
3184
3180
|
{
|
|
3185
|
-
|
|
3186
|
-
checkpoint: () => this._correlate.checkpoint,
|
|
3187
|
-
correlate: (q) => this._correlate_scanned(
|
|
3181
|
+
correlate: (q) => this._correlate_pass(
|
|
3188
3182
|
{ ...q, limit: q.limit ?? this._poll_limit ?? 100 },
|
|
3189
3183
|
true
|
|
3190
3184
|
),
|
|
@@ -3247,15 +3241,16 @@ var Act = class {
|
|
|
3247
3241
|
if (running.length === 0 && !settling) return;
|
|
3248
3242
|
const grace = grace_ms ?? this._derive_grace_ms(running, !!settling);
|
|
3249
3243
|
if (grace <= 0) return;
|
|
3250
|
-
const inflight = running.map((c) => c.inflight);
|
|
3251
|
-
if (settling) inflight.push(settling);
|
|
3252
3244
|
let timer;
|
|
3253
3245
|
const budget = new Promise((resolve) => {
|
|
3254
3246
|
timer = setTimeout(resolve, grace);
|
|
3255
3247
|
timer.unref();
|
|
3256
3248
|
});
|
|
3257
3249
|
try {
|
|
3258
|
-
await Promise.race([
|
|
3250
|
+
await Promise.race([
|
|
3251
|
+
Promise.all([...running.map((c) => c.inflight), settling]),
|
|
3252
|
+
budget
|
|
3253
|
+
]);
|
|
3259
3254
|
} finally {
|
|
3260
3255
|
clearTimeout(timer);
|
|
3261
3256
|
}
|
|
@@ -3514,27 +3509,20 @@ var Act = class {
|
|
|
3514
3509
|
}
|
|
3515
3510
|
/** In parallel, so a slow lane never holds up a fast one. */
|
|
3516
3511
|
async _drain_all(options) {
|
|
3517
|
-
const
|
|
3518
|
-
|
|
3512
|
+
const merged = merge_drains(
|
|
3513
|
+
await Promise.all(
|
|
3514
|
+
[...this._drain_controllers.values()].map((c) => c.drain(options))
|
|
3515
|
+
)
|
|
3519
3516
|
);
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
(e) => this.registry.query_gate(e.name)(e)
|
|
3530
|
-
)
|
|
3531
|
-
}))
|
|
3532
|
-
);
|
|
3533
|
-
leased.push(...r.leased);
|
|
3534
|
-
acked.push(...r.acked);
|
|
3535
|
-
blocked.push(...r.blocked);
|
|
3536
|
-
}
|
|
3537
|
-
return { fetched, leased, acked, blocked };
|
|
3517
|
+
return {
|
|
3518
|
+
...merged,
|
|
3519
|
+
fetched: merged.fetched.map((f) => ({
|
|
3520
|
+
...f,
|
|
3521
|
+
events: f.events.map(
|
|
3522
|
+
(e) => this.registry.query_gate(e.name)(e)
|
|
3523
|
+
)
|
|
3524
|
+
}))
|
|
3525
|
+
};
|
|
3538
3526
|
}
|
|
3539
3527
|
/**
|
|
3540
3528
|
* Scans committed events from the correlation checkpoint, subscribes the
|
|
@@ -3553,16 +3541,20 @@ var Act = class {
|
|
|
3553
3541
|
* @see {@link start_correlations} for automatic periodic correlation
|
|
3554
3542
|
*/
|
|
3555
3543
|
async correlate(query = { after: -1, limit: 10 }) {
|
|
3556
|
-
const
|
|
3557
|
-
return {
|
|
3544
|
+
const pass = await this._correlate_pass(query);
|
|
3545
|
+
return {
|
|
3546
|
+
subscribed: pass.kind === "scanned" ? pass.subscribed : 0,
|
|
3547
|
+
last_id: pass.last_id
|
|
3548
|
+
};
|
|
3558
3549
|
}
|
|
3559
|
-
/**
|
|
3560
|
-
async
|
|
3561
|
-
if (!this._drain) return {
|
|
3550
|
+
/** One correlate pass; arms every lane when it found work. */
|
|
3551
|
+
async _correlate_pass(query, lease = false) {
|
|
3552
|
+
if (!this._drain) return { kind: "idle", last_id: -1 };
|
|
3562
3553
|
return this._scoped(async () => {
|
|
3563
|
-
const
|
|
3564
|
-
if (subscribed > 0 || marked > 0)
|
|
3565
|
-
|
|
3554
|
+
const pass = await this._correlate.correlate(query, lease);
|
|
3555
|
+
if (pass.kind === "scanned" && (pass.subscribed > 0 || pass.marked > 0))
|
|
3556
|
+
this._arm_all();
|
|
3557
|
+
return pass;
|
|
3566
3558
|
});
|
|
3567
3559
|
}
|
|
3568
3560
|
/**
|