Nobody has started this yet — be first.
Business impact
DELETE /images/{id} returns a clean 204 No Content and the database row genuinely disappears -- so from the outside, deletion looks 100% successful. But the three thumbnail files it generated (thumb_small., thumb_medium., thumb_large.*) are never removed from disk. Every delete of a fully-processed image now leaks 3 files with nothing left in the database to ever reference or clean them up again. On a service whose whole job is storing images, this is a slow, silent disk-space leak that will eventually page whoever is on call when the disk fills up -- and by then there is no record left anywhere of which orphaned files belong to which (already-deleted) user upload, making cleanup a forensic exercise instead of a query.
Problem
delete_image deletes the original file from storage and the DB row, but no longer deletes the generated thumbnail files.
Current behavior
After a successful DELETE /images/{id} on a fully-processed image, the DB row is gone and the request returns 204, but the per-image storage directory still contains thumb_small/medium/large files with nothing left to ever reference or clean them up.
Expected behavior
DELETE /images/{id} must remove everything stored for that image: the original file and every thumbnail file that was generated for it. After a successful delete, nothing under that image's storage key prefix should remain on disk.
Steps to reproduce
cd fastapi/image_service && source .venv/bin/activate pytest -q tests/test_upload.py::test_delete_removes_original_and_all_thumbnails -v
Why this matters
app/storage.py's StorageBackend interface exists specifically so the rest of the app doesn't reach into the filesystem directly -- but that only helps if every caller that creates storage objects also remembers to clean them all up. record.thumbnails (a dict of size_name -> storage key, populated by the background pipeline once processing succeeds) is exactly the manifest needed to know what to delete; it's read correctly everywhere else (the metadata response, thumbnail download) but is no longer consulted during delete.
Suggested approach
Look at delete_image in app/main.py. It already deletes record.original_key via storage.delete(...) -- record.thumbnails is a dict of size_name -> key populated by run_thumbnail_pipeline once processing succeeds (see how download_thumbnail reads it a few lines above, for the shape). The fix belongs right next to the existing storage.delete(record.original_key) call.
Acceptance criteria
Verification
pytest practicetickets/test_ticket02_delete_thumbnail_cleanup.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
$git checkout -b fix/delete-thumbnail-cleanupFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/delete-thumbnail-cleanupSubmit 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 indocker-compose.yml./app./testsuvicorn --reload/app/dataDockerfile.proddocker compose -f docker-compose.prod.yml up --build -dWithout Docker:
cd fastapi/image_service
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements-dev.txt
cp .env.example .env # optional, defaults work out of the box
uvicorn app.main:app --reload # -> http://127.0.0.1:8000/docs
Work the tickets in practicetickets/ (TICKET_01 through TICKET_07); each names one dedicated pytest file:
pytest practicetickets/test_ticket01_upload_size_boundary.py -v # a single ticket
./practicetickets/run_tickets.sh # all 7, clean pass/fail summary
Run run_tickets.sh from anywhere -- it cds to the project root itself before running, since app/main.py resolves its SQLite file and upload directory relative to the working directory at import time. pytest -q tests/ (the project's own pre-existing suite, separate from practicetickets/) is also worth running before and after each fix -- three of the four bugs (tickets 02, 04, 06) also break specific pre-existing tests there, and fixing the ticket correctly should make those green again too, with zero changes needed inside tests/ itself.
Level 1
Fix a bug
Read existing behaviour, correct it.