@rotorsoft/act 1.33.7 → 1.33.9

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.cjs CHANGED
@@ -1162,23 +1162,27 @@ var CorrelateCycle = (_class3 = class {
1162
1162
 
1163
1163
  /** Local expiry of the held lease (0 = none); stale only costs a duplicate scan. */
1164
1164
  __init6() {this._lease_until = 0}
1165
- /** Raised by a commit or notification, lowered by a short page. Starts armed. */
1166
- __init7() {this._armed = true}
1165
+ /**
1166
+ * Armed while `_raised` (bumped by a commit or notification) is ahead of
1167
+ * `_lowered` (the raise count the last short page saw). Starts armed.
1168
+ */
1169
+ __init7() {this._raised = 1}
1170
+ __init8() {this._lowered = 0}
1171
+ /** Counts releases, so a lease reply that lands after one is dropped. */
1172
+ __init9() {this._releases = 0}
1167
1173
 
1168
1174
  // Bounded by `maxSubscribedStreams`; static records live apart so eviction
1169
1175
  // never drops their +Infinity floor.
1170
1176
 
1171
- __init8() {this._static_subscriptions = /* @__PURE__ */ new Map()}
1172
- __init9() {this._patterns = new (0, _chunkO6QIJQRNcjs.LruMap)(PATTERN_CACHE_SIZE)}
1173
-
1177
+ __init10() {this._static_subscriptions = /* @__PURE__ */ new Map()}
1178
+ __init11() {this._patterns = new (0, _chunkO6QIJQRNcjs.LruMap)(PATTERN_CACHE_SIZE)}
1174
1179
 
1175
1180
 
1176
1181
 
1177
- /** Runs once after `on_init`; re-seeds defer timers across a restart. */
1178
1182
 
1179
1183
 
1180
1184
  /** Report-once keys; per instance because `internal/` holds no module state. */
1181
- __init10() {this._reported = /* @__PURE__ */ new Set()}
1185
+ __init12() {this._reported = /* @__PURE__ */ new Set()}
1182
1186
  constructor({
1183
1187
  registry,
1184
1188
  static_targets,
@@ -1186,9 +1190,8 @@ var CorrelateCycle = (_class3 = class {
1186
1190
  max_subscribed_streams,
1187
1191
  declared_lanes,
1188
1192
  shard,
1189
- on_init,
1190
- on_init_async
1191
- }) {;_class3.prototype.__init3.call(this);_class3.prototype.__init4.call(this);_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);
1193
+ on_init
1194
+ }) {;_class3.prototype.__init3.call(this);_class3.prototype.__init4.call(this);_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);
1192
1195
  this._key = shard ? `${registry_key(registry.events)}:${[...shard].sort().join(",")}` : registry_key(registry.events);
1193
1196
  this._dynamic_subscriptions = new (0, _chunkO6QIJQRNcjs.LruMap)(max_subscribed_streams);
1194
1197
  this._registry = registry;
@@ -1196,14 +1199,13 @@ var CorrelateCycle = (_class3 = class {
1196
1199
  this._static_targets = static_targets;
1197
1200
  this._cd = cd;
1198
1201
  this._on_init = on_init;
1199
- this._on_init_async = on_init_async;
1200
1202
  }
1201
1203
  get checkpoint() {
1202
1204
  return this._checkpoint;
1203
1205
  }
1204
1206
  /** A commit (local or remote) may have produced uncorrelated events. */
1205
1207
  arm() {
1206
- this._armed = true;
1208
+ this._raised++;
1207
1209
  }
1208
1210
  async init() {
1209
1211
  if (this._initialized) return;
@@ -1221,7 +1223,6 @@ var CorrelateCycle = (_class3 = class {
1221
1223
  ...this._static_targets
1222
1224
  ]);
1223
1225
  this._checkpoint = correlated_at >= 0 ? correlated_at : Math.max(-1, watermark - COLD_START_BACK_SCAN);
1224
- _optionalChain([this, 'access', _59 => _59._on_init, 'optionalCall', _60 => _60()]);
1225
1226
  for (const { stream, priority = 0, lane } of this._static_targets) {
1226
1227
  this._static_subscriptions.set(stream, {
1227
1228
  floor: Number.POSITIVE_INFINITY,
@@ -1229,7 +1230,7 @@ var CorrelateCycle = (_class3 = class {
1229
1230
  lane
1230
1231
  });
1231
1232
  }
1232
- await _optionalChain([this, 'access', _61 => _61._on_init_async, 'optionalCall', _62 => _62()]);
1233
+ await _optionalChain([this, 'access', _59 => _59._on_init, 'optionalCall', _60 => _60()]);
1233
1234
  }
1234
1235
  /** After `restore` replaced the log: forget everything and cold-start again. */
1235
1236
  restart() {
@@ -1238,7 +1239,7 @@ var CorrelateCycle = (_class3 = class {
1238
1239
  this._checkpoint = -1;
1239
1240
  this._dynamic_subscriptions.clear();
1240
1241
  this._static_subscriptions.clear();
1241
- this._armed = true;
1242
+ this._raised++;
1242
1243
  }
1243
1244
  /** Forget dynamic targets whose rows a full close deleted, so they re-subscribe. */
1244
1245
  forget_subscribed(streams) {
@@ -1258,22 +1259,26 @@ var CorrelateCycle = (_class3 = class {
1258
1259
  /** Scan past the checkpoint, subscribe new targets and raise their work marks. */
1259
1260
  async correlate(query = { after: -1, limit: 10 }, lease = false) {
1260
1261
  await this.init();
1261
- if (!this._armed)
1262
+ if (this._raised === this._lowered)
1262
1263
  return {
1263
1264
  subscribed: 0,
1264
1265
  last_id: this._checkpoint,
1265
1266
  marked: 0,
1266
1267
  scanned: false
1267
1268
  };
1269
+ const raised = this._raised;
1268
1270
  const now = Date.now();
1269
1271
  if (lease && now >= this._lease_until - CORRELATION_LEASE_MS / 2) {
1272
+ const releases = this._releases;
1270
1273
  const { correlating } = await this._cd.subscribe([], void 0, {
1271
1274
  key: this._key,
1272
1275
  by: this._by,
1273
1276
  millis: CORRELATION_LEASE_MS
1274
1277
  });
1275
- this._lease_until = correlating ? now + CORRELATION_LEASE_MS : 0;
1276
- if (correlating === false)
1278
+ const released = this._releases !== releases;
1279
+ if (!released)
1280
+ this._lease_until = correlating ? now + CORRELATION_LEASE_MS : 0;
1281
+ if (correlating === false || released)
1277
1282
  return {
1278
1283
  subscribed: 0,
1279
1284
  last_id: this._checkpoint,
@@ -1329,8 +1334,8 @@ var CorrelateCycle = (_class3 = class {
1329
1334
  correlated_at: void 0
1330
1335
  };
1331
1336
  const seen_in_scan = correlated.has(resolved.target);
1332
- const held_lane = _nullishCoalesce((seen_in_scan ? entry.lane : _optionalChain([recorded, 'optionalAccess', _63 => _63.lane])), () => ( _chunk7AHW7FCNcjs.DEFAULT_LANE));
1333
- const held_priority = seen_in_scan ? entry.priority : _optionalChain([recorded, 'optionalAccess', _64 => _64.priority]);
1337
+ const held_lane = _nullishCoalesce((seen_in_scan ? entry.lane : _optionalChain([recorded, 'optionalAccess', _61 => _61.lane])), () => ( _chunk7AHW7FCNcjs.DEFAULT_LANE));
1338
+ const held_priority = seen_in_scan ? entry.priority : _optionalChain([recorded, 'optionalAccess', _62 => _62.priority]);
1334
1339
  const resolved_lane = _nullishCoalesce(lane, () => ( _chunk7AHW7FCNcjs.DEFAULT_LANE));
1335
1340
  if (held_priority === priority && held_lane !== resolved_lane)
1336
1341
  report_lane_conflict(
@@ -1384,7 +1389,7 @@ var CorrelateCycle = (_class3 = class {
1384
1389
  ).length;
1385
1390
  this._checkpoint = last_id;
1386
1391
  for (const { stream, priority, lane } of streams) {
1387
- if (_optionalChain([correlated, 'access', _65 => _65.get, 'call', _66 => _66(stream), 'optionalAccess', _67 => _67.upgraded]))
1392
+ if (_optionalChain([correlated, 'access', _63 => _63.get, 'call', _64 => _64(stream), 'optionalAccess', _65 => _65.upgraded]))
1388
1393
  this._dynamic_subscriptions.set(stream, {
1389
1394
  floor: priority,
1390
1395
  priority,
@@ -1394,7 +1399,7 @@ var CorrelateCycle = (_class3 = class {
1394
1399
  return { subscribed, last_id, marked, scanned: true };
1395
1400
  }
1396
1401
  this._checkpoint = last_id;
1397
- this._armed = stopped || found === query.limit;
1402
+ if (!stopped && found !== query.limit) this._lowered = raised;
1398
1403
  return { subscribed: 0, last_id, marked: 0, scanned: true };
1399
1404
  }
1400
1405
  /**
@@ -1440,6 +1445,7 @@ var CorrelateCycle = (_class3 = class {
1440
1445
  async release_correlation() {
1441
1446
  try {
1442
1447
  this._lease_until = 0;
1448
+ this._releases++;
1443
1449
  await this._cd.subscribe([], void 0, {
1444
1450
  key: this._key,
1445
1451
  by: this._by,
@@ -1508,14 +1514,14 @@ function compute_backoff_delay(retry, opts) {
1508
1514
  // src/internal/defer-timer.ts
1509
1515
  var MAX_TIMER_DELAY_MS = 2147483647;
1510
1516
  var DeferTimer = (_class4 = class {
1511
- __init11() {this._due = /* @__PURE__ */ new Map()}
1517
+ __init13() {this._due = /* @__PURE__ */ new Map()}
1512
1518
 
1513
1519
 
1514
1520
  /**
1515
1521
  * @param on_wake - invoked once each time the earliest due-time elapses.
1516
1522
  * The consumer re-schedules for whatever is still parked.
1517
1523
  */
1518
- constructor(on_wake) {;_class4.prototype.__init11.call(this);
1524
+ constructor(on_wake) {;_class4.prototype.__init13.call(this);
1519
1525
  this._on_wake = on_wake;
1520
1526
  }
1521
1527
  /** Number of currently parked streams. */
@@ -1619,7 +1625,7 @@ async function fetch(leased, eventLimit) {
1619
1625
  at,
1620
1626
  lagging,
1621
1627
  events: [],
1622
- error: _nullishCoalesce(_optionalChain([error, 'optionalAccess', _68 => _68.message]), () => ( String(error)))
1628
+ error: _nullishCoalesce(_optionalChain([error, 'optionalAccess', _66 => _66.message]), () => ( String(error)))
1623
1629
  };
1624
1630
  }
1625
1631
  return { stream, source, at, lagging, events };
@@ -1748,7 +1754,7 @@ async function scan(source, opts = {}, callback) {
1748
1754
  return;
1749
1755
  }
1750
1756
  let migrated = event;
1751
- const migration = _optionalChain([event_migrations, 'optionalAccess', _69 => _69[event.name]]);
1757
+ const migration = _optionalChain([event_migrations, 'optionalAccess', _67 => _67[event.name]]);
1752
1758
  if (migration) {
1753
1759
  const old_data = migration.from_schema.parse(event.data);
1754
1760
  const new_data = migration.migrate(old_data);
@@ -1770,7 +1776,7 @@ async function scan(source, opts = {}, callback) {
1770
1776
  return;
1771
1777
  }
1772
1778
  let remapped = migrated;
1773
- const caused_by = _optionalChain([migrated, 'access', _70 => _70.meta, 'access', _71 => _71.causation, 'access', _72 => _72.event, 'optionalAccess', _73 => _73.id]);
1779
+ const caused_by = _optionalChain([migrated, 'access', _68 => _68.meta, 'access', _69 => _69.causation, 'access', _70 => _70.event, 'optionalAccess', _71 => _71.id]);
1774
1780
  if (caused_by !== void 0) {
1775
1781
  const new_caused_by = id_map.get(caused_by);
1776
1782
  if (new_caused_by !== void 0 && new_caused_by !== caused_by) {
@@ -1812,9 +1818,9 @@ async function load(me, target, callback, patch_fn = bare_patch) {
1812
1818
  const time_travel = !!asOf && Object.values(asOf).some((v) => v !== void 0);
1813
1819
  const cached = time_travel ? void 0 : await _chunkO6QIJQRNcjs.cache.call(void 0, ).get(stream);
1814
1820
  const cache_hit = !!cached;
1815
- let state2 = _nullishCoalesce(_optionalChain([cached, 'optionalAccess', _74 => _74.state]), () => ( (me.init ? me.init() : {})));
1816
- let patches = _nullishCoalesce(_optionalChain([cached, 'optionalAccess', _75 => _75.patches]), () => ( 0));
1817
- let snaps = _nullishCoalesce(_optionalChain([cached, 'optionalAccess', _76 => _76.snaps]), () => ( 0));
1821
+ let state2 = _nullishCoalesce(_optionalChain([cached, 'optionalAccess', _72 => _72.state]), () => ( (me.init ? me.init() : {})));
1822
+ let patches = _nullishCoalesce(_optionalChain([cached, 'optionalAccess', _73 => _73.patches]), () => ( 0));
1823
+ let snaps = _nullishCoalesce(_optionalChain([cached, 'optionalAccess', _74 => _74.snaps]), () => ( 0));
1818
1824
  let replayed = 0;
1819
1825
  let event;
1820
1826
  await _chunkO6QIJQRNcjs.store.call(void 0, ).query(
@@ -1834,7 +1840,7 @@ async function load(me, target, callback, patch_fn = bare_patch) {
1834
1840
  `Skipping unknown event "${String(event.name)}" on stream "${stream}" (id=${event.id}) \u2014 no reducer in state "${me.name}"`
1835
1841
  );
1836
1842
  }
1837
- _optionalChain([callback, 'optionalCall', _77 => _77({
1843
+ _optionalChain([callback, 'optionalCall', _75 => _75({
1838
1844
  event,
1839
1845
  state: state2,
1840
1846
  version: event.version,
@@ -1854,7 +1860,7 @@ async function load(me, target, callback, patch_fn = bare_patch) {
1854
1860
  ...cached ? { after: cached.event_id, with_snaps: true } : { ...time_travel ? {} : { with_snaps: true }, ...asOf }
1855
1861
  }
1856
1862
  );
1857
- const head_is_tombstone = _optionalChain([event, 'optionalAccess', _78 => _78.name]) === _chunk7AHW7FCNcjs.TOMBSTONE_EVENT;
1863
+ const head_is_tombstone = _optionalChain([event, 'optionalAccess', _76 => _76.name]) === _chunk7AHW7FCNcjs.TOMBSTONE_EVENT;
1858
1864
  if (replayed > 0 && !time_travel && event && !me.pii_aware && !head_is_tombstone) {
1859
1865
  await cache_put(stream, {
1860
1866
  stream,
@@ -1868,9 +1874,9 @@ async function load(me, target, callback, patch_fn = bare_patch) {
1868
1874
  return {
1869
1875
  event,
1870
1876
  state: state2,
1871
- version: _nullishCoalesce(_nullishCoalesce(_optionalChain([event, 'optionalAccess', _79 => _79.version]), () => ( _optionalChain([cached, 'optionalAccess', _80 => _80.version]))), () => ( -1)),
1877
+ version: _nullishCoalesce(_nullishCoalesce(_optionalChain([event, 'optionalAccess', _77 => _77.version]), () => ( _optionalChain([cached, 'optionalAccess', _78 => _78.version]))), () => ( -1)),
1872
1878
  // Captured with `state`, so consumers never race a separate cache lookup.
1873
- id: _nullishCoalesce(_nullishCoalesce(_optionalChain([event, 'optionalAccess', _81 => _81.id]), () => ( _optionalChain([cached, 'optionalAccess', _82 => _82.event_id]))), () => ( -1)),
1879
+ id: _nullishCoalesce(_nullishCoalesce(_optionalChain([event, 'optionalAccess', _79 => _79.id]), () => ( _optionalChain([cached, 'optionalAccess', _80 => _80.event_id]))), () => ( -1)),
1874
1880
  patches,
1875
1881
  snaps,
1876
1882
  cache_hit,
@@ -1880,11 +1886,11 @@ async function load(me, target, callback, patch_fn = bare_patch) {
1880
1886
  async function action(me, action2, target, payload, options, patch_fn = bare_patch) {
1881
1887
  const { stream, expectedVersion, actor } = target;
1882
1888
  if (!stream) throw new Error("Missing target stream");
1883
- const reactingTo = _optionalChain([options, 'optionalAccess', _83 => _83.reactingTo]);
1884
- const correlator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _84 => _84.correlator]), () => ( default_correlator));
1889
+ const reactingTo = _optionalChain([options, 'optionalAccess', _81 => _81.reactingTo]);
1890
+ const correlator = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _82 => _82.correlator]), () => ( default_correlator));
1885
1891
  const validated = _chunkO6QIJQRNcjs.validate.call(void 0, action2, payload, me.actions[action2]);
1886
- const opts = _optionalChain([me, 'access', _85 => _85.options, 'optionalAccess', _86 => _86[action2]]);
1887
- const max_retries = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _87 => _87.maxRetries]), () => ( 0));
1892
+ const opts = _optionalChain([me, 'access', _83 => _83.options, 'optionalAccess', _84 => _84[action2]]);
1893
+ const max_retries = _nullishCoalesce(_optionalChain([opts, 'optionalAccess', _85 => _85.maxRetries]), () => ( 0));
1888
1894
  for (let attempt = 0; ; attempt++) {
1889
1895
  try {
1890
1896
  const snapshot = await load(
@@ -1893,7 +1899,7 @@ async function action(me, action2, target, payload, options, patch_fn = bare_pat
1893
1899
  void 0,
1894
1900
  patch_fn
1895
1901
  );
1896
- if (_optionalChain([snapshot, 'access', _88 => _88.event, 'optionalAccess', _89 => _89.name]) === _chunk7AHW7FCNcjs.TOMBSTONE_EVENT)
1902
+ if (_optionalChain([snapshot, 'access', _86 => _86.event, 'optionalAccess', _87 => _87.name]) === _chunk7AHW7FCNcjs.TOMBSTONE_EVENT)
1897
1903
  throw new (0, _chunk7AHW7FCNcjs.StreamClosedError)(stream);
1898
1904
  const expected = _nullishCoalesce(expectedVersion, () => ( (snapshot.version >= 0 ? snapshot.version : void 0)));
1899
1905
  if (me.given) {
@@ -1921,7 +1927,7 @@ async function action(me, action2, target, payload, options, patch_fn = bare_pat
1921
1927
  }));
1922
1928
  const emitted = valid.map((e) => me.message(e));
1923
1929
  const meta = {
1924
- correlation: _optionalChain([reactingTo, 'optionalAccess', _90 => _90.meta, 'access', _91 => _91.correlation]) || correlator({
1930
+ correlation: _optionalChain([reactingTo, 'optionalAccess', _88 => _88.meta, 'access', _89 => _89.correlation]) || correlator({
1925
1931
  action: action2,
1926
1932
  state: me.name,
1927
1933
  stream,
@@ -1974,15 +1980,15 @@ async function action(me, action2, target, payload, options, patch_fn = bare_pat
1974
1980
  });
1975
1981
  const last = snapshots.at(-1);
1976
1982
  const contiguous = committed[0].version === snapshot.version + 1;
1977
- const snapped = contiguous && _optionalChain([me, 'access', _92 => _92.snap, 'optionalCall', _93 => _93(last)]);
1983
+ const snapped = contiguous && _optionalChain([me, 'access', _90 => _90.snap, 'optionalCall', _91 => _91(last)]);
1978
1984
  const snap_event = snapped ? await snap(last) : void 0;
1979
1985
  if (!me.pii_aware) {
1980
1986
  if (contiguous)
1981
1987
  void cache_put(stream, {
1982
1988
  stream,
1983
1989
  state: last.state,
1984
- version: _nullishCoalesce(_optionalChain([snap_event, 'optionalAccess', _94 => _94.version]), () => ( last.event.version)),
1985
- event_id: _nullishCoalesce(_optionalChain([snap_event, 'optionalAccess', _95 => _95.id]), () => ( last.event.id)),
1990
+ version: _nullishCoalesce(_optionalChain([snap_event, 'optionalAccess', _92 => _92.version]), () => ( last.event.version)),
1991
+ event_id: _nullishCoalesce(_optionalChain([snap_event, 'optionalAccess', _93 => _93.id]), () => ( last.event.id)),
1986
1992
  patches: snap_event ? 0 : last.patches,
1987
1993
  snaps: snap_event ? last.snaps + 1 : last.snaps
1988
1994
  });
@@ -1993,7 +1999,7 @@ async function action(me, action2, target, payload, options, patch_fn = bare_pat
1993
1999
  if (!(error instanceof _chunk7AHW7FCNcjs.ConcurrencyError)) throw error;
1994
2000
  if (expectedVersion !== void 0) throw error;
1995
2001
  if (attempt >= max_retries) throw error;
1996
- if (_optionalChain([opts, 'optionalAccess', _96 => _96.backoff])) {
2002
+ if (_optionalChain([opts, 'optionalAccess', _94 => _94.backoff])) {
1997
2003
  const delay_ms = compute_backoff_delay(attempt, opts.backoff);
1998
2004
  if (delay_ms > 0) await _chunkO6QIJQRNcjs.sleep.call(void 0, delay_ms);
1999
2005
  }
@@ -2048,9 +2054,9 @@ var as_of_marker = (asOf) => {
2048
2054
  return parts.length ? ` (as-of ${parts.join(" ")})` : " (as-of)";
2049
2055
  };
2050
2056
  var traced = (inner, exit, entry) => (async (...args) => {
2051
- _optionalChain([entry, 'optionalCall', _97 => _97(...args)]);
2057
+ _optionalChain([entry, 'optionalCall', _95 => _95(...args)]);
2052
2058
  const result = await inner(...args);
2053
- _optionalChain([exit, 'optionalCall', _98 => _98(result, ...args)]);
2059
+ _optionalChain([exit, 'optionalCall', _96 => _96(result, ...args)]);
2054
2060
  return result;
2055
2061
  });
2056
2062
  function build_es(logger, correlator = default_correlator, patch_fn = bare_patch) {
@@ -2135,7 +2141,7 @@ function build_drain(logger) {
2135
2141
  subscribe: logger.level !== "trace" ? subscribe : traced(subscribe, (result, streams) => {
2136
2142
  if (!result.subscribed) return;
2137
2143
  const lanes = new Set(streams.map((s) => _nullishCoalesce(s.lane, () => ( "default"))));
2138
- const uniform_lane = lanes.size === 1 ? _optionalChain([streams, 'access', _99 => _99[0], 'optionalAccess', _100 => _100.lane]) : void 0;
2144
+ const uniform_lane = lanes.size === 1 ? _optionalChain([streams, 'access', _97 => _97[0], 'optionalAccess', _98 => _98.lane]) : void 0;
2139
2145
  const data = streams.map(
2140
2146
  ({ stream, lane }) => uniform_lane || !lane || lane === "default" ? hue(C_STREAM, stream) : `${hue(C_STREAM, stream)}${dim(`[${lane}]`)}`
2141
2147
  ).join(" ");
@@ -2147,7 +2153,7 @@ function build_drain(logger) {
2147
2153
  }
2148
2154
  function trace_cycle(logger, leased, fetched, handled, acked, blocked) {
2149
2155
  if (logger.level !== "trace" || !leased.length) return;
2150
- const lane = _optionalChain([leased, 'access', _101 => _101[0], 'optionalAccess', _102 => _102.lane]);
2156
+ const lane = _optionalChain([leased, 'access', _99 => _99[0], 'optionalAccess', _100 => _100.lane]);
2151
2157
  const fetch_by_stream = new Map(fetched.map((f) => [f.stream, f]));
2152
2158
  const acked_by_stream = new Map(acked.map((a) => [a.stream, a.at]));
2153
2159
  const blocked_by_stream = new Map(blocked.map((b) => [b.stream, b.error]));
@@ -2156,8 +2162,8 @@ function trace_cycle(logger, leased, fetched, handled, acked, blocked) {
2156
2162
  );
2157
2163
  const detail = leased.map(({ stream, at, retry }) => {
2158
2164
  const f = fetch_by_stream.get(stream);
2159
- const key = _optionalChain([f, 'optionalAccess', _103 => _103.source]) ? `${hue(C_STREAM, stream)}${dim(`<-${f.source}`)}` : hue(C_STREAM, stream);
2160
- const events = _optionalChain([f, 'optionalAccess', _104 => _104.events, 'access', _105 => _105.length]) ? ` ${dim(
2165
+ const key = _optionalChain([f, 'optionalAccess', _101 => _101.source]) ? `${hue(C_STREAM, stream)}${dim(`<-${f.source}`)}` : hue(C_STREAM, stream);
2166
+ const events = _optionalChain([f, 'optionalAccess', _102 => _102.events, 'access', _103 => _103.length]) ? ` ${dim(
2161
2167
  `[${f.events.map(({ id, name }) => `#${id} ${String(name)}`).join(", ")}]`
2162
2168
  )}` : "";
2163
2169
  const acked_at = acked_by_stream.get(stream);
@@ -2185,7 +2191,7 @@ function trace_cycle(logger, leased, fetched, handled, acked, blocked) {
2185
2191
 
2186
2192
  // src/internal/drain-cycle.ts
2187
2193
  function budget_exhausted(lease, options, store_failing) {
2188
- if (store_failing || !_optionalChain([options, 'optionalAccess', _106 => _106.blockOnError]) || lease.retry <= options.maxRetries)
2194
+ if (store_failing || !_optionalChain([options, 'optionalAccess', _104 => _104.blockOnError]) || lease.retry <= options.maxRetries)
2189
2195
  return void 0;
2190
2196
  const error = `Blocking ${lease.stream} after ${lease.retry} claims with no acknowledged progress \u2014 the retry budget (${options.maxRetries}) was spent without the handler ever reporting an error. That means every attempt lost its lease before it could ack: move the reaction to a lane whose leaseMillis covers the handler, then unblock the stream.`;
2191
2197
  _chunkO6QIJQRNcjs.log.call(void 0, ).error(error);
@@ -2249,7 +2255,7 @@ async function run_drain_cycle(deps, cycle) {
2249
2255
  const fetched = await ops.fetch(leased, eventLimit);
2250
2256
  const fetch_map = /* @__PURE__ */ new Map();
2251
2257
  const fetch_window_at = fetched.reduce(
2252
- (max, { at, events }) => Math.max(max, _optionalChain([events, 'access', _107 => _107.at, 'call', _108 => _108(-1), 'optionalAccess', _109 => _109.id]) || at),
2258
+ (max, { at, events }) => Math.max(max, _optionalChain([events, 'access', _105 => _105.at, 'call', _106 => _106(-1), 'optionalAccess', _107 => _107.id]) || at),
2253
2259
  0
2254
2260
  );
2255
2261
  for (const f of fetched) {
@@ -2313,11 +2319,11 @@ async function run_drain_cycle(deps, cycle) {
2313
2319
  deps.logger
2314
2320
  )
2315
2321
  );
2316
- const at = _optionalChain([entry, 'access', _110 => _110.fetch, 'access', _111 => _111.events, 'access', _112 => _112.at, 'call', _113 => _113(-1), 'optionalAccess', _114 => _114.id]) || fetch_window_at;
2322
+ const at = _optionalChain([entry, 'access', _108 => _108.fetch, 'access', _109 => _109.events, 'access', _110 => _110.at, 'call', _111 => _111(-1), 'optionalAccess', _112 => _112.id]) || fetch_window_at;
2317
2323
  const { payloads } = entry;
2318
2324
  const exhausted = budget_exhausted(
2319
2325
  lease,
2320
- _optionalChain([payloads, 'access', _115 => _115[0], 'optionalAccess', _116 => _116.options]),
2326
+ _optionalChain([payloads, 'access', _113 => _113[0], 'optionalAccess', _114 => _114.options]),
2321
2327
  store_failing
2322
2328
  );
2323
2329
  if (exhausted) return Promise.resolve(exhausted);
@@ -2353,9 +2359,14 @@ var EMPTY_DRAIN = {
2353
2359
  };
2354
2360
  var RETRY = "";
2355
2361
  var DrainController = (_class5 = class {
2356
- __init12() {this._armed = false}
2357
- __init13() {this._locked = false}
2358
- __init14() {this._ratio = 0.5}
2362
+ /**
2363
+ * Armed while `_raised` is ahead of `_lowered` (the raise count the last
2364
+ * empty claim saw), so a claim never lowers over a raise that landed
2365
+ * during it.
2366
+ */
2367
+ __init14() {this._raised = 0}
2368
+ __init15() {this._lowered = 0}
2369
+ __init16() {this._ratio = 0.5}
2359
2370
  /**
2360
2371
  * Local wake at the earliest parked (backoff or defer) visit, or at the
2361
2372
  * lease expiry after a failed pass (the {@link RETRY} key); the schedule
@@ -2363,24 +2374,24 @@ var DrainController = (_class5 = class {
2363
2374
  * drains until a pass leases nothing or the controller stops, and an entry
2364
2375
  * stays until handled or until a later pass claims nothing.
2365
2376
  */
2366
- __init15() {this._defer = new DeferTimer(() => {
2367
- this._armed = true;
2377
+ __init17() {this._defer = new DeferTimer(() => {
2378
+ this.arm();
2368
2379
  void this._deps.run_scoped(async () => {
2369
2380
  while ((await this.drain()).leased.length > 0) ;
2370
2381
  });
2371
2382
  })}
2372
2383
 
2373
- __init16() {this._misrouted = /* @__PURE__ */ new Set()}
2374
- __init17() {this._stopped = false}
2384
+ __init18() {this._misrouted = /* @__PURE__ */ new Set()}
2385
+ __init19() {this._stopped = false}
2375
2386
  /** Never rejects; graceful shutdown waits on it. */
2376
2387
 
2377
2388
 
2378
2389
 
2379
- constructor(deps) {;_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);
2390
+ constructor(deps) {;_class5.prototype.__init14.call(this);_class5.prototype.__init15.call(this);_class5.prototype.__init16.call(this);_class5.prototype.__init17.call(this);_class5.prototype.__init18.call(this);_class5.prototype.__init19.call(this);
2380
2391
  this._deps = deps;
2381
2392
  }
2382
2393
  arm() {
2383
- this._armed = true;
2394
+ this._raised++;
2384
2395
  }
2385
2396
  /** Cold start: re-seed a persisted `deferred_at` into the local wake. */
2386
2397
  seed_defer(stream, at) {
@@ -2388,14 +2399,14 @@ var DrainController = (_class5 = class {
2388
2399
  this._defer.schedule();
2389
2400
  }
2390
2401
  get armed() {
2391
- return this._armed;
2402
+ return this._raised !== this._lowered;
2392
2403
  }
2393
2404
  get inflight() {
2394
2405
  return this._inflight;
2395
2406
  }
2396
2407
  /** This lane's configured lease, or `undefined`; the shutdown grace basis. */
2397
2408
  get lease_millis() {
2398
- return _optionalChain([this, 'access', _117 => _117._deps, 'access', _118 => _118.defaults, 'optionalAccess', _119 => _119.leaseMillis]);
2409
+ return _optionalChain([this, 'access', _115 => _115._deps, 'access', _116 => _116.defaults, 'optionalAccess', _117 => _117.leaseMillis]);
2399
2410
  }
2400
2411
  get lane() {
2401
2412
  return this._deps.lane;
@@ -2405,7 +2416,7 @@ var DrainController = (_class5 = class {
2405
2416
  if (this._worker || this._stopped) return;
2406
2417
  const run = this._deps.run_scoped;
2407
2418
  const tick = async () => {
2408
- if (this._armed) await run(() => this.drain());
2419
+ if (this.armed) await run(() => this.drain());
2409
2420
  if (this._stopped) return;
2410
2421
  this._worker = setTimeout(tick, cycleMs);
2411
2422
  this._worker.unref();
@@ -2422,8 +2433,8 @@ var DrainController = (_class5 = class {
2422
2433
  this._defer.stop();
2423
2434
  }
2424
2435
  async drain(options = {}) {
2425
- if (!this._armed || this._stopped) return EMPTY_DRAIN;
2426
- if (this._locked) return EMPTY_DRAIN;
2436
+ if (!this.armed || this._stopped || this._inflight)
2437
+ return EMPTY_DRAIN;
2427
2438
  const d = _nullishCoalesce(this._deps.defaults, () => ( {}));
2428
2439
  const streamLimit = _nullishCoalesce(_nullishCoalesce(d.streamLimit, () => ( options.streamLimit)), () => ( _chunkO6QIJQRNcjs.DEFAULT_STREAM_LIMIT));
2429
2440
  const eventLimit = _nullishCoalesce(options.eventLimit, () => ( _chunkO6QIJQRNcjs.DEFAULT_EVENT_LIMIT));
@@ -2431,13 +2442,13 @@ var DrainController = (_class5 = class {
2431
2442
  if (this._deps.breaker.state(Date.now()) === "open")
2432
2443
  return EMPTY_DRAIN;
2433
2444
  try {
2434
- this._locked = true;
2435
2445
  this._inflight = new Promise((done) => {
2436
2446
  this._inflight_done = done;
2437
2447
  });
2438
2448
  const lagging = Math.ceil(streamLimit * this._ratio);
2439
2449
  const leading = streamLimit - lagging;
2440
2450
  const started = Date.now();
2451
+ const raised = this._raised;
2441
2452
  const cycle = await run_drain_cycle(this._deps, {
2442
2453
  lagging,
2443
2454
  leading,
@@ -2449,7 +2460,7 @@ var DrainController = (_class5 = class {
2449
2460
  if (!cycle) {
2450
2461
  this._defer.prune(started);
2451
2462
  this._deps.breaker.passed();
2452
- this._armed = false;
2463
+ this._lowered = raised;
2453
2464
  return EMPTY_DRAIN;
2454
2465
  }
2455
2466
  const { leased, fetched, handled, acked, blocked, closeable } = cycle;
@@ -2474,9 +2485,8 @@ var DrainController = (_class5 = class {
2474
2485
  return EMPTY_DRAIN;
2475
2486
  } finally {
2476
2487
  if (!this._stopped) this._defer.schedule();
2477
- this._locked = false;
2478
2488
  this._inflight = void 0;
2479
- _optionalChain([this, 'access', _120 => _120._inflight_done, 'optionalCall', _121 => _121()]);
2489
+ _optionalChain([this, 'access', _118 => _118._inflight_done, 'optionalCall', _119 => _119()]);
2480
2490
  this._inflight_done = void 0;
2481
2491
  }
2482
2492
  }
@@ -2683,10 +2693,10 @@ var CloseSignal = class extends Error {
2683
2693
  constructor(opts) {
2684
2694
  super("reaction requested close");
2685
2695
  this.name = "CloseSignal";
2686
- this.stream = _optionalChain([opts, 'optionalAccess', _122 => _122.stream]);
2687
- this.archive = _optionalChain([opts, 'optionalAccess', _123 => _123.archive]);
2688
- this.at = _optionalChain([opts, 'optionalAccess', _124 => _124.at]);
2689
- this.before = _optionalChain([opts, 'optionalAccess', _125 => _125.before]);
2696
+ this.stream = _optionalChain([opts, 'optionalAccess', _120 => _120.stream]);
2697
+ this.archive = _optionalChain([opts, 'optionalAccess', _121 => _121.archive]);
2698
+ this.at = _optionalChain([opts, 'optionalAccess', _122 => _122.at]);
2699
+ this.before = _optionalChain([opts, 'optionalAccess', _123 => _123.before]);
2690
2700
  }
2691
2701
  };
2692
2702
  function build_handle(deps) {
@@ -2716,13 +2726,23 @@ function build_handle(deps) {
2716
2726
  handled++;
2717
2727
  }
2718
2728
  } catch (error) {
2719
- if (error instanceof _chunk7AHW7FCNcjs.DeferSignal)
2720
- return {
2721
- lease,
2722
- handled,
2723
- acked_at: at,
2724
- defer: resolve_defer_at(error.when, event)
2725
- };
2729
+ if (error instanceof _chunk7AHW7FCNcjs.DeferSignal) {
2730
+ let defer;
2731
+ try {
2732
+ defer = resolve_defer_at(error.when, event);
2733
+ } catch (invalid) {
2734
+ return finalize(
2735
+ lease,
2736
+ handled,
2737
+ at,
2738
+ invalid,
2739
+ payload.options,
2740
+ logger,
2741
+ event.id
2742
+ );
2743
+ }
2744
+ return { lease, handled, acked_at: at, defer };
2745
+ }
2726
2746
  if (error instanceof CloseSignal)
2727
2747
  return {
2728
2748
  lease,
@@ -2785,24 +2805,24 @@ function build_handle_batch(logger) {
2785
2805
 
2786
2806
  // src/internal/settle.ts
2787
2807
  var SettleLoop = (_class6 = class {
2788
- __init18() {this._timer = void 0}
2808
+ __init20() {this._timer = void 0}
2789
2809
  /**
2790
2810
  * The cycle in flight, set while one runs. Shutdown waits for it
2791
2811
  * (`stop()` cancels scheduling only). Never rejects.
2792
2812
  */
2793
2813
 
2794
2814
  /** A wake-up arrived while a cycle ran: run one more pass after it. */
2795
- __init19() {this._pending = false}
2815
+ __init21() {this._pending = false}
2796
2816
  /** The last caller's options, used by the next pass. */
2797
- __init20() {this._next = void 0}
2817
+ __init22() {this._next = void 0}
2798
2818
  /** When the scheduled pass fires (epoch ms). */
2799
- __init21() {this._due = 0}
2819
+ __init23() {this._due = 0}
2800
2820
  /** Set at shutdown: nothing schedules again. */
2801
- __init22() {this._stopped = false}
2821
+ __init24() {this._stopped = false}
2802
2822
 
2803
2823
  /** Debounce window applied when the caller doesn't override via `SettleOptions.debounceMs`. */
2804
2824
 
2805
- constructor(deps, default_debounce_ms) {;_class6.prototype.__init18.call(this);_class6.prototype.__init19.call(this);_class6.prototype.__init20.call(this);_class6.prototype.__init21.call(this);_class6.prototype.__init22.call(this);
2825
+ constructor(deps, default_debounce_ms) {;_class6.prototype.__init20.call(this);_class6.prototype.__init21.call(this);_class6.prototype.__init22.call(this);_class6.prototype.__init23.call(this);_class6.prototype.__init24.call(this);
2806
2826
  this._deps = deps;
2807
2827
  this._default_debounce_ms = default_debounce_ms;
2808
2828
  }
@@ -2824,7 +2844,7 @@ var SettleLoop = (_class6 = class {
2824
2844
  this._pending = true;
2825
2845
  return;
2826
2846
  }
2827
- const delay = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _126 => _126.debounceMs]), () => ( this._default_debounce_ms));
2847
+ const delay = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _124 => _124.debounceMs]), () => ( this._default_debounce_ms));
2828
2848
  const due = Date.now() + delay;
2829
2849
  if (this._timer) {
2830
2850
  if (due >= this._due) return;
@@ -2906,8 +2926,7 @@ function validate_only_lanes(options, lanes) {
2906
2926
  );
2907
2927
  }
2908
2928
  var Act = (_class7 = class {
2909
- __init23() {this._emitter = new (0, _events2.default)()}
2910
-
2929
+ __init25() {this._emitter = new (0, _events2.default)()}
2911
2930
 
2912
2931
 
2913
2932
 
@@ -2983,22 +3002,14 @@ var Act = (_class7 = class {
2983
3002
  /** Lanes to arm per event; `"all"` when a dynamic resolver hides the lane. */
2984
3003
 
2985
3004
 
2986
- __init24() {this._logger = _chunkO6QIJQRNcjs.log.call(void 0, )}
3005
+ __init26() {this._logger = _chunkO6QIJQRNcjs.log.call(void 0, )}
2987
3006
  /** This Act's ports: its own bag, or the singleton adapters. */
2988
3007
 
2989
3008
  /** Runs a body so internal `store()`/`cache()` calls resolve to `_ports`. */
2990
3009
 
2991
3010
 
2992
- // Bound once, reused by every reaction payload.
2993
- __init25() {this._bound_do = this.do.bind(this)}
2994
- __init26() {this._bound_load = this.load.bind(this)}
2995
- __init27() {this._bound_query = this.query.bind(this)}
2996
- __init28() {this._bound_query_array = this.query_array.bind(this)}
2997
- __init29() {this._bound_forget = this.forget.bind(this)}
2998
-
2999
3011
 
3000
-
3001
- __init30() {this._close_lock = new CloseLock()}
3012
+ __init27() {this._close_lock = new CloseLock()}
3002
3013
  /** Every lane a controller can exist for: `"default"` plus each declared one. */
3003
3014
 
3004
3015
  /** Drain lanes declared via `.withLane(...)`. Implicit default not included. */
@@ -3006,7 +3017,7 @@ var Act = (_class7 = class {
3006
3017
  return this._lanes;
3007
3018
  }
3008
3019
  /** Use the {@link act} builder rather than constructing directly. */
3009
- constructor(registry, states = /* @__PURE__ */ new Map(), batch_handlers = /* @__PURE__ */ new Map(), options = {}, lanes = [], patch_fn = bare_patch) {;_class7.prototype.__init23.call(this);_class7.prototype.__init24.call(this);_class7.prototype.__init25.call(this);_class7.prototype.__init26.call(this);_class7.prototype.__init27.call(this);_class7.prototype.__init28.call(this);_class7.prototype.__init29.call(this);_class7.prototype.__init30.call(this);
3020
+ constructor(registry, states = /* @__PURE__ */ new Map(), batch_handlers = /* @__PURE__ */ new Map(), options = {}, lanes = [], patch_fn = bare_patch) {;_class7.prototype.__init25.call(this);_class7.prototype.__init26.call(this);_class7.prototype.__init27.call(this);
3010
3021
  this.registry = registry;
3011
3022
  this._states = states;
3012
3023
  this._batch_handlers = batch_handlers;
@@ -3030,31 +3041,38 @@ var Act = (_class7 = class {
3030
3041
  this._correlator = _nullishCoalesce(options.correlator, () => ( default_correlator));
3031
3042
  this._es = build_es(this._logger, this._correlator, patch_fn);
3032
3043
  this._cd = build_drain(this._logger);
3033
- this._handle = build_handle({
3044
+ const handle = build_handle({
3034
3045
  logger: this._logger,
3035
3046
  reaction_scope: _chunkO6QIJQRNcjs.make_reaction_scope.call(void 0, {
3036
- do: this._bound_do,
3037
- load: this._bound_load,
3038
- query: this._bound_query,
3039
- query_array: this._bound_query_array,
3040
- forget: this._bound_forget
3047
+ do: this.do.bind(this),
3048
+ load: this.load.bind(this),
3049
+ query: this.query.bind(this),
3050
+ query_array: this.query_array.bind(this),
3051
+ forget: this.forget.bind(this)
3041
3052
  })
3042
3053
  });
3043
- this._handle_batch = build_handle_batch(this._logger);
3054
+ const handle_batch = build_handle_batch(this._logger);
3044
3055
  const classification = classify_registry(this.registry, this._states);
3045
3056
  this._reactive = classification.event_to_lanes.size > 0;
3046
3057
  this._event_to_state = classification.event_to_state;
3047
3058
  this._event_to_lanes = classification.event_to_lanes;
3048
- this._listen = options.listen !== false;
3049
3059
  this._drain = options.drain !== false;
3050
3060
  this._auto_settle = options.autoSettle !== false;
3051
3061
  this._breaker = this._build_breaker(options);
3052
- this._drain_controllers = this._build_drain_controllers(options, lanes);
3062
+ this._drain_controllers = this._build_drain_controllers(
3063
+ options,
3064
+ lanes,
3065
+ handle,
3066
+ handle_batch
3067
+ );
3053
3068
  this._advise_orphaned_lanes(options);
3054
3069
  this._audit_deps = this._build_audit_deps();
3055
3070
  this._correlate = this._build_correlate(options, classification);
3056
3071
  this._settle = this._build_settle(options);
3057
- this._notify_disposer = this._wire_notify(this._ports.store);
3072
+ this._notify_disposer = this._wire_notify(
3073
+ this._ports.store,
3074
+ options.listen !== false
3075
+ );
3058
3076
  _chunkO6QIJQRNcjs.register_weak_disposer.call(void 0, new WeakRef(this), (self) => self.shutdown());
3059
3077
  }
3060
3078
  /** Shared by drain, settle and autoclose; bad knobs throw at build. */
@@ -3070,7 +3088,7 @@ var Act = (_class7 = class {
3070
3088
  );
3071
3089
  }
3072
3090
  /** Apps that declare no lanes pass no lane filter to `claim`. */
3073
- _build_drain_controllers(options, lanes) {
3091
+ _build_drain_controllers(options, lanes, handle, handle_batch) {
3074
3092
  const all_lanes = this._declared_lanes;
3075
3093
  const only_set = options.onlyLanes && options.onlyLanes.length > 0 ? new Set(options.onlyLanes) : void 0;
3076
3094
  const active_lanes = only_set ? all_lanes.filter((n) => only_set.has(n)) : all_lanes;
@@ -3083,8 +3101,8 @@ var Act = (_class7 = class {
3083
3101
  ops: this._cd,
3084
3102
  registry: this.registry,
3085
3103
  batch_handlers: this._batch_handlers,
3086
- handle: this._handle,
3087
- handle_batch: this._handle_batch,
3104
+ handle,
3105
+ handle_batch,
3088
3106
  on_acked: (acked) => this.emit("acked", acked),
3089
3107
  on_blocked: (blocked) => this.emit("blocked", blocked),
3090
3108
  // Reaction-requested close: the same machinery as `app.close`.
@@ -3109,7 +3127,7 @@ var Act = (_class7 = class {
3109
3127
  leaseMillis: cfg.leaseMillis
3110
3128
  }
3111
3129
  });
3112
- if (_optionalChain([cfg, 'optionalAccess', _127 => _127.cycleMs]) !== void 0 && options.drain !== false)
3130
+ if (_optionalChain([cfg, 'optionalAccess', _125 => _125.cycleMs]) !== void 0 && options.drain !== false)
3113
3131
  controller.start(cfg.cycleMs);
3114
3132
  controllers.set(name, controller);
3115
3133
  }
@@ -3149,8 +3167,10 @@ var Act = (_class7 = class {
3149
3167
  // Built after the controllers, so their keys are the active lanes.
3150
3168
  shard: this._drain_controllers.size < this._declared_lanes.length ? [...this._drain_controllers.keys()] : void 0,
3151
3169
  // Only reached on a draining app: writer-only ones never correlate.
3152
- on_init: () => this._arm_all(),
3153
- on_init_async: this._drain ? () => this._seed_persisted_defers() : void 0
3170
+ on_init: async () => {
3171
+ this._arm_all();
3172
+ await this._seed_persisted_defers();
3173
+ }
3154
3174
  });
3155
3175
  }
3156
3176
  /** Cold start: an idle deferred stream still fires on time after a restart. */
@@ -3159,7 +3179,7 @@ var Act = (_class7 = class {
3159
3179
  await walk_streams(_chunkO6QIJQRNcjs.store.call(void 0, ), (pos) => {
3160
3180
  if (pos.deferred_at === void 0 || pos.deferred_at <= now) return;
3161
3181
  const controller = this._drain_controllers.get(_nullishCoalesce(pos.lane, () => ( "default")));
3162
- _optionalChain([controller, 'optionalAccess', _128 => _128.seed_defer, 'call', _129 => _129(pos.stream, pos.deferred_at)]);
3182
+ _optionalChain([controller, 'optionalAccess', _126 => _126.seed_defer, 'call', _127 => _127(pos.stream, pos.deferred_at)]);
3163
3183
  });
3164
3184
  }
3165
3185
  _build_settle(options) {
@@ -3204,7 +3224,7 @@ var Act = (_class7 = class {
3204
3224
  for (const c of this._drain_controllers.values()) c.stop();
3205
3225
  const disposer = await this._notify_disposer;
3206
3226
  if (disposer) await disposer();
3207
- await this._await_inflight(_optionalChain([options, 'optionalAccess', _130 => _130.graceMs]));
3227
+ await this._await_inflight(_optionalChain([options, 'optionalAccess', _128 => _128.graceMs]));
3208
3228
  await this._scoped(() => this._correlate.release_correlation());
3209
3229
  this._emitter.removeAllListeners();
3210
3230
  })();
@@ -3243,10 +3263,10 @@ var Act = (_class7 = class {
3243
3263
  }
3244
3264
  }
3245
3265
  /** Failures are logged, never thrown: `notify` is a hint. */
3246
- async _wire_notify(s) {
3266
+ async _wire_notify(s, listen) {
3247
3267
  if (!this._reactive) return void 0;
3248
3268
  if (!s.notify) return void 0;
3249
- if (!this._listen) return void 0;
3269
+ if (!listen) return void 0;
3250
3270
  try {
3251
3271
  return await s.notify((notification) => {
3252
3272
  try {
@@ -3299,8 +3319,8 @@ var Act = (_class7 = class {
3299
3319
  * @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}
3300
3320
  */
3301
3321
  async do(action2, target, payload, options) {
3302
- const reacting_to = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _131 => _131.reactingTo]), () => ( _chunkO6QIJQRNcjs.current_reacting.call(void 0, )));
3303
- const do_options = reacting_to === _optionalChain([options, 'optionalAccess', _132 => _132.reactingTo]) ? options : { ...options, reactingTo: reacting_to };
3322
+ const reacting_to = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _129 => _129.reactingTo]), () => ( _chunkO6QIJQRNcjs.current_reacting.call(void 0, )));
3323
+ const do_options = reacting_to === _optionalChain([options, 'optionalAccess', _130 => _130.reactingTo]) ? options : { ...options, reactingTo: reacting_to };
3304
3324
  return this._scoped(async () => {
3305
3325
  const snapshots = await this._es.action(
3306
3326
  this.registry.actions[action2],
@@ -3364,7 +3384,7 @@ var Act = (_class7 = class {
3364
3384
  const gated = this.registry.query_gate(e.name)(e);
3365
3385
  if (!first) first = gated;
3366
3386
  last = gated;
3367
- _optionalChain([callback, 'optionalCall', _133 => _133(gated)]);
3387
+ _optionalChain([callback, 'optionalCall', _131 => _131(gated)]);
3368
3388
  }, query);
3369
3389
  return { first, last, count };
3370
3390
  });
@@ -3491,7 +3511,7 @@ var Act = (_class7 = class {
3491
3511
  }
3492
3512
  if (to_arm.size === 0) return false;
3493
3513
  this._correlate.arm();
3494
- for (const lane of to_arm) _optionalChain([this, 'access', _134 => _134._drain_controllers, 'access', _135 => _135.get, 'call', _136 => _136(lane), 'optionalAccess', _137 => _137.arm, 'call', _138 => _138()]);
3514
+ for (const lane of to_arm) _optionalChain([this, 'access', _132 => _132._drain_controllers, 'access', _133 => _133.get, 'call', _134 => _134(lane), 'optionalAccess', _135 => _135.arm, 'call', _136 => _136()]);
3495
3515
  return true;
3496
3516
  }
3497
3517
  /** In parallel, so a slow lane never holds up a fast one. */
@@ -3636,7 +3656,7 @@ var Act = (_class7 = class {
3636
3656
  return this._scoped(async () => {
3637
3657
  const count = await _chunkO6QIJQRNcjs.store.call(void 0, ).reset(input);
3638
3658
  for (const handler of this._batch_handlers.values())
3639
- _optionalChain([handler, 'access', _139 => _139[FOLD_RESET], 'optionalCall', _140 => _140()]);
3659
+ _optionalChain([handler, 'access', _137 => _137[FOLD_RESET], 'optionalCall', _138 => _138()]);
3640
3660
  if (count > 0) {
3641
3661
  this._wake();
3642
3662
  }
@@ -3768,7 +3788,7 @@ var Act = (_class7 = class {
3768
3788
  (p) => {
3769
3789
  positions.push(p);
3770
3790
  },
3771
- { blocked: true, after: _optionalChain([options, 'optionalAccess', _141 => _141.after]), limit: _optionalChain([options, 'optionalAccess', _142 => _142.limit]) }
3791
+ { blocked: true, after: _optionalChain([options, 'optionalAccess', _139 => _139.after]), limit: _optionalChain([options, 'optionalAccess', _140 => _140.limit]) }
3772
3792
  );
3773
3793
  return positions;
3774
3794
  });
@@ -3964,12 +3984,12 @@ function policy_min_after_days(options) {
3964
3984
  const parsed = AutoclosePolicySchema.parse(options);
3965
3985
  const windows = [];
3966
3986
  if (parsed.after) windows.push(parsed.after.days);
3967
- if (_optionalChain([parsed, 'access', _143 => _143.or, 'optionalAccess', _144 => _144.after])) windows.push(parsed.or.after.days);
3987
+ if (_optionalChain([parsed, 'access', _141 => _141.or, 'optionalAccess', _142 => _142.after])) windows.push(parsed.or.after.days);
3968
3988
  return windows.length ? Math.min(...windows) : void 0;
3969
3989
  }
3970
3990
  function policy_keep_days(options) {
3971
3991
  const parsed = AutoclosePolicySchema.parse(options);
3972
- return _optionalChain([parsed, 'access', _145 => _145.keep, 'optionalAccess', _146 => _146.days]);
3992
+ return _optionalChain([parsed, 'access', _143 => _143.keep, 'optionalAccess', _144 => _144.days]);
3973
3993
  }
3974
3994
  function compile_autoclose_policy(options) {
3975
3995
  const parsed = AutoclosePolicySchema.parse(options);
@@ -4001,7 +4021,7 @@ function hour_in_zone(now, timeZone) {
4001
4021
  hour: "2-digit",
4002
4022
  hourCycle: "h23"
4003
4023
  }).formatToParts(now);
4004
- return Number(_optionalChain([parts, 'access', _147 => _147.find, 'call', _148 => _148((p) => p.type === "hour"), 'optionalAccess', _149 => _149.value]));
4024
+ return Number(_optionalChain([parts, 'access', _145 => _145.find, 'call', _146 => _146((p) => p.type === "hour"), 'optionalAccess', _147 => _147.value]));
4005
4025
  }
4006
4026
  function hour_in_range(hour, start, end) {
4007
4027
  return start < end ? hour >= start && hour < end : hour >= start || hour < end;
@@ -4099,7 +4119,7 @@ function synthesize_autoclose_reactions(registry, states, read_window) {
4099
4119
  };
4100
4120
  const key = `__autoclose_${st.name}`;
4101
4121
  for (const event_name of Object.keys(st.events)) {
4102
- _optionalChain([registry, 'access', _150 => _150.events, 'access', _151 => _151[event_name], 'optionalAccess', _152 => _152.reactions, 'access', _153 => _153.set, 'call', _154 => _154(
4122
+ _optionalChain([registry, 'access', _148 => _148.events, 'access', _149 => _149[event_name], 'optionalAccess', _150 => _150.reactions, 'access', _151 => _151.set, 'call', _152 => _152(
4103
4123
  key,
4104
4124
  reaction
4105
4125
  )]);
@@ -4343,9 +4363,9 @@ function reaction_on(event, events, builder) {
4343
4363
  // `maxRetries`/`backoff`/`blockOnError` throws ZodError at build,
4344
4364
  // not a NaN gate on the first retry.
4345
4365
  options: _chunkO6QIJQRNcjs.resolveReactionConfig.call(void 0, {
4346
- blockOnError: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _155 => _155.blockOnError]), () => ( _chunkO6QIJQRNcjs.DEFAULT_BLOCK_ON_ERROR)),
4347
- maxRetries: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _156 => _156.maxRetries]), () => ( _chunkO6QIJQRNcjs.DEFAULT_MAX_RETRIES)),
4348
- backoff: _optionalChain([options, 'optionalAccess', _157 => _157.backoff])
4366
+ blockOnError: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _153 => _153.blockOnError]), () => ( _chunkO6QIJQRNcjs.DEFAULT_BLOCK_ON_ERROR)),
4367
+ maxRetries: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _154 => _154.maxRetries]), () => ( _chunkO6QIJQRNcjs.DEFAULT_MAX_RETRIES)),
4368
+ backoff: _optionalChain([options, 'optionalAccess', _155 => _155.backoff])
4349
4369
  })
4350
4370
  };
4351
4371
  },
@@ -4364,9 +4384,9 @@ function reaction_on(event, events, builder) {
4364
4384
 
4365
4385
  // src/internal/date-reviver.ts
4366
4386
 
4367
- var def_of = (schema) => _nullishCoalesce(_optionalChain([schema, 'access', _158 => _158._zod, 'optionalAccess', _159 => _159.def]), () => ( schema.def));
4387
+ var def_of = (schema) => _nullishCoalesce(_optionalChain([schema, 'access', _156 => _156._zod, 'optionalAccess', _157 => _157.def]), () => ( schema.def));
4368
4388
  function variant_schema(schema) {
4369
- const shape = _optionalChain([def_of, 'call', _160 => _160(schema), 'optionalAccess', _161 => _161.shape]);
4389
+ const shape = _optionalChain([def_of, 'call', _158 => _158(schema), 'optionalAccess', _159 => _159.shape]);
4370
4390
  if (!shape) {
4371
4391
  const dates = date_reviver_schema(schema);
4372
4392
  return { schema: _nullishCoalesce(dates, () => ( schema)), dated: !!dates };
@@ -4414,7 +4434,7 @@ function date_reviver_schema(schema) {
4414
4434
  return variants.some((v) => v.dated) ? _zod2.z.union(variants.map((v) => v.schema)) : void 0;
4415
4435
  }
4416
4436
  case "nullable":
4417
- return _optionalChain([inner, 'call', _162 => _162(), 'optionalAccess', _163 => _163.nullable, 'call', _164 => _164()]);
4437
+ return _optionalChain([inner, 'call', _160 => _160(), 'optionalAccess', _161 => _161.nullable, 'call', _162 => _162()]);
4418
4438
  case "optional":
4419
4439
  case "nonoptional":
4420
4440
  case "readonly":
@@ -4483,7 +4503,7 @@ function build_events(registry, states, lanes, owners) {
4483
4503
  throw new Error(
4484
4504
  `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`
4485
4505
  );
4486
- if (resolver.lane && !declared.has(resolver.lane))
4506
+ if (resolver.lane !== void 0 && !declared.has(resolver.lane))
4487
4507
  lane_errors.push(
4488
4508
  `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.`
4489
4509
  );
@@ -4591,7 +4611,7 @@ function act() {
4591
4611
  let _built = false;
4592
4612
  const read_wrap = (original) => {
4593
4613
  const wrapped = async (events, stream) => {
4594
- const read = events.map((e) => _nullishCoalesce(_optionalChain([_hr, 'access', _165 => _165.get, 'call', _166 => _166(e.name), 'optionalCall', _167 => _167(e)]), () => ( e)));
4614
+ const read = events.map((e) => _nullishCoalesce(_optionalChain([_hr, 'access', _163 => _163.get, 'call', _164 => _164(e.name), 'optionalCall', _165 => _165(e)]), () => ( e)));
4595
4615
  return original(read, stream);
4596
4616
  };
4597
4617
  const reset = original[FOLD_RESET];
@@ -4633,7 +4653,7 @@ function act() {
4633
4653
  });
4634
4654
  }
4635
4655
  for (const [action_name, handler] of Object.entries(state2.on)) {
4636
- const static_target = _optionalChain([handler, 'optionalAccess', _168 => _168._static_emit]);
4656
+ const static_target = _optionalChain([handler, 'optionalAccess', _166 => _166._static_emit]);
4637
4657
  if (static_target && deprecated.has(static_target)) {
4638
4658
  const current = current_version_of(static_target, event_names);
4639
4659
  throw new Error(
@@ -4689,7 +4709,7 @@ function act() {
4689
4709
  },
4690
4710
  build: (options) => {
4691
4711
  _chunkO6QIJQRNcjs.resolveActConfig.call(void 0, options);
4692
- const patch_fn = _optionalChain([options, 'optionalAccess', _169 => _169.validateFoldedState]) === true ? validating_patch : bare_patch;
4712
+ const patch_fn = _optionalChain([options, 'optionalAccess', _167 => _167.validateFoldedState]) === true ? validating_patch : bare_patch;
4693
4713
  if (!_built) {
4694
4714
  for (const proj of pending_projections) add_projection(proj);
4695
4715
  for (const proj of fold_projections) {
@@ -4707,7 +4727,7 @@ function act() {
4707
4727
  `State projection "${proj.target}" of "${fold.name}" is missing events ${missing.join(", ")} \u2014 pass every partial of the state to .of()`
4708
4728
  );
4709
4729
  const claimed = fold_specs.find((s) => s.target === proj.target);
4710
- if (_optionalChain([claimed, 'optionalAccess', _170 => _170.projection]) === proj) continue;
4730
+ if (_optionalChain([claimed, 'optionalAccess', _168 => _168.projection]) === proj) continue;
4711
4731
  if (batch_handlers.has(proj.target) || claimed)
4712
4732
  throw new Error(
4713
4733
  `Duplicate projection target "${proj.target}" \u2014 a target is served by one batch handler or one state projection, never both`