Nobody has started this yet — be first.
Business impact
Progress is the entire reason a caller polls a job at all instead of just waiting for a single "done" webhook -- it's what a progress bar, a "3 of 5 steps complete" label, or an ETA estimate is built on. Right now, every progress update reports 0% for the job's entire runtime, until a separate, hardcoded completion write jumps straight to 100%. A frontend showing this as a progress bar shows it frozen at the start for the whole job, then teleporting to done -- indistinguishable, to a user, from "this progress bar is broken" or "this job actually hung and then suddenly finished," either of which erodes trust in the product a lot faster than an honest, accurate 40% would.
Problem
step and steps are both integers, and step is always strictly less than steps except on the loop's final iteration. Integer division truncates every intermediate ratio to 0.
Current behavior
run_job()'s progress loop computes progress = (step // steps) * 100 using floor division, which truncates to 0 for every step strictly less than steps, jumping straight to 100 only on the separate final completion write.
Expected behavior
Progress should advance proportionally as steps complete -- e.g. a 4-step job should report roughly 25%, 50%, 75% at each intermediate step, not 0 four times in a row.
Steps to reproduce
pytest practice_tickets/tests/test_ticket_05_progress_stuck_at_zero.py -vPOST /jobs with {"duration_seconds": 1.2, "steps": 4}, then poll GET /jobs/{id}?wait=2 repeatedly.running 0 printed for every intermediate step, then an instant jump to -- no intermediate progress value is ever reported.Why this matters
A very common Python mistake: // (floor division) instead of / (true division) when someone's converting a percentage calculation to "avoid floats," or copies a pattern from integer-bucketing code where truncation was actually the intent. Both operators are valid, both type-check fine, and the bug only shows up as output that's wrong in a way you have to actually run the code and watch to notice.
Suggested approach
Compare step / steps (true division, giving a float between 0 and 1) against step // steps (floor division, which truncates to 0 for every step < steps). Look at what the surrounding code does with the result (rounding, multiplication by 100) to see which one the original intent was reaching for.
Acceptance criteria
Verification
pytest practice_tickets/tests/test_ticket_05_progress_stuck_at_zero.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/progress-stuck-at-zeroFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/progress-stuck-at-zeroSubmit 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 incompleted 100http://localhost:8000localhost:6379curl localhost:8000/healthz{"status": "ok", "redis": true}Work the tickets in practice_tickets/tickets/ (ordered easy → hard); each names one dedicated pytest file in practice_tickets/tests/:
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements-dev.txt
pytest practice_tickets/tests/test_ticket_01_completed_jobs_counted_as_failed.py -v # a single ticket
./practice_tickets/run_tickets.sh # all 15, clean pass/fail summary
Each ticket test runs in its own pytest process with a 60s timeout, so one hung/crashed ticket can't take down the whole run or hide another ticket's result. Run pytest tests/ (the project's own suite, against fakeredis, hermetic and fast) after each fix to check for regressions -- the README documents exactly which fixes are expected to change that suite's results.
Level 1
Fix a bug
Read existing behaviour, correct it.