@rotorsoft/act 1.31.13 → 1.31.14

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
@@ -916,6 +916,15 @@ var CircuitBreaker = class {
916
916
  this._cooldown_ms = config2.cooldownMs;
917
917
  this._hooks = hooks;
918
918
  }
919
+ /**
920
+ * True when the store has failed at least once since the last pass that
921
+ * went all the way through. The breaker can still read "closed" here: it
922
+ * only opens after several failures in a row, so this catches the first
923
+ * one, which `state()` cannot.
924
+ */
925
+ get failing() {
926
+ return this._failures > 0;
927
+ }
919
928
  /** Current state given the wall-clock `now`. */
920
929
  state(now) {
921
930
  if (this._opened_at === void 0) return "closed";
@@ -2623,10 +2632,10 @@ function trace_cycle(logger, leased, fetched, handled, acked, blocked) {
2623
2632
  }
2624
2633
 
2625
2634
  // src/internal/drain-cycle.ts
2626
- function budget_exhausted(lease, options) {
2627
- if (!options?.blockOnError || lease.retry <= options.maxRetries)
2635
+ function budget_exhausted(lease, options, store_failing) {
2636
+ if (store_failing || !options?.blockOnError || lease.retry <= options.maxRetries)
2628
2637
  return void 0;
2629
- const error = `Blocking ${lease.stream} after ${lease.retry} claims with no acknowledged progress \u2014 the lease was lost on every attempt, so the retry budget (${options.maxRetries}) was spent without the handler ever reporting an error. Raise leaseMillis for this handler, then unblock the stream.`;
2638
+ 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.`;
2630
2639
  log().error(error);
2631
2640
  return { lease, handled: 0, acked_at: lease.at, error, block: true };
2632
2641
  }
@@ -2637,7 +2646,7 @@ function warn_misrouted(seen, stream, handler, event) {
2637
2646
  `Reaction "${handler}" on "${event}" resolved to target "${stream}", which a projection already serves. A target is served by one batch handler or one state projection, so this reaction can never run \u2014 and delivering to it would hand the projection an aggregate from another stream. Skipping it. The equivalent static \`.to({ target })\` is rejected at build; a dynamic resolver's target is only knowable here.`
2638
2647
  );
2639
2648
  }
2640
- async function run_drain_cycle(ops, registry, batch_handlers, misrouted, handle, handle_batch, lagging, leading, eventLimit, leaseMillis, on_blocked, lane) {
2649
+ async function run_drain_cycle(ops, registry, batch_handlers, misrouted, store_failing, handle, handle_batch, lagging, leading, eventLimit, leaseMillis, on_blocked, lane) {
2641
2650
  const leased = await ops.claim(
2642
2651
  lagging,
2643
2652
  leading,
@@ -2679,7 +2688,11 @@ async function run_drain_cycle(ops, registry, batch_handlers, misrouted, handle,
2679
2688
  const entry = fetch_map.get(lease.stream);
2680
2689
  const at = entry.fetch.events.at(-1)?.id || fetch_window_at;
2681
2690
  const { payloads } = entry;
2682
- const exhausted = budget_exhausted(lease, payloads[0]?.options);
2691
+ const exhausted = budget_exhausted(
2692
+ lease,
2693
+ payloads[0]?.options,
2694
+ store_failing
2695
+ );
2683
2696
  if (exhausted) return Promise.resolve(exhausted);
2684
2697
  const batchHandler = batch_handlers.get(lease.stream);
2685
2698
  if (batchHandler && payloads.length > 0) {
@@ -2851,6 +2864,7 @@ var DrainController = class {
2851
2864
  this._deps.registry,
2852
2865
  this._deps.batch_handlers,
2853
2866
  this._misrouted,
2867
+ this._deps.breaker.failing,
2854
2868
  this._deps.handle,
2855
2869
  this._deps.handle_batch,
2856
2870
  lagging,