@rotorsoft/act 1.32.21 → 1.32.23

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.
Files changed (33) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/@types/act.d.ts +1 -2
  3. package/dist/@types/act.d.ts.map +1 -1
  4. package/dist/@types/adapters/in-memory-store.d.ts +18 -16
  5. package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
  6. package/dist/@types/builders/act-builder.d.ts.map +1 -1
  7. package/dist/@types/internal/audit.d.ts +1 -4
  8. package/dist/@types/internal/audit.d.ts.map +1 -1
  9. package/dist/@types/internal/config.d.ts +3 -9
  10. package/dist/@types/internal/config.d.ts.map +1 -1
  11. package/dist/@types/internal/correlate-cycle.d.ts +1 -11
  12. package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
  13. package/dist/@types/internal/defer-timer.d.ts +0 -5
  14. package/dist/@types/internal/defer-timer.d.ts.map +1 -1
  15. package/dist/@types/internal/drain-cycle.d.ts +3 -5
  16. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  17. package/dist/@types/internal/index.d.ts +1 -1
  18. package/dist/@types/internal/index.d.ts.map +1 -1
  19. package/dist/@types/types/ports.d.ts +10 -10
  20. package/dist/@types/types/ports.d.ts.map +1 -1
  21. package/dist/@types/utils.d.ts +3 -2
  22. package/dist/@types/utils.d.ts.map +1 -1
  23. package/dist/{chunk-QOSQI3CA.js → chunk-OG5O36AJ.js} +50 -141
  24. package/dist/chunk-OG5O36AJ.js.map +1 -0
  25. package/dist/index.cjs +75 -191
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.js +27 -52
  28. package/dist/index.js.map +1 -1
  29. package/dist/test/index.cjs +49 -140
  30. package/dist/test/index.cjs.map +1 -1
  31. package/dist/test/index.js +1 -1
  32. package/package.json +1 -1
  33. package/dist/chunk-QOSQI3CA.js.map +0 -1
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  sleep,
27
27
  store,
28
28
  validate
