Skip to content

Table of Contents

Month 5 · Week 4 — Exercises (queue resilience: backoff, dead-letter, metrics)

Standard-library-only Go packages with table-driven tests. They rebuild the resilience and observability mechanics behind this week's capstone — the gRPC + Redis job-queue service — so go test runs anywhere with no Redis, no Prometheus, and no network.

How to run

go test ./exercises/month-05/week-4/...
# race detector matters for the metrics registry:
go test -race ./exercises/month-05/week-4/metrics
# one at a time, verbose:
go test -v ./exercises/month-05/week-4/backoff

Prompts

  1. backoff/ — Implement Backoff(attempt, base, max) returning base * 2^attempt clamped to max, with NO integer overflow for large attempts (double iteratively and cap in-loop). Then FullJitter(...r *rand.Rand) returning a uniform delay in [0, Backoff]. Inject *rand.Rand for deterministic tests. Concepts: exponential backoff, full jitter / thundering herd, overflow-safe math (Day 137).

  2. deadletter/ — Implement Run(Job, maxAttempts) that retries a job's work up to the budget, stops early on success, dead-letters immediately on ErrPermanent, and on exhaustion returns a %w-wrapped final error with Dead: true. Add Dispatch([]Job, maxAttempts) partitioning IDs into succeeded / dlq in input order. Concepts: retry budgets, transient vs permanent errors, dead-letter queues, error wrapping (Day 137).

  3. metrics/ — Implement a concurrency-safe counter Registry: Inc/Add/ Get/Snapshot plus a SeriesKey(name, labels) that sorts labels so {a,b} and {b,a} map to the same series. Snapshot must return a copy. Must pass go test -race. Concepts: counters, label cardinality, mutex-guarded shared state, defensive copies (Day 138).

Results

Exercise Focus go test
backoff exponential backoff + full jitter, overflow-safe
deadletter retry budget + DLQ routing + error wrapping
metrics concurrency-safe labeled counters (race-clean)