Nobody has started this yet — be first.
Business impact
This service supports two idempotency schemes: a client-supplied event_id UUID, or a (device_id, sequence) pair for clients that can't mint UUIDs. The second scheme's key is built by concatenating the two fields with no separator between them. Because both fields are variable-length, two completely different, unrelated events from two different devices can produce the identical event_key string — which means the second one silently vanishes, dropped by the ON CONFLICT DO NOTHING upsert as if it were a duplicate. This is common for any pair of devices whose IDs share a prefix relationship (e.g. "device1", "device12"). Events go missing with no error, no log line, and no way to tell from the API response that anything was lost.
Problem
The (device_id, sequence)-based idempotency key is built by concatenating the two fields with no separator between them, so two different (device_id, sequence) pairs can produce the identical key string.
Current behavior
event_key() returns f"{self.device_id}{self.sequence}" with no delimiter — device_id="d1", sequence=23 and device_id="d12", sequence=3 both produce "d123".
Expected behavior
event_key() must be injective over (device_id, sequence) pairs: no two distinct pairs may ever produce the same string, while the same pair must always produce the same key (so genuine retries still dedupe).
Steps to reproduce
cd fastapi/ingest_service && .venv/bin/python -c "from app.schemas import EventIn; a = EventIn(device_id='d1', event_type='t', sequence=23); b = EventIn(device_id='d12', event_type='t', sequence=3); print(a.event_key(), b.event_key(), a.event_key() == b.event_key())"d123 d123 True — two different events, same key.Why this matters
Building a composite key by naive string concatenation without a delimiter is a classic way to accidentally make a supposedly-unique key non-injective. It's especially insidious here because the failure is silent by design — the whole point of ON CONFLICT DO NOTHING is to make duplicates disappear without an error, so a key collision between two genuinely different events looks identical to the system working exactly as intended.
Suggested approach
Look at EventIn.event_key() in app/schemas.py. The event_id-based branch already works (a UUID string can't collide with the composite scheme). Focus on the f"{self.device_id}{self.sequence}" line — what would make two different (device_id, sequence) pairs guaranteed to produce different strings?
Acceptance criteria
Verification
pytest practice_tickets/tests/test_ticket_07_event_key_collision.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/event-key-delimiter-collisionFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/event-key-delimiter-collisionSubmit 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.