You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// cancel() before the final LREM/DEL so the goroutine exits cleanly
47
+
```
26
48
27
49
2. Unify Redis client (pick v9, everywhere).
28
50
You’ve got github.com/redis/go-redis/v9 is the only supported client; wrap it in your own interface { Cmdable } for tests to avoid duplicate dependency trees.
29
51
3. Lose any KEYS in admin paths.
30
-
I saw Keys( references in admin/handlers. Replace with SCAN (you already do in reaper). No accidental O(N) death spirals.
52
+
Global `SCAN jobqueue:*` still burns clusters. Keep a registry and stick to per-worker slots.
// operate on a single slot (LLEN, LINDEX, etc.) instead of global SCANs
68
+
}
69
+
```
70
+
71
+
Hash-tag processing keys (e.g., `jobqueue:{workerID}:processing`) so each worker’s keys live in the same slot. Iterate the registry and inspect one slot per worker—no cross-slot SCAN explosions.
39
72
40
73
4. Fairness across priorities.
41
74
Your “short block per queue in priority order” can starve low-prio. Introduce a tiny token bucket per priority (e.g., 8:2:1) so low priority gets a time slice even under high load.
42
75
5. Add scheduled jobs (delays/retries with a due date).
43
-
You already have backoff; give it teeth with a ZSET mover:
76
+
You already have backoff; give it teeth with an atomic mover using `ZPOPMIN` or Lua:
// If the last batch contained only future items we can exit
104
+
ready:=false
105
+
for_, entry:=range entries {
106
+
if entry.Score <= now {
107
+
ready = true
108
+
break
109
+
}
110
+
}
111
+
if !ready {
112
+
break
113
+
}
53
114
}
115
+
```
54
116
55
-
6. Ack path is good—make it bulletproof.
56
-
You do LREM procList 1 payload after success. Keep it. Also emit an event (append-only NDJSON) so your TUI and autopsies don’t have to reconstruct history from Redis:
117
+
Prefer a Lua script if you want to pop and push in one server-side call, guaranteeing atomic delivery without client round-trips.
You do LREM procList 1 payload after success. Keep it. Emit events to a **durable sink** (S3, Kafka, etc.) so the TUI and autopsies have an authoritative ledger. If you must keep local NDJSON for debugging, write via an atomic appender with daily rotation, gzip, size caps, documented retention, and PII scrubbing. Add alerts/backpressure when the sink is unavailable so workers fail fast instead of silently dropping history.
61
121
62
122
7. Wire “exactly-once” for handlers.
63
123
You built a great idempotency/outbox module—but worker handlers aren’t using it. Before side-effects, check/process via your IdempotencyManager; on success, mark done; on retry, it short-circuits. That turns duplicate replays from “oops” into “no-op”.
|`BenchmarkHMACSigner_SignPayload`|`go test -bench=SignPayload -benchtime=3s`| MacBook Pro M2 (2023), macOS 14.5, Go 1.22.5 | 256 B payload, single goroutine | 92µs | 118µs | 140µs | Averaged over 5 runs; raw output stored in `benchmarks/event-hooks/hmac.json`. |
253
+
|`BenchmarkMatchEventFilter`|`go test -bench=MatchEvent -benchtime=3s`| Same as above | 10 filters, 4 attributes/event | 12µs | 18µs | 23µs | Captured with `BENCH_MEM=1` to record allocations. |
254
+
|`BenchmarkBackoffCalculator`|`go test -bench=BackoffCalculator -benchtime=1s`| Same as above | Exponential backoff, jitter enabled | 950ns | 1.3µs | 1.6µs | Measured with race detector disabled. |
255
+
256
+
Reproduce by running the corresponding `go test -bench` commands above; persist the raw output (for example `go test ... > benchmarks/event-hooks/latest.txt`) alongside the commit that changes these numbers.
0 commit comments