diff --git a/serverAppConfigs-docs/Dankserver/Audiobookshelf.md b/serverAppConfigs-docs/Dankserver/Audiobookshelf.md index 153aee5..5ce6c80 100644 --- a/serverAppConfigs-docs/Dankserver/Audiobookshelf.md +++ b/serverAppConfigs-docs/Dankserver/Audiobookshelf.md @@ -121,13 +121,30 @@ the file, not the bind: the same line count grows while the total climbs. itself.** The door is `GET /api/libraries//items?limit=1` → `total`; a poller 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. + page, so a census that loops "until empty" invents its own total: `limit=500` + against a `total` of 4,628 hands back exactly 5,000 rows — the collected count + is `ceil(total / limit) × limit`, which is why two runs reported "exactly 1,500" + and "exactly 4,000" for one library. Stop on `total`, count *unique ids*, and + take the number after the pass settles (`total` itself moves during a scan). - **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 law — so the in-container watcher sees nothing a host process files onto the array, and the deployer's re-run of the bootstrapper is the cheap scan trigger. +- **A book is the shallowest folder that holds audio — and that item owns the + subtree beneath it.** A folder with audio in its own file list becomes ONE book + and the scanner folds everything below it into that book's tracks instead of + making items: 6 stray files at the root of `_unsorted` turned the whole + collection dump into a single item of 5,693 tracks, titled after whichever file + supplied metadata, with 542 real books inside it. So "hundreds of books are + missing" is a layout fault, not a scan fault — and no scan, forced or not, + subdivides an existing item. Census the layout the server's way: a directory is + a book folder iff its *own* files include an audio extension. +- **`DELETE /api/items/:id` is a DB row; `?hard=1` is `fs.remove()`.** Read + `LibraryItemController.delete`: `hardDelete = req.query.hard == 1` and then + `fs.remove(libraryItemPath)`. Pointed at a covering item, that path is the whole + swallowed subtree — `hard=1` there deletes every audiobook under it off the + array. Un-swallowing is: file the loose root files with the journal-guarded + mover, then delete the stale covering item with NO query string. - **`Invalid data found when processing input` names the file, not the bind.** The scanner logs it per file and skips the file — the book never appears — so a missing title beside those lines is library debris, not a server fault. Census of