@rotorsoft/act 1.23.25 → 1.23.27

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/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  sleep,
21
21
  store,
22
22
  validate
23
- } from "./chunk-ORKHOSH2.js";
23
+ } from "./chunk-UEZ7T2SX.js";
24
24
  import {
25
25
  ActorSchema,
26
26
  CausationEventSchema,
@@ -115,6 +115,27 @@ function current_version_of(deprecated_name, all_names) {
115
115
  return highest && highest.version > target.version ? highest.name : void 0;
116
116
  }
117
117
 
118
+ // src/internal/walk-streams.ts
119
+ var DEFAULT_STREAM_PAGE = 500;
120
+ async function walk_streams(store2, callback, query) {
121
+ const page_size = query?.limit ?? DEFAULT_STREAM_PAGE;
122
+ let after = query?.after;
123
+ let total = 0;
124
+ for (; ; ) {
125
+ let last;
126
+ const { count } = await store2.query_streams(
127
+ (position) => {
128
+ last = position.stream;
129
+ callback(position);
130
+ },
131
+ { ...query, after, limit: page_size }
132
+ );
133
+ total += count;
134
+ if (count < page_size) return total;
135
+ after = last;
136
+ }
137
+ }
138
+
118
139
  // src/internal/audit.ts
119
140
  var DEFAULTS = {
120
141
  idle_days: 90,
@@ -145,13 +166,16 @@ async function* audit(deps, categories, options = {}) {
145
166
  const need_streams = passes.some((p) => p.on_stream !== void 0);
146
167
  const need_events = passes.some((p) => p.on_event !== void 0);
147
168
  if (need_stats) {
148
- const stats = await deps.store().query_stats({}, { count: true, names: true });
169
+ const stats = await deps.store().query_stats(
170
+ {},
171
+ { count: true, names: true, exclude: [SNAP_EVENT] }
172
+ );
149
173
  for (const [stream, s] of stats) {
150
174
  for (const p of passes) p.on_stat?.(stream, s);
151
175
  }
152
176
  }
153
177
  if (need_streams) {
154
- await deps.store().query_streams((pos) => {
178
+ await walk_streams(deps.store(), (pos) => {
155
179
  for (const p of passes) p.on_stream?.(pos);
156
180
  });
157
181
  }
@@ -285,23 +309,38 @@ var make_close_candidate_pass = (deps, options) => {
285
309
  };
286
310
  var make_restart_candidate_pass = (deps, options) => {
287
311
  const threshold = options.thresholds?.restart_min ?? DEFAULTS.restart_min;
312
+ const candidates = [];
288
313
  const findings = [];
289
314
  return {
290
315
  category: "restart-candidate",
291
- on_stat(stream, { head, count, names }) {
316
+ on_stat(stream, { head, count }) {
292
317
  if (count < threshold) return;
293
318
  const head_name = String(head.name);
294
319
  if (head_name.startsWith("__")) return;
295
320
  if (!restart_is_supported(deps, head_name)) return;
296
- findings.push({
297
- category: "restart-candidate",
298
- stream,
299
- count,
300
- // names map is sparse — `__snapshot__` key absent when the
301
- // stream has never been snapshotted (a common case for the
302
- // restart-candidate signal).
303
- snaps: names.__snapshot__ ?? 0
304
- });
321
+ candidates.push({ stream, count });
322
+ },
323
+ async finalize(deps2) {
324
+ for (const { stream, count } of candidates) {
325
+ let snaps = 0;
326
+ await deps2.store().query(
327
+ () => {
328
+ snaps++;
329
+ },
330
+ {
331
+ stream,
332
+ stream_exact: true,
333
+ names: [SNAP_EVENT],
334
+ with_snaps: true
335
+ }
336
+ );
337
+ findings.push({
338
+ category: "restart-candidate",
339
+ stream,
340
+ count,
341
+ snaps
342
+ });
343
+ }
305
344
  },
306
345
  drain: () => findings
307
346
  };
@@ -356,34 +395,33 @@ var make_snapshot_drift_pass = (deps, options) => {
356
395
  const findings = [];
357
396
  return {
358
397
  category: "snapshot-drift",
359
- on_stat(stream, { head, count, names }) {
398
+ on_stat(stream, { head, count }) {
360
399
  if (!restart_is_supported(deps, String(head.name))) return;
361
400
  if (count < drift_min) return;
362
401
  candidates.push({
363
402
  stream,
364
- total: count,
365
- snaps: names.__snapshot__ ?? 0
403
+ total: count
366
404
  });
367
405
  },
368
406
  async finalize(deps2) {
369
- for (const { stream, total, snaps } of candidates) {
407
+ for (const { stream, total } of candidates) {
370
408
  let events_since_snap = total;
371
409
  let snap_at;
372
- if (snaps > 0) {
373
- const collected = [];
374
- await deps2.store().query(
375
- (e) => {
376
- collected.push({ id: e.id });
377
- },
378
- {
379
- stream,
380
- stream_exact: true,
381
- names: ["__snapshot__"],
382
- backward: true,
383
- limit: 1,
384
- with_snaps: true
385
- }
386
- );
410
+ const collected = [];
411
+ await deps2.store().query(
412
+ (e) => {
413
+ collected.push({ id: e.id });
414
+ },
415
+ {
416
+ stream,
417
+ stream_exact: true,
418
+ names: ["__snapshot__"],
419
+ backward: true,
420
+ limit: 1,
421
+ with_snaps: true
422
+ }
423
+ );
424
+ if (collected.length > 0) {
387
425
  snap_at = collected[0].id;
388
426
  let after = 0;
389
427
  await deps2.store().query(
@@ -3343,7 +3381,7 @@ var Act = class {
3343
3381
  */
3344
3382
  async _seed_persisted_defers() {
3345
3383
  const now = Date.now();
3346
- await store().query_streams((pos) => {
3384
+ await walk_streams(store(), (pos) => {
3347
3385
  if (pos.deferred_at === void 0 || pos.deferred_at <= now) return;
3348
3386
  const controller = this._drain_controllers.get(pos.lane ?? "default");
3349
3387
  controller?.seed_defer(pos.stream, pos.deferred_at);
@@ -4325,8 +4363,35 @@ function act() {
4325
4363
  const pending_projections = [];
4326
4364
  const fold_projections = [];
4327
4365
  const batch_handlers = /* @__PURE__ */ new Map();
4366
+ const fold_specs = [];
4328
4367
  const lanes = [];
4329
4368
  let _built = false;
4369
+ const pii_wrap = (original) => async (events, stream) => {
4370
+ const stripped = events.map((e) => {
4371
+ const f = _sf.get(e.name);
4372
+ return f ? pii_strip(e, f) : e;
4373
+ });
4374
+ return original(stripped, stream);
4375
+ };
4376
+ const make_batch_handlers = (patch_fn) => {
4377
+ const handlers = new Map(batch_handlers);
4378
+ for (const spec of fold_specs) {
4379
+ handlers.set(
4380
+ spec.target,
4381
+ pii_wrap(
4382
+ make_fold_handler(
4383
+ spec.merged,
4384
+ spec.flush,
4385
+ spec.config,
4386
+ patch_fn,
4387
+ // Head loads strip sensitive keys like the warm path (#1320).
4388
+ (event_name) => _sf.get(event_name) ?? []
4389
+ )
4390
+ )
4391
+ );
4392
+ }
4393
+ return handlers;
4394
+ };
4330
4395
  const finalize_deprecations = () => {
4331
4396
  const deprecation_summary = [];
4332
4397
  for (const state2 of states.values()) {
@@ -4422,19 +4487,12 @@ function act() {
4422
4487
  throw new Error(
4423
4488
  `State projection "${proj.target}" of "${fold.name}" is missing events ${missing.join(", ")} \u2014 pass every partial of the state to .of()`
4424
4489
  );
4425
- batch_handlers.set(
4426
- proj.target,
4427
- make_fold_handler(
4428
- merged,
4429
- fold.flush,
4430
- fold.config,
4431
- patch_fn,
4432
- // Head loads strip sensitive keys like the warm path (#1320).
4433
- // `_sf` is populated in the events pass below; read lazily at
4434
- // fold time, by when the map is complete.
4435
- (event_name) => _sf.get(event_name) ?? []
4436
- )
4437
- );
4490
+ fold_specs.push({
4491
+ target: proj.target,
4492
+ merged,
4493
+ flush: fold.flush,
4494
+ config: fold.config
4495
+ });
4438
4496
  }
4439
4497
  finalize_deprecations();
4440
4498
  validate_lane_references(registry, lanes);
@@ -4485,14 +4543,7 @@ function act() {
4485
4543
  };
4486
4544
  }
4487
4545
  for (const [target, original] of batch_handlers) {
4488
- const wrapped = async (events, stream) => {
4489
- const stripped = events.map((e) => {
4490
- const f = _sf.get(e.name);
4491
- return f ? pii_strip(e, f) : e;
4492
- });
4493
- return original(stripped, stream);
4494
- };
4495
- batch_handlers.set(target, wrapped);
4546
+ batch_handlers.set(target, pii_wrap(original));
4496
4547
  }
4497
4548
  synthesize_autoclose_reactions(
4498
4549
  registry,
@@ -4507,7 +4558,7 @@ function act() {
4507
4558
  return new Act(
4508
4559
  registry,
4509
4560
  states,
4510
- batch_handlers,
4561
+ make_batch_handlers(patch_fn),
4511
4562
  options,
4512
4563
  lanes,
4513
4564
  patch_fn