@rotorsoft/act 1.33.6 → 1.33.8
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 +0 -8
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/builders/builder-utils.d.ts +18 -6
- package/dist/@types/builders/builder-utils.d.ts.map +1 -1
- package/dist/@types/builders/projection-builder.d.ts.map +1 -1
- package/dist/@types/internal/correlate-cycle.d.ts +3 -5
- package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
- package/dist/@types/internal/drain-cycle.d.ts +0 -1
- package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
- package/dist/@types/internal/reaction-dispatch.d.ts.map +1 -1
- package/dist/index.cjs +180 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +105 -100
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1174,8 +1174,6 @@ var CorrelateCycle = class {
|
|
|
1174
1174
|
_static_targets;
|
|
1175
1175
|
_cd;
|
|
1176
1176
|
_on_init;
|
|
1177
|
-
/** Runs once after `on_init`; re-seeds defer timers across a restart. */
|
|
1178
|
-
_on_init_async;
|
|
1179
1177
|
_declared_lanes;
|
|
1180
1178
|
/** Report-once keys; per instance because `internal/` holds no module state. */
|
|
1181
1179
|
_reported = /* @__PURE__ */ new Set();
|
|
@@ -1186,8 +1184,7 @@ var CorrelateCycle = class {
|
|
|
1186
1184
|
max_subscribed_streams,
|
|
1187
1185
|
declared_lanes,
|
|
1188
1186
|
shard,
|
|
1189
|
-
on_init
|
|
1190
|
-
on_init_async
|
|
1187
|
+
on_init
|
|
1191
1188
|
}) {
|
|
1192
1189
|
this._key = shard ? `${registry_key(registry.events)}:${[...shard].sort().join(",")}` : registry_key(registry.events);
|
|
1193
1190
|
this._dynamic_subscriptions = new LruMap(max_subscribed_streams);
|
|
@@ -1196,7 +1193,6 @@ var CorrelateCycle = class {
|
|
|
1196
1193
|
this._static_targets = static_targets;
|
|
1197
1194
|
this._cd = cd;
|
|
1198
1195
|
this._on_init = on_init;
|
|
1199
|
-
this._on_init_async = on_init_async;
|
|
1200
1196
|
}
|
|
1201
1197
|
get checkpoint() {
|
|
1202
1198
|
return this._checkpoint;
|
|
@@ -1221,7 +1217,6 @@ var CorrelateCycle = class {
|
|
|
1221
1217
|
...this._static_targets
|
|
1222
1218
|
]);
|
|
1223
1219
|
this._checkpoint = correlated_at >= 0 ? correlated_at : Math.max(-1, watermark - COLD_START_BACK_SCAN);
|
|
1224
|
-
this._on_init?.();
|
|
1225
1220
|
for (const { stream, priority = 0, lane } of this._static_targets) {
|
|
1226
1221
|
this._static_subscriptions.set(stream, {
|
|
1227
1222
|
floor: Number.POSITIVE_INFINITY,
|
|
@@ -1229,7 +1224,7 @@ var CorrelateCycle = class {
|
|
|
1229
1224
|
lane
|
|
1230
1225
|
});
|
|
1231
1226
|
}
|
|
1232
|
-
await this.
|
|
1227
|
+
await this._on_init?.();
|
|
1233
1228
|
}
|
|
1234
1229
|
/** After `restore` replaced the log: forget everything and cold-start again. */
|
|
1235
1230
|
restart() {
|
|
@@ -2354,7 +2349,6 @@ var EMPTY_DRAIN = {
|
|
|
2354
2349
|
var RETRY = "";
|
|
2355
2350
|
var DrainController = class {
|
|
2356
2351
|
_armed = false;
|
|
2357
|
-
_locked = false;
|
|
2358
2352
|
_ratio = 0.5;
|
|
2359
2353
|
/**
|
|
2360
2354
|
* Local wake at the earliest parked (backoff or defer) visit, or at the
|
|
@@ -2422,8 +2416,8 @@ var DrainController = class {
|
|
|
2422
2416
|
this._defer.stop();
|
|
2423
2417
|
}
|
|
2424
2418
|
async drain(options = {}) {
|
|
2425
|
-
if (!this._armed || this._stopped
|
|
2426
|
-
|
|
2419
|
+
if (!this._armed || this._stopped || this._inflight)
|
|
2420
|
+
return EMPTY_DRAIN;
|
|
2427
2421
|
const d = this._deps.defaults ?? {};
|
|
2428
2422
|
const streamLimit = d.streamLimit ?? options.streamLimit ?? DEFAULT_STREAM_LIMIT;
|
|
2429
2423
|
const eventLimit = options.eventLimit ?? DEFAULT_EVENT_LIMIT;
|
|
@@ -2431,7 +2425,6 @@ var DrainController = class {
|
|
|
2431
2425
|
if (this._deps.breaker.state(Date.now()) === "open")
|
|
2432
2426
|
return EMPTY_DRAIN;
|
|
2433
2427
|
try {
|
|
2434
|
-
this._locked = true;
|
|
2435
2428
|
this._inflight = new Promise((done) => {
|
|
2436
2429
|
this._inflight_done = done;
|
|
2437
2430
|
});
|
|
@@ -2474,7 +2467,6 @@ var DrainController = class {
|
|
|
2474
2467
|
return EMPTY_DRAIN;
|
|
2475
2468
|
} finally {
|
|
2476
2469
|
if (!this._stopped) this._defer.schedule();
|
|
2477
|
-
this._locked = false;
|
|
2478
2470
|
this._inflight = void 0;
|
|
2479
2471
|
this._inflight_done?.();
|
|
2480
2472
|
this._inflight_done = void 0;
|
|
@@ -2716,13 +2708,23 @@ function build_handle(deps) {
|
|
|
2716
2708
|
handled++;
|
|
2717
2709
|
}
|
|
2718
2710
|
} catch (error) {
|
|
2719
|
-
if (error instanceof DeferSignal)
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2711
|
+
if (error instanceof DeferSignal) {
|
|
2712
|
+
let defer;
|
|
2713
|
+
try {
|
|
2714
|
+
defer = resolve_defer_at(error.when, event);
|
|
2715
|
+
} catch (invalid) {
|
|
2716
|
+
return finalize(
|
|
2717
|
+
lease,
|
|
2718
|
+
handled,
|
|
2719
|
+
at,
|
|
2720
|
+
invalid,
|
|
2721
|
+
payload.options,
|
|
2722
|
+
logger,
|
|
2723
|
+
event.id
|
|
2724
|
+
);
|
|
2725
|
+
}
|
|
2726
|
+
return { lease, handled, acked_at: at, defer };
|
|
2727
|
+
}
|
|
2726
2728
|
if (error instanceof CloseSignal)
|
|
2727
2729
|
return {
|
|
2728
2730
|
lease,
|
|
@@ -2908,7 +2910,6 @@ function validate_only_lanes(options, lanes) {
|
|
|
2908
2910
|
var Act = class {
|
|
2909
2911
|
_emitter = new EventEmitter();
|
|
2910
2912
|
_breaker;
|
|
2911
|
-
_listen;
|
|
2912
2913
|
_drain;
|
|
2913
2914
|
_auto_settle;
|
|
2914
2915
|
/** Whether any event has a reaction; nothing arms without one. */
|
|
@@ -2989,14 +2990,6 @@ var Act = class {
|
|
|
2989
2990
|
/** Runs a body so internal `store()`/`cache()` calls resolve to `_ports`. */
|
|
2990
2991
|
_scoped;
|
|
2991
2992
|
_correlator;
|
|
2992
|
-
// Bound once, reused by every reaction payload.
|
|
2993
|
-
_bound_do = this.do.bind(this);
|
|
2994
|
-
_bound_load = this.load.bind(this);
|
|
2995
|
-
_bound_query = this.query.bind(this);
|
|
2996
|
-
_bound_query_array = this.query_array.bind(this);
|
|
2997
|
-
_bound_forget = this.forget.bind(this);
|
|
2998
|
-
_handle;
|
|
2999
|
-
_handle_batch;
|
|
3000
2993
|
_lanes;
|
|
3001
2994
|
_close_lock = new CloseLock();
|
|
3002
2995
|
/** Every lane a controller can exist for: `"default"` plus each declared one. */
|
|
@@ -3030,31 +3023,38 @@ var Act = class {
|
|
|
3030
3023
|
this._correlator = options.correlator ?? default_correlator;
|
|
3031
3024
|
this._es = build_es(this._logger, this._correlator, patch_fn);
|
|
3032
3025
|
this._cd = build_drain(this._logger);
|
|
3033
|
-
|
|
3026
|
+
const handle = build_handle({
|
|
3034
3027
|
logger: this._logger,
|
|
3035
3028
|
reaction_scope: make_reaction_scope({
|
|
3036
|
-
do: this.
|
|
3037
|
-
load: this.
|
|
3038
|
-
query: this.
|
|
3039
|
-
query_array: this.
|
|
3040
|
-
forget: this.
|
|
3029
|
+
do: this.do.bind(this),
|
|
3030
|
+
load: this.load.bind(this),
|
|
3031
|
+
query: this.query.bind(this),
|
|
3032
|
+
query_array: this.query_array.bind(this),
|
|
3033
|
+
forget: this.forget.bind(this)
|
|
3041
3034
|
})
|
|
3042
3035
|
});
|
|
3043
|
-
|
|
3036
|
+
const handle_batch = build_handle_batch(this._logger);
|
|
3044
3037
|
const classification = classify_registry(this.registry, this._states);
|
|
3045
3038
|
this._reactive = classification.event_to_lanes.size > 0;
|
|
3046
3039
|
this._event_to_state = classification.event_to_state;
|
|
3047
3040
|
this._event_to_lanes = classification.event_to_lanes;
|
|
3048
|
-
this._listen = options.listen !== false;
|
|
3049
3041
|
this._drain = options.drain !== false;
|
|
3050
3042
|
this._auto_settle = options.autoSettle !== false;
|
|
3051
3043
|
this._breaker = this._build_breaker(options);
|
|
3052
|
-
this._drain_controllers = this._build_drain_controllers(
|
|
3044
|
+
this._drain_controllers = this._build_drain_controllers(
|
|
3045
|
+
options,
|
|
3046
|
+
lanes,
|
|
3047
|
+
handle,
|
|
3048
|
+
handle_batch
|
|
3049
|
+
);
|
|
3053
3050
|
this._advise_orphaned_lanes(options);
|
|
3054
3051
|
this._audit_deps = this._build_audit_deps();
|
|
3055
3052
|
this._correlate = this._build_correlate(options, classification);
|
|
3056
3053
|
this._settle = this._build_settle(options);
|
|
3057
|
-
this._notify_disposer = this._wire_notify(
|
|
3054
|
+
this._notify_disposer = this._wire_notify(
|
|
3055
|
+
this._ports.store,
|
|
3056
|
+
options.listen !== false
|
|
3057
|
+
);
|
|
3058
3058
|
register_weak_disposer(new WeakRef(this), (self) => self.shutdown());
|
|
3059
3059
|
}
|
|
3060
3060
|
/** Shared by drain, settle and autoclose; bad knobs throw at build. */
|
|
@@ -3070,7 +3070,7 @@ var Act = class {
|
|
|
3070
3070
|
);
|
|
3071
3071
|
}
|
|
3072
3072
|
/** Apps that declare no lanes pass no lane filter to `claim`. */
|
|
3073
|
-
_build_drain_controllers(options, lanes) {
|
|
3073
|
+
_build_drain_controllers(options, lanes, handle, handle_batch) {
|
|
3074
3074
|
const all_lanes = this._declared_lanes;
|
|
3075
3075
|
const only_set = options.onlyLanes && options.onlyLanes.length > 0 ? new Set(options.onlyLanes) : void 0;
|
|
3076
3076
|
const active_lanes = only_set ? all_lanes.filter((n) => only_set.has(n)) : all_lanes;
|
|
@@ -3083,8 +3083,8 @@ var Act = class {
|
|
|
3083
3083
|
ops: this._cd,
|
|
3084
3084
|
registry: this.registry,
|
|
3085
3085
|
batch_handlers: this._batch_handlers,
|
|
3086
|
-
handle
|
|
3087
|
-
handle_batch
|
|
3086
|
+
handle,
|
|
3087
|
+
handle_batch,
|
|
3088
3088
|
on_acked: (acked) => this.emit("acked", acked),
|
|
3089
3089
|
on_blocked: (blocked) => this.emit("blocked", blocked),
|
|
3090
3090
|
// Reaction-requested close: the same machinery as `app.close`.
|
|
@@ -3149,8 +3149,10 @@ var Act = class {
|
|
|
3149
3149
|
// Built after the controllers, so their keys are the active lanes.
|
|
3150
3150
|
shard: this._drain_controllers.size < this._declared_lanes.length ? [...this._drain_controllers.keys()] : void 0,
|
|
3151
3151
|
// Only reached on a draining app: writer-only ones never correlate.
|
|
3152
|
-
on_init: () =>
|
|
3153
|
-
|
|
3152
|
+
on_init: async () => {
|
|
3153
|
+
this._arm_all();
|
|
3154
|
+
await this._seed_persisted_defers();
|
|
3155
|
+
}
|
|
3154
3156
|
});
|
|
3155
3157
|
}
|
|
3156
3158
|
/** Cold start: an idle deferred stream still fires on time after a restart. */
|
|
@@ -3243,10 +3245,10 @@ var Act = class {
|
|
|
3243
3245
|
}
|
|
3244
3246
|
}
|
|
3245
3247
|
/** Failures are logged, never thrown: `notify` is a hint. */
|
|
3246
|
-
async _wire_notify(s) {
|
|
3248
|
+
async _wire_notify(s, listen) {
|
|
3247
3249
|
if (!this._reactive) return void 0;
|
|
3248
3250
|
if (!s.notify) return void 0;
|
|
3249
|
-
if (!
|
|
3251
|
+
if (!listen) return void 0;
|
|
3250
3252
|
try {
|
|
3251
3253
|
return await s.notify((notification) => {
|
|
3252
3254
|
try {
|
|
@@ -4308,37 +4310,49 @@ function register_lane(config2, lanes) {
|
|
|
4308
4310
|
`Lane "${config2.name}" was already declared with a different config`
|
|
4309
4311
|
);
|
|
4310
4312
|
}
|
|
4313
|
+
function add_reaction(events, event, name, kind, make, builder) {
|
|
4314
|
+
if (!name)
|
|
4315
|
+
throw new Error(
|
|
4316
|
+
`${kind} handler for "${String(event)}" must be a named function`
|
|
4317
|
+
);
|
|
4318
|
+
const label = kind === "Reaction" ? "reaction" : "projection handler";
|
|
4319
|
+
if (events[event].reactions.has(name))
|
|
4320
|
+
throw new Error(
|
|
4321
|
+
`Duplicate ${label} "${name}" for event "${String(event)}". ${kind} handlers are keyed by function name; rename one of them.`
|
|
4322
|
+
);
|
|
4323
|
+
const reaction = make();
|
|
4324
|
+
events[event].reactions.set(name, reaction);
|
|
4325
|
+
return Object.assign(builder, {
|
|
4326
|
+
to(resolver) {
|
|
4327
|
+
reaction.resolver = typeof resolver === "string" ? { target: resolver } : resolver;
|
|
4328
|
+
return builder;
|
|
4329
|
+
}
|
|
4330
|
+
});
|
|
4331
|
+
}
|
|
4311
4332
|
function reaction_on(event, events, builder) {
|
|
4312
|
-
const register = (handler, options, schedule) =>
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
return Object.assign(builder, {
|
|
4336
|
-
to(resolver) {
|
|
4337
|
-
reaction.resolver = typeof resolver === "string" ? { target: resolver } : resolver;
|
|
4338
|
-
return builder;
|
|
4339
|
-
}
|
|
4340
|
-
});
|
|
4341
|
-
};
|
|
4333
|
+
const register = (handler, options, schedule) => add_reaction(
|
|
4334
|
+
events,
|
|
4335
|
+
event,
|
|
4336
|
+
handler.name,
|
|
4337
|
+
"Reaction",
|
|
4338
|
+
() => {
|
|
4339
|
+
if (schedule && typeof schedule !== "function")
|
|
4340
|
+
assert_defer_when(schedule);
|
|
4341
|
+
return {
|
|
4342
|
+
handler: schedule ? make_deferred(handler, schedule) : handler,
|
|
4343
|
+
resolver: _this_,
|
|
4344
|
+
// Validate the whole bag at the declaration site so a bad
|
|
4345
|
+
// `maxRetries`/`backoff`/`blockOnError` throws ZodError at build,
|
|
4346
|
+
// not a NaN gate on the first retry.
|
|
4347
|
+
options: resolveReactionConfig({
|
|
4348
|
+
blockOnError: options?.blockOnError ?? DEFAULT_BLOCK_ON_ERROR,
|
|
4349
|
+
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,
|
|
4350
|
+
backoff: options?.backoff
|
|
4351
|
+
})
|
|
4352
|
+
};
|
|
4353
|
+
},
|
|
4354
|
+
builder
|
|
4355
|
+
);
|
|
4342
4356
|
return {
|
|
4343
4357
|
do: (handler, options) => register(handler, options),
|
|
4344
4358
|
defer: (schedule) => ({
|
|
@@ -4471,7 +4485,7 @@ function build_events(registry, states, lanes, owners) {
|
|
|
4471
4485
|
throw new Error(
|
|
4472
4486
|
`Reaction on target "${resolver.target}" conflicts with the projection that already serves it \u2014 a target is served by one batch handler or one state projection, and a reaction to it would never run`
|
|
4473
4487
|
);
|
|
4474
|
-
if (resolver.lane && !declared.has(resolver.lane))
|
|
4488
|
+
if (resolver.lane !== void 0 && !declared.has(resolver.lane))
|
|
4475
4489
|
lane_errors.push(
|
|
4476
4490
|
`Reaction "${handler_name}" on "${event_name}" targets undeclared lane "${resolver.lane}". Declared lanes: ${[...declared].map((l) => `"${l}"`).join(", ")}. Add \`.withLane({ name: "${resolver.lane}", ... })\` to act() or correct the .to() declaration.`
|
|
4477
4491
|
);
|
|
@@ -4767,31 +4781,22 @@ function _projection(target) {
|
|
|
4767
4781
|
}
|
|
4768
4782
|
return {
|
|
4769
4783
|
do: (handler) => {
|
|
4770
|
-
const reaction = {
|
|
4771
|
-
handler,
|
|
4772
|
-
resolver: default_resolver ?? _this_,
|
|
4773
|
-
options: {
|
|
4774
|
-
blockOnError: DEFAULT_BLOCK_ON_ERROR,
|
|
4775
|
-
maxRetries: DEFAULT_MAX_RETRIES
|
|
4776
|
-
}
|
|
4777
|
-
};
|
|
4778
|
-
const register = events[event];
|
|
4779
|
-
if (!handler.name)
|
|
4780
|
-
throw new Error(
|
|
4781
|
-
`Projection handler for "${event}" must be a named function`
|
|
4782
|
-
);
|
|
4783
|
-
if (register.reactions.has(handler.name))
|
|
4784
|
-
throw new Error(
|
|
4785
|
-
`Duplicate projection handler "${handler.name}" for event "${event}". Projection handlers are keyed by function name; rename one of them.`
|
|
4786
|
-
);
|
|
4787
|
-
register.reactions.set(handler.name, reaction);
|
|
4788
4784
|
const widened = base;
|
|
4789
|
-
return
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4785
|
+
return add_reaction(
|
|
4786
|
+
events,
|
|
4787
|
+
event,
|
|
4788
|
+
handler.name,
|
|
4789
|
+
"Projection",
|
|
4790
|
+
() => ({
|
|
4791
|
+
handler,
|
|
4792
|
+
resolver: default_resolver ?? _this_,
|
|
4793
|
+
options: {
|
|
4794
|
+
blockOnError: DEFAULT_BLOCK_ON_ERROR,
|
|
4795
|
+
maxRetries: DEFAULT_MAX_RETRIES
|
|
4796
|
+
}
|
|
4797
|
+
}),
|
|
4798
|
+
widened
|
|
4799
|
+
);
|
|
4795
4800
|
}
|
|
4796
4801
|
};
|
|
4797
4802
|
},
|