fix(api): name the genre route, and report where the event stream has been cut - #181
Conversation
Closes #179. `GET /api/v2/songs` required `genre` and answered 400 without it, while being wired to a handler called `list_songs_by_genre`. The path said "songs", the handler said "songs by genre", and the contract said no. The behaviour is the deliberate half. A test already pinned that 400 with its reason — the genre is what the request is about, so its absence is a malformed request and not an unfiltered catalogue — and the general listing exists elsewhere, as `/libraries/{id}/tracks`, which pages and searches. Relaxing `genre` to an option would have undone a decision somebody made on purpose and left two ways to list songs. So the path moves rather than the parameter: `/api/v2/songs/by-genre`, beside `/songs/random`. `/api/v2/songs` now belongs to nobody, and a test says it answers 404 — it was its readability that sent people looking for a bug, not its status code, and a path that means nothing is better than one that means something it will not do. The last reference was found by the suite rather than by me: the search that swept the rename looked for `"/api/v2/songs"` closed, and missed the one carrying a query string. Claude-Session: https://claude.ai/code/session_01TyKunaKXS16hyFDBHwc5KK Signed-off-by: InstaZDLL <github.105mh@8shield.net>
Closes #178. A client following a library's events keeps a cursor, and the server refuses it once retention has cut past it. Nothing said how close that was, so the first sign of trouble was the refusal — the worst moment to pay for a full resync, since it has to happen right then whatever else is going on. The watermark was not missing, only unreported. `library.events_purged_through` already exists, is already read in the same transaction that builds the page, and is already what decides the refusal. It is now a field on that page, at no extra query and describing the same instant as the rows it travels with, which a second read could not promise. The test found an error in the sentence that documented it. The margin is the client's **own** cursor minus the watermark, not `next_cursor` minus the watermark: `next_cursor` is the end of the page just served, so it says what the margin becomes once the page is applied, not what it is. The assertion failed on exactly that gap; the field's documentation and the API guide now draw the distinction rather than glossing it. Claude-Session: https://claude.ai/code/session_01TyKunaKXS16hyFDBHwc5KK Signed-off-by: InstaZDLL <github.105mh@8shield.net>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (9)
Included review availability: 8 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour. 📝 WalkthroughWalkthroughLa route de filtrage par genre passe à ChangesRoute de filtrage par genre
Limite de rétention des événements
Estimated code review effort: 2 (Simple) | ~10 minutes Severity of issue fixed: Low Merge Risk: ⚪ Minimal · up to Genre-filtered song requests now use the explicit by-genre route, while event pages expose their retention watermark. The API, client, documentation, and tests align with the intended behavior, with no remaining merge-blocking risk identified. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Out of Scope Changes checkExplanation Les changements relatifs à
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Closes #179 and #178. Two independent issues, one commit each.
#179 — the path was wrong, not the parameter
GET /api/v2/songsrequiredgenreand answered 400 without it, while wired to a handler calledlist_songs_by_genre.The issue offered two coherent fixes and asked for one to be picked. The code picked it: a test already pinned that 400 with its reason — the genre is what the request is about, so its absence is a malformed request and not an unfiltered catalogue — so the behaviour is deliberate. And the general listing exists already, as
/libraries/{id}/tracks, which pages and searches. Relaxinggenreto an option would have undone a decision somebody made on purpose and left two ways to list songs.So the path moved:
/api/v2/songs/by-genre, beside/songs/random./api/v2/songsnow belongs to nobody, and a test says it answers 404 — a path that means nothing is better than one that means something it will not do.The last reference was found by the suite, not by me: the search that swept the rename looked for
"/api/v2/songs"closed and missed the one carrying a query string.#178 — the watermark was not missing, only unreported
The issue says the stream exposes no watermark. It exists:
library.events_purged_through, read in the same transaction that builds the page, and already the value that decides the refusal. It is now a field onLibraryEventPage, at no extra query — and describing the same instant as the rows it travels with, which a second read could not promise.{ "events": [...], "next_cursor": 41, "has_more": false, "purged_through": 0 }The test corrected the sentence I wrote to document it. I had said the margin was
next_cursor - purged_through. It is not:next_cursoris the end of the page just served, so it describes the margin the client will have after applying it. The margin it holds is its own cursor minus the watermark. The assertion failed on exactly that gap, and both the field's doc comment and the API guide now draw the distinction.Verification
cargo fmt,clippy -D warnings, 162 Rust tests across 17 targets · biome, tsc and the web build clean.Both assertions were checked by taking the fix away: hard-coding
purged_through: 0fails the feed test.#177 is untouched — it needs the desktop audit recorded in
web-client-gap-analysis.mdbefore its semantics change.https://claude.ai/code/session_01TyKunaKXS16hyFDBHwc5KK
Summary by CodeRabbit
Nouvelles fonctionnalités
/api/v2/songs/by-genre.Corrections
Documentation