Skip to content

Bound the dead-letter stream, circuit breaker, damped metrics and dashboard fixes - #1

Merged
webpatser merged 1 commit into
mainfrom
feature/dead-letter-safeguards-dashboard-fixes
Aug 28, 2026
Merged

webpatser merged 1 commit into
mainfrom
feature/dead-letter-safeguards-dashboard-fixes

Conversation

@webpatser

Copy link
Copy Markdown
Owner

Why

On 2026-08-27 a scrpr.nl instance lost its KvK upstream. Every job failed permanently, the dead-letter stream grew to 3.9M entries (22 GB) and Redis went OOM. The stream had no cap and nothing ever called trim(). Meanwhile the dashboard's refresh popover was stuck open and the throughput gauge swung between 0 and 90K/min on bursty workloads.

What

Dead-letter / OOM

  • XADD MAXLEN ~ cap (dead_letter.max_entries, default 100k)
  • Master housekeeping every dead_letter.prune_interval seconds; torque:prune [--deep] [--dry-run]
  • Workers XGROUP DELCONSUMER themselves on clean shutdown
  • Per-stream circuit breaker (circuit_breaker.*, per-stream override or opt-out), reusing the per-queue pause path; torque:pause continue / queue:resume force-close it
  • Version-keyed data upgrade on master start ({prefix}version) that sweeps orphaned job streams, stale index members and legacy keys once

Metrics

  • Minute / hour / day rollups, cluster-wide, per stream and per job class, ~60 KB per scope
  • Gauge tier so every overview sparkline survives a reload
  • Damped 5-minute gauge with exact last-hour count and auto-fitting scale
  • New Jobs page; Queues page gets processed/failed today, jobs/min and a breaker badge

Dashboard fixes

  • Popover / theme toggle vs Livewire morph (wire:ignore, Alpine-driven)
  • Tables scroll inside cards, grids stack below 1180px
  • Inspector no longer lists bookkeeping keys as queues

Verified

  • vendor/bin/pest: 485 passed, 0 failed (8 environment skips) against Redis 8
  • vendor/bin/pint clean
  • Gauge and rollups smoke-tested against seeded Redis data (two 1500-job bursts read as 326 jobs/min, 3000 in the last hour)

Docs: CHANGELOG 0.16.0, README, new UPGRADE.md.

… dashboard fixes

Dead-letter / Redis OOM (scrpr 2026-08-27 incident):
- XADD MAXLEN cap on the dead-letter stream (dead_letter.max_entries)
- master-driven housekeeping every dead_letter.prune_interval seconds
  (TTL trim, cap, stale consumer sweep), plus torque:prune [--deep]
- workers delete their own consumer on clean shutdown
- per-stream circuit breaker with configurable window, threshold,
  cooldown and half-open probes, reusing the per-queue pause path
- version-keyed data upgrade on master start ({prefix}version) that
  sweeps orphaned job streams, stale index members and legacy keys

Metrics:
- minute / hour / day rollups (processed,failed) cluster-wide, per stream
  and per job class; gauge tier for latency, concurrency, memory, depth
- damped 5-minute throughput gauge with exact last-hour count and
  auto-fitting scale (dashboard.gauge_max)
- Jobs page: throughput, avg and peak runtime, fail rate per job class
- Queues page: processed and failed today, jobs/min, breaker badge

Dashboard fixes:
- refresh popover and theme toggle no longer reset on every poll tick
  (Livewire morph vs x-show); tables scroll inside cards; grids stack
  below 1180px
- inspector no longer lists Torque bookkeeping keys as queues
@webpatser
webpatser merged commit efbaedc into main Aug 28, 2026
1 check passed
@webpatser
webpatser deleted the feature/dead-letter-safeguards-dashboard-fixes branch August 28, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant