Nobody has started this yet — be first.
Business impact
GET /readyz exists so a load balancer / Kubernetes stops routing traffic to an instance that can't actually process what it accepts. If it reports "ready" as long as even one flush worker out of several is still alive, an instance where 3 of 4 flush workers have crashed keeps receiving 100% of its traffic slice, its ingest queue fills up far faster than the one surviving worker can drain, and every request starts getting 503s — all while the readiness probe keeps insisting everything is fine.
Problem
GET /readyz is meant to report whether an instance can actually keep up with what it accepts, but it computes workers_alive using a check that stays true as long as a single flush worker out of several configured ones is still running.
Current behavior
readyz computes workers_alive = bool(flush_tasks) and any(not t.done() for t in flush_tasks) — any(...) is true the moment one worker survives, so an instance with flush_workers=4 where 3 have crashed still reports ready.
Expected behavior
workers_alive should be True only when every configured flush worker is still alive; a deployment with any crashed worker (while at least one other is still running) should report /readyz as not ready.
Steps to reproduce
pytest practice_tickets/tests/test_ticket_05_readyz_worker_crash.py -v — starts an app with flush_workers=3, cancels 2 of the 3 flush tasks, then calls GET /readyz, which currently still returns 200 ready.Why this matters
any() and all() are easy to swap when skimming code quickly — both read as reasonable-sounding English, but they encode opposite quantifiers over the same collection. The failure mode this swap produces is especially dangerous because it's silent: nothing crashes, no error is logged, the endpoint just keeps returning 200 while the system is degraded underneath it.
Suggested approach
Look at the workers_alive line in app/routers/health.py::readyz. Think about what "every worker is alive" vs. "at least one worker is alive" should each look like as a one-line boolean expression over flush_tasks, and which one this readiness check is supposed to mean.
Acceptance criteria
Verification
pytest practice_tickets/tests/test_ticket_05_readyz_worker_crash.py -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
Sign in to create it automatically, or do it yourself:
$git checkout -b fix/readyz-any-vs-allFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/readyz-any-vs-allSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inhttp://localhost:8000localhost:5432curl localhost:8000/healthzcurl localhost:8000/readyzWork the tickets in practice_tickets/tickets/ (ordered easy → hard); each names one dedicated test in practice_tickets/tests/:
pytest practice_tickets/tests/test_ticket_01_persisted_count.py -v # a single ticket
./practice_tickets/run_tickets.sh # all 20, clean pass/fail summary
TICKET-17 needs a real Postgres to run at all (it checks which column a value lands in, which no fake/in-memory DB backend can meaningfully verify) — set TEST_DATABASE_URL=postgresql://<you>@localhost/ingest_test before running it or the full suite; without it, that one test is skipped, not failed.
Level 1
Fix a bug
Read existing behaviour, correct it.