docs(audiobookshelf): paging the items endpoint never terminates itself

Two censuses this session reported exactly 1,500 and exactly 4,000 books for one
library mid-scan. Cause: an out-of-range offset returns the last item instead of an
empty page, so a loop written "until the page is empty" manufactures its own
total, and total itself moves while a scan is running. Stop on total; count after
the pass settles.
This commit is contained in:
Frank committed 2026-11-02 03:18:04 -08:00
1 parent 56dfc6d0b9
commit 006bbcef28
1 file changed
+7 -3
@@ -117,9 +117,13 @@ the file, not the bind: the same line count grows while the total climbs.
- **A 200 may carry plain text.** `res.sendStatus(200)` answers the body `OK`, and - **A 200 may carry plain text.** `res.sendStatus(200)` answers the body `OK`, and
`/init` and the scan route use it; a client that parses every success as JSON `/init` and the scan route use it; a client that parses every success as JSON
crashes on the one call that matters (`tests/audiobookshelf_init.bats` pins it). crashes on the one call that matters (`tests/audiobookshelf_init.bats` pins it).
- **The item count is not a field on the library DTO.** The door is - **The item count is not a field on the library DTO, and paging never ends
`GET /api/libraries/<id>/items?limit=1` → `total`. A poller that guesses a itself.** The door is `GET /api/libraries/<id>/items?limit=1` → `total`; a poller
plausible name (`numItems`) prints `0` forever beside a scan that is working. that guesses a plausible name (`numItems`) prints `0` forever beside a scan that
is working. An out-of-range `offset` returns the last item rather than an empty
page, so a census that loops "until empty" invents its own total — two runs
reported exactly 1,500 and 4,000 for one library — and `total` itself moves while
a scan runs. Stop on `total`, and take the count after the pass settles.
- **A fresh scan is the only thing that notices new audio.** `inotify` does not - **A fresh scan is the only thing that notices new audio.** `inotify` does not
cross a rootless podman bind — measured for [[Jellyfin]], whose page owns that cross a rootless podman bind — measured for [[Jellyfin]], whose page owns that
law — so the in-container watcher sees nothing a host process files onto the law — so the in-container watcher sees nothing a host process files onto the