29
- } from "./chunk-QOSQI3CA.js";
29
+ } from "./chunk-OG5O36AJ.js";
30
30
  import {
31
31
  ActorSchema,
32
32
  CausationEventSchema,
@@ -926,7 +926,6 @@ function resolveSettleConfig(options) {
926
926
  return options;
927
927
  }
928
928
  var MAX_SHUTDOWN_GRACE_MS = 3e4;
929
- var DEFAULT_SHUTDOWN_GRACE_MS = DEFAULT_LEASE_MILLIS;
930
929
  var ShutdownOptionsSchema = z2.object({
931
930
  // `0` is legal and is exactly today's behavior: stop scheduling and
932
931
  // return without waiting.
@@ -1561,8 +1560,8 @@ function report_once(seen, key, message) {
1561
1560
  }
1562
1561
 
1563
1562
  // src/internal/correlate-cycle.ts
1564
- var DEFAULT_COLD_START_BACK_SCAN = 1e4;
1565
- var DEFAULT_CORRELATION_LEASE_MS = 5e3;
1563
+ var COLD_START_BACK_SCAN = 1e4;
1564
+ var CORRELATION_LEASE_MS = 5e3;
1566
1565
  var registry_key = (events) => {
1567
1566
  const shape = Object.keys(events).filter((name) => events[name].reactions.size > 0).sort().map((name) => [name, [...events[name].reactions.keys()].sort()]);
1568
1567
  return createHash("sha256").update(JSON.stringify(shape)).digest("hex").slice(0, 32);
@@ -1591,8 +1590,6 @@ var CorrelateCycle = class {
1591
1590
  * same holder and a restarted process never inherits a stale claim.
1592
1591
  */
1593
1592
  _by = randomUUID();
1594
- /** How long the correlation lease is taken for. */
1595
- _lease_millis;
1596
1593
  /**
1597
1594
  * Which correlator this is. Computed once from the registry so identical
1598
1595
  * workers share a lease and unrelated applications never do.
@@ -1645,12 +1642,6 @@ var CorrelateCycle = class {
1645
1642
  * here, so an idle deferred stream re-arms across a restart.
1646
1643
  */
1647
1644
  _on_init_async;
1648
- /**
1649
- * Tail re-scan window applied to the cold-start checkpoint.
1650
- * See {@link DEFAULT_COLD_START_BACK_SCAN}. Constructor arg (not a
1651
- * public option) so tests can shrink it; defaults otherwise.
1652
- */
1653
- _cold_start_back_scan;
1654
1645
  /** Lanes a controller exists for. See {@link CorrelateCycleDeps}. */
1655
1646
  _declared_lanes;
1656
1647
  /**
@@ -1667,11 +1658,8 @@ var CorrelateCycle = class {
1667
1658
  declared_lanes,
1668
1659
  shard,
1669
1660
  on_init,
1670
- on_init_async,
1671
- cold_start_back_scan = DEFAULT_COLD_START_BACK_SCAN,
1672
- lease_millis = DEFAULT_CORRELATION_LEASE_MS
1661
+ on_init_async
1673
1662
  }) {
1674
- this._lease_millis = lease_millis;
1675
1663
  this._key = shard ? `${registry_key(registry.events)}:${[...shard].sort().join(",")}` : registry_key(registry.events);
1676
1664
  this._dynamic_subscriptions = new LruMap(max_subscribed_streams);
1677
1665
  this._registry = registry;
@@ -1680,7 +1668,6 @@ var CorrelateCycle = class {
1680
1668
  this._cd = cd;
1681
1669
  this._on_init = on_init;
1682
1670
  this._on_init_async = on_init_async;
1683
- this._cold_start_back_scan = cold_start_back_scan;
1684
1671
  }
1685
1672
  /** Last correlated event id. */
1686
1673
  get checkpoint() {
@@ -1719,7 +1706,7 @@ var CorrelateCycle = class {
1719
1706
  const { watermark, correlated_at } = await this._cd.subscribe([
1720
1707
  ...this._static_targets
1721
1708
  ]);
1722
- this._checkpoint = correlated_at >= 0 ? correlated_at : Math.max(-1, watermark - this._cold_start_back_scan);
1709
+ this._checkpoint = correlated_at >= 0 ? correlated_at : Math.max(-1, watermark - COLD_START_BACK_SCAN);
1723
1710
  this._on_init?.();
1724
1711
  for (const { stream, priority = 0, lane } of this._static_targets) {
1725
1712
  this._static_subscriptions.set(stream, {
@@ -1793,13 +1780,13 @@ var CorrelateCycle = class {
1793
1780
  scanned: false
1794
1781
  };
1795
1782
  const now = Date.now();
1796
- if (lease && now >= this._lease_until - this._lease_millis / 2) {
1783
+ if (lease && now >= this._lease_until - CORRELATION_LEASE_MS / 2) {
1797
1784
  const { correlating } = await this._cd.subscribe([], void 0, {
1798
1785
  key: this._key,
1799
1786
  by: this._by,
1800
- millis: this._lease_millis
1787
+ millis: CORRELATION_LEASE_MS
1801
1788
  });
1802
- this._lease_until = correlating ? now + this._lease_millis : 0;
1789
+ this._lease_until = correlating ? now + CORRELATION_LEASE_MS : 0;
1803
1790
  if (correlating === false)
1804
1791
  return {
1805
1792
  subscribed: 0,
@@ -1890,10 +1877,10 @@ var CorrelateCycle = class {
1890
1877
  const { subscribed, correlating } = await this._cd.subscribe(
1891
1878
  streams,
1892
1879
  last_id,
1893
- lease ? { key: this._key, by: this._by, millis: this._lease_millis } : void 0
1880
+ lease ? { key: this._key, by: this._by, millis: CORRELATION_LEASE_MS } : void 0
1894
1881
  );
1895
1882
  if (lease && correlating !== false)
1896
- this._lease_until = renewed_at + this._lease_millis;
1883
+ this._lease_until = renewed_at + CORRELATION_LEASE_MS;
1897
1884
  const marked = streams.filter(
1898
1885
  (entry) => entry.correlated_at !== void 0
1899
1886
  ).length;
@@ -1973,7 +1960,7 @@ var CorrelateCycle = class {
1973
1960
  });
1974
1961
  } catch (error) {
1975
1962
  log().warn(
1976
- `Could not hand back the correlation lease during shutdown; it expires on its own within ${this._lease_millis}ms and correlation resumes normally after that. On a single-writer store this usually means another connection holds the database. Cause: ${String(error)}`
1963
+ `Could not hand back the correlation lease during shutdown; it expires on its own within ${CORRELATION_LEASE_MS}ms and correlation resumes normally after that. On a single-writer store this usually means another connection holds the database. Cause: ${String(error)}`
1977
1964
  );
1978
1965
  }
1979
1966
  }
@@ -2125,14 +2112,6 @@ var DeferTimer = class {
2125
2112
  get size() {
2126
2113
  return this._due.size;
2127
2114
  }
2128
- /**
2129
- * True while `stream` is parked with a due-time still in the future.
2130
- * Consumers skip work for deferred streams until their window elapses.
2131
- */
2132
- is_deferred = (stream) => {
2133
- const next = this._due.get(stream);
2134
- return next !== void 0 && next > Date.now();
2135
- };
2136
2115
  /**
2137
2116
  * Park `stream` for a re-visit at `at` (ms since epoch). A plain
2138
2117
  * overwrite: the caller computes the authoritative next-visit for the
@@ -2815,7 +2794,7 @@ function trace_cycle(logger, leased, fetched, handled, acked, blocked) {
2815
2794
  function budget_exhausted(lease, options, store_failing) {
2816
2795
  if (store_failing || !options?.blockOnError || lease.retry <= options.maxRetries)
2817
2796
  return void 0;
2818
- 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: raise leaseMillis for this handler, then unblock the stream.`;
2797
+ 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.`;
2819
2798
  log().error(error);
2820
2799
  return { lease, handled: 0, acked_at: lease.at, error, block: true };
2821
2800
  }
@@ -2895,7 +2874,9 @@ async function run_drain_cycle(deps, cycle) {
2895
2874
  handled: 0,
2896
2875
  acked_at: lease.at,
2897
2876
  error,
2898
- ...block2 ? { block: true } : { next_attempt_at: Date.now() + DEFAULT_BACKOFF.baseMs }
2877
+ ...block2 ? { block: true } : {
2878
+ next_attempt_at: Date.now() + compute_backoff_delay(lease.retry, DEFAULT_BACKOFF)
2879
+ }
2899
2880
  };
2900
2881
  return Promise.resolve(failed);
2901
2882
  }
@@ -3044,7 +3025,7 @@ var DrainController = class {
3044
3025
  if (this._locked) return EMPTY_DRAIN;
3045
3026
  const d = this._deps.defaults ?? {};
3046
3027
  const streamLimit = d.streamLimit ?? options.streamLimit ?? DEFAULT_STREAM_LIMIT;
3047
- const eventLimit = d.eventLimit ?? options.eventLimit ?? DEFAULT_EVENT_LIMIT;
3028
+ const eventLimit = options.eventLimit ?? DEFAULT_EVENT_LIMIT;
3048
3029
  const leaseMillis = d.leaseMillis ?? options.leaseMillis ?? DEFAULT_LEASE_MILLIS;
3049
3030
  if (this._deps.breaker.state(Date.now()) === "open")
3050
3031
  return EMPTY_DRAIN;
@@ -3708,9 +3689,7 @@ var Act = class {
3708
3689
  _build_audit_deps() {
3709
3690
  return {
3710
3691
  store,
3711
- logger: this._logger,
3712
3692
  event_to_state: this._event_to_state,
3713
- states: this._states,
3714
3693
  // Declared lanes, not this process's controllers: a lane another
3715
3694
  // worker drains is not `unknown-lane`.
3716
3695
  declared_lanes: new Set(this._declared_lanes),
@@ -3817,9 +3796,9 @@ var Act = class {
3817
3796
  * fallback, capped at the maximum. Idle lanes don't count.
3818
3797
  */
3819
3798
  _derive_grace_ms(running, settling) {
3820
- let max = settling ? DEFAULT_SHUTDOWN_GRACE_MS : 0;
3799
+ let max = settling ? DEFAULT_LEASE_MILLIS : 0;
3821
3800
  for (const c of running)
3822
- max = Math.max(max, c.lease_millis || DEFAULT_SHUTDOWN_GRACE_MS);
3801
+ max = Math.max(max, c.lease_millis || DEFAULT_LEASE_MILLIS);
3823
3802
  return Math.min(max, MAX_SHUTDOWN_GRACE_MS);
3824
3803
  }
3825
3804
  async _await_inflight(grace_ms) {
@@ -4129,8 +4108,7 @@ var Act = class {
4129
4108
  * Call `correlate()` before `drain()`. It is not only how dynamic targets
4130
4109
  * are discovered: a stream is claimable while `at < correlated_at`, and
4131
4110
  * `correlate` is the only component that raises that mark, so a
4132
- * commit no correlate has seen is not drainable — including for static
4133
- * targets, which were served by a probe of the event log before. For a
4111
+ * commit no correlate has seen is not drainable, static targets included. For a
4134
4112
  * higher-level API that handles debouncing, correlation, and signaling
4135
4113
  * automatically, use {@link settle}.
4136
4114
  *
@@ -5136,6 +5114,12 @@ function act() {
5136
5114
  };
5137
5115
  const fold_projections = [];
5138
5116
  const batch_handlers = /* @__PURE__ */ new Map();
5117
+ const add_projection = (proj) => {
5118
+ record_projection_reactions(proj);
5119
+ merge_projection(proj, registry.events);
5120
+ register_batch_handler(proj, batch_handlers);
5121
+ if (proj.fold) fold_projections.push(proj);
5122
+ };
5139
5123
  const fold_specs = [];
5140
5124
  const lanes = [];
5141
5125
  let _built = false;
@@ -5235,11 +5219,7 @@ function act() {
5235
5219
  },
5236
5220
  withProjection: (proj) => {
5237
5221
  if (_built) closed("withProjection");
5238
- record_projection_reactions(proj);
5239
- merge_projection(proj, registry.events);
5240
- register_batch_handler(proj, batch_handlers);
5241
- if (proj.fold)
5242
- fold_projections.push(proj);
5222
+ add_projection(proj);
5243
5223
  return builder;
5244
5224
  },
5245
5225
  withActor: () => builder,
@@ -5256,12 +5236,7 @@ function act() {
5256
5236
  resolveActConfig(options);
5257
5237
  const patch_fn = options?.validateFoldedState === true ? validating_patch : bare_patch;
5258
5238
  if (!_built) {
5259
- for (const proj of pending_projections) {
5260
- record_projection_reactions(proj);
5261
- merge_projection(proj, registry.events);
5262
- register_batch_handler(proj, batch_handlers);
5263
- if (proj.fold) fold_projections.push(proj);
5264
- }
5239
+ for (const proj of pending_projections) add_projection(proj);
5265
5240
  for (const proj of fold_projections) {
5266
5241
  const fold = proj.fold;
5267
5242
  const merged = states.get(fold.name);