@rotorsoft/act 1.32.17 → 1.32.19

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 (32) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/@types/builders/builder-base.d.ts +1 -1
  3. package/dist/@types/builders/builder-base.d.ts.map +1 -1
  4. package/dist/@types/builders/reaction-builder.d.ts.map +1 -1
  5. package/dist/@types/internal/autoclose-reaction.d.ts +0 -8
  6. package/dist/@types/internal/autoclose-reaction.d.ts.map +1 -1
  7. package/dist/@types/internal/config.d.ts +6 -6
  8. package/dist/@types/internal/config.d.ts.map +1 -1
  9. package/dist/@types/internal/defer-timer.d.ts +6 -12
  10. package/dist/@types/internal/defer-timer.d.ts.map +1 -1
  11. package/dist/@types/internal/drain-cycle.d.ts +6 -44
  12. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  13. package/dist/@types/internal/event-sourcing.d.ts +2 -1
  14. package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
  15. package/dist/@types/internal/index.d.ts +1 -1
  16. package/dist/@types/internal/index.d.ts.map +1 -1
  17. package/dist/@types/internal/sensitive.d.ts +0 -21
  18. package/dist/@types/internal/sensitive.d.ts.map +1 -1
  19. package/dist/@types/types/reaction.d.ts +3 -3
  20. package/dist/{chunk-PZP5ZEZ4.js → chunk-QOSQI3CA.js} +2 -2
  21. package/dist/{chunk-JRTZGWVS.js → chunk-XSG2NW4J.js} +1 -1
  22. package/dist/{chunk-JRTZGWVS.js.map → chunk-XSG2NW4J.js.map} +1 -1
  23. package/dist/index.cjs +19 -19
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +21 -21
  26. package/dist/index.js.map +1 -1
  27. package/dist/test/index.cjs.map +1 -1
  28. package/dist/test/index.js +2 -2
  29. package/dist/types/index.cjs.map +1 -1
  30. package/dist/types/index.js +1 -1
  31. package/package.json +1 -1
  32. /package/dist/{chunk-PZP5ZEZ4.js.map → chunk-QOSQI3CA.js.map} +0 -0
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  sleep,
27
27
  store,
28
28
  validate
29
- } from "./chunk-PZP5ZEZ4.js";
29
+ } from "./chunk-QOSQI3CA.js";
30
30
  import {
31
31
  ActorSchema,
32
32
  CausationEventSchema,
@@ -53,7 +53,7 @@ import {
53
53
  pii_split,
54
54
  pii_strip,
55
55
  sensitive
56
- } from "./chunk-JRTZGWVS.js";
56
+ } from "./chunk-XSG2NW4J.js";
57
57
 
58
58
  // src/signals.ts
