Conversation
request() envolvía cualquier fallo en Exception("HTTP $code: ..."), enterrando
el código de estado dentro de un String (GEN-AP-06). Sin él, el clasificador de
errores de F3.3 (docs/downloads) no puede distinguir 401/403/404/416/429/5xx sin
parsear texto.
- JellyfinHttpException(statusCode, retryAfter, message): retryAfter va crudo,
sin parsear — los dos formatos de Retry-After los decide quien clasifica.
- catch (e: CancellationException) { throw e } antes del catch genérico: el
catch (e: Exception) existente tragaba la cancelación (AND-CONC-04).
- Cero llamantes en el proyecto parseaban el mensaje anterior; sin regresiones.
Self-review (code-review skill, medium effort) surfaced one finding:
authenticateByName(), a few lines below, has the exact same
CancellationException-swallowing catch (e: Exception) — same bug, same file,
just not the method R19 named. Fixed it too, same one-line pattern, with a
test mirroring the existing deterministic cancel-before-call case. Left its
HTTP-failure paths as plain Exception (not JellyfinHttpException): unlike
request(), nothing downstream needs to distinguish auth failure status codes,
and R19/F3.3 don't ask for it there.
6 tests JVM nuevos (5 + 1 de la autorevisión), en verde. Baseline: 393 tests,
los mismos 5 fallos preexistentes de siempre, ninguno nuevo (check-baseline.sh).
Self-review (code-review, medium effort)One finding, applied: `authenticateByName()`, a few lines below `request()` in this same file, had the identical `catch (e: Exception)` that swallows `CancellationException` into a `Result.failure` — the exact bug this PR fixes, just not the method R19 named. Fixed with the same one-line pattern, plus a test mirroring the existing deterministic cancel-before-call case. Left `authenticateByName()`'s HTTP-failure paths as plain `Exception` (not `JellyfinHttpException`) — unlike `request()`, nothing downstream needs to distinguish auth failure status codes, and that's not what R19/F3.3 ask for here. Re-verified: 6 JVM tests (was 5), all green. Baseline unaffected — 393 tests, same 5 pre-existing failures, none new. |
f2808bc to
7fa1eed
Compare
Comments cited local-only planning files and rule IDs (docs/downloads/*.md, GEN-/AND- rule docs) that don't exist outside this machine and are meaningless to anyone reviewing the PR. Reworded to keep the same technical reasoning without the dangling references.
|
Closing for now — reorganizing how this work is staged. It'll go through our fork first and we'll propose it upstream again, possibly bundled differently, once the larger feature it's part of is further along. Not a rejection, just a process change on our side. |
What
JellyfinApiService.request()wraps every non-2xx response inException("HTTP $code: ${response.message}"), so callers can't tell 401 from429 without parsing a message string. This is one of the small independent
fixes listed in #2813.
Changes
JellyfinHttpException(statusCode, retryAfter, message)replaces the plainExceptionon the failure path ofrequest().retryAfteris passedthrough unparsed (HTTP allows either a number of seconds or an HTTP-date;
deciding between the two is a caller concern, not this type's).
catch (e: CancellationException) { throw e }added before the existingcatch (e: Exception), which was silently swallowing cancellation.Why now, and why scoped this tight
Grepped the whole codebase first: nothing parses the old message string, so
this has no other call site to update.
authenticateByName()andcheckDownloadPermission()in the same file have the identicalswallowed-cancellation issue, but I left them alone here to keep this PR to
exactly the one thing it claims to do — happy to open a follow-up for those
two if useful.
Testing
5 new JUnit5 tests. No mock-server dependency added — a real
okhttp3.Responsebuilt through anInterceptoron the injected client isenough to exercise
request()'s real parsing path (status code, theRetry-Afterheader, and the happy path), without introducing anything newto the test graph.
:app:testDebugUnitTest: 393 tests, same 5 pre-existing failures asmaster's baseline, none new.