59
59
  process.once("SIGINT", async (arg) => {
@@ -859,6 +859,10 @@ var BackoffOptionsSchema = z2.object({
859
859
  maxMs: z2.number().gt(0).optional(),
860
860
  jitter: z2.boolean().optional()
861
861
  });
862
+ var DEFAULT_BACKOFF = {
863
+ strategy: "fixed",
864
+ baseMs: 1e4
865
+ };
862
866
  var DEFAULT_MAX_RETRIES = 3;
863
867
  var DEFAULT_BLOCK_ON_ERROR = true;
864
868
  var ReactionOptionsSchema = z2.object({
@@ -2063,9 +2067,8 @@ var DeferTimer = class {
2063
2067
  _on_wake;
2064
2068
  /**
2065
2069
  * @param on_wake - invoked once each time the earliest due-time elapses,
2066
- * after the come-due entries have been removed. Consumers use it to
2067
- * re-arm their loop (the drain sets its `armed` flag; autoclose runs a
2068
- * tick).
2070
+ * after the come-due entries have been removed. The consumer re-schedules
2071
+ * for whatever is still parked.
2069
2072
  */
2070
2073
  constructor(on_wake) {
2071
2074
  this._on_wake = on_wake;
@@ -2118,14 +2121,9 @@ var DeferTimer = class {
2118
2121
  this._timer = setTimeout(() => {
2119
2122
  this._timer = void 0;
2120
2123
  const now = Date.now();
2121
- let came_due = false;
2122
2124
  for (const [stream, at] of this._due)
2123
- if (at <= now) {
2124
- this._due.delete(stream);
2125
- came_due = true;
2126
- }
2125
+ if (at <= now) this._due.delete(stream);
2127
2126
  this._on_wake();
2128
- if (!came_due && this._due.size > 0) this.schedule();
2129
2127
  }, delay);
2130
2128
  this._timer.unref();
2131
2129
  }
@@ -2842,7 +2840,7 @@ async function run_drain_cycle(deps, cycle) {
2842
2840
  handled: 0,
2843
2841
  acked_at: lease.at,
2844
2842
  error,
2845
- ...block2 ? { block: true } : {}
2843
+ ...block2 ? { block: true } : { next_attempt_at: Date.now() + DEFAULT_BACKOFF.baseMs }
2846
2844
  };
2847
2845
  return Promise.resolve(failed);
2848
2846
  }
@@ -2890,11 +2888,15 @@ var DrainController = class {
2890
2888
  _ratio = 0.5;
2891
2889
  /**
2892
2890
  * Local wake for streams this worker parked (backoff or defer). The
2893
- * schedule itself is persisted in the store; this only re-arms the drain
2894
- * at the earliest pending visit.
2891
+ * schedule itself is persisted in the store; this runs the drain at the
2892
+ * earliest pending visit. A parked stream already carries its mark, so
2893
+ * the drain alone finds it, and on an idle app nothing else would.
2894
+ * `stop()` cancels the timer and a stopped drain never re-schedules it,
2895
+ * so a wake never runs after a stop.
2895
2896
  */
2896
2897
  _defer = new DeferTimer(() => {
2897
2898
  this._armed = true;
2899
+ void this._deps.run_scoped(() => this.drain());
2898
2900
  });
2899
2901
  /** Worker timer. Set when `start()` is active, undefined otherwise. */
2900
2902
  _worker;
@@ -2982,13 +2984,13 @@ var DrainController = class {
2982
2984
  async drain(options = {}) {
2983
2985
  if (!this._armed) return EMPTY_DRAIN;
2984
2986
  if (this._locked) return EMPTY_DRAIN;
2985
- if (this._deps.breaker.state(Date.now()) === "open")
2986
- return EMPTY_DRAIN;
2987
2987
  const d = this._deps.defaults ?? {};
2988
2988
  const streamLimit = d.streamLimit ?? options.streamLimit ?? DEFAULT_STREAM_LIMIT;
2989
2989
  const eventLimit = d.eventLimit ?? options.eventLimit ?? DEFAULT_EVENT_LIMIT;
2990
2990
  const leaseMillis = d.leaseMillis ?? options.leaseMillis ?? DEFAULT_LEASE_MILLIS;
2991
2991
  try {
2992
+ if (this._deps.breaker.state(Date.now()) === "open")
2993
+ return EMPTY_DRAIN;
2992
2994
  this._locked = true;
2993
2995
  this._inflight = new Promise((done) => {
2994
2996
  this._inflight_done = done;
@@ -3006,7 +3008,6 @@ var DrainController = class {
3006
3008
  if (!cycle) {
3007
3009
  this._deps.breaker.passed();
3008
3010
  this._armed = false;
3009
- if (this._defer.size > 0) this._defer.schedule();
3010
3011
  return EMPTY_DRAIN;
3011
3012
  }
3012
3013
  const { leased, fetched, handled, acked, blocked, closeable } = cycle;
@@ -3015,11 +3016,9 @@ var DrainController = class {
3015
3016
  for (const lease of acked) this._defer.delete(lease.stream);
3016
3017
  for (const lease of blocked) this._defer.delete(lease.stream);
3017
3018
  for (const h of handled) {
3018
- const retry_at = h.error && !h.block ? h.next_attempt_at ?? Date.now() + leaseMillis : void 0;
3019
- const next = h.defer ?? retry_at;
3019
+ const next = h.defer ?? h.next_attempt_at;
3020
3020
  if (next !== void 0) this._defer.set(h.lease.stream, next);
3021
3021
  }
3022
- if (this._defer.size > 0) this._defer.schedule();
3023
3022
  if (acked.length) this._deps.on_acked(acked);
3024
3023
  if (closeable.length) await this._deps.on_close(closeable);
3025
3024
  this._deps.breaker.passed();
@@ -3030,6 +3029,7 @@ var DrainController = class {
3030
3029
  this._deps.breaker.failed(Date.now(), error);
3031
3030
  return EMPTY_DRAIN;
3032
3031
  } finally {
3032
+ if (!this._stopped) this._defer.schedule();
3033
3033
  this._locked = false;
3034
3034
  this._inflight = void 0;
3035
3035
  this._inflight_done?.();
@@ -3235,7 +3235,7 @@ function finalize(lease, handled, at, error, options, logger, failed_at) {
3235
3235
  logger.error(
3236
3236
  non_retryable ? `Blocking ${lease.stream} on non-retryable error.` : `Blocking ${lease.stream} after ${lease.retry} retries.`
3237
3237
  );
3238
- const next_attempt_at = !block2 && options.backoff ? Date.now() + compute_backoff_delay(lease.retry, options.backoff) : void 0;
3238
+ const next_attempt_at = block2 ? void 0 : Date.now() + compute_backoff_delay(lease.retry, options.backoff ?? DEFAULT_BACKOFF);
3239
3239
  return {
3240
3240
  lease,
3241
3241
  handled,