Files
bookhoard/docs/admin/scanning.md
T
John O'Keefe b3a8cbd582 fix(admin): library row button renamed 'Scan' -> 'Force Rescan', per owner
Owner ruling that closed the scan-semantics discussion: the code is
correct (per-library scan IS a force scan — hx-vals force:true since
706be09d), but the label hid that. Now the naming invariant holds
everywhere: anything with Force/Rescan in its name re-reads everything
in its scope; plain 'Scan' only exists at folder scope ('Scan this
folder', shallow) and in auto mode. Book-level Rescan verified as the
per-item force path (extractMetadata re-reads sidecars/tags regardless
of file size; recomputeHashInfo follows) — it is the documented answer
to 'I changed this book's sidecar'.

Glossary Scan entry replaced with Force Rescan (old label kept in also:),
scanning.md table + prose pick up the new label. Generated file
regenerated with the Dockerfile-pinned templ version from inside
templates/ so the diff is exactly the label strings.
2026-11-02 14:08:19 -05:00

90 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- Ground truth: internal/handlers/scanner.go (ScanLibrary, StartScanner,
per-folder validation, coalescing), internal/services/media_scanner.go
(forceRescan semantics, steady-skip path, watcher/poll/initial
triggers, enqueueLibraryScan force:false), internal/services/worker.go
(SetForce), templates/admin.templ + web/src/admin.ts (dashboard
button, one job per library), templates/admin_library.templ +
templates/utils.go (per-library Scan force:true, per-folder scan),
templates/admin_settings.templ (Auto-Scan, Scan Interval).
Re-verify against these when scanning behavior changes. -->
# Scanning
Scanning is how Bookhoard's server reads your library folders and keeps the
catalog in step with the files on disk. This page covers every scan an
admin can trigger, what each one actually does, and what it costs — so you
can pick the right one before clicking.
## The one distinction: shallow vs. force
Every scan is one of two kinds:
- **Shallow** (the default). The scanner walks the folder and skips any
file whose size and modification time are unchanged since it was last
seen. New and changed files get processed; untouched files cost nothing.
Fast, and the right choice for day-to-day keeping-up.
- **Force**. Nothing is skipped. Every file is re-read and re-extracted
with the scanner's current parsing, and each item's hash identifiers
(the SHA-256 fingerprints used for duplicate detection and device book
matching) are recomputed. This is the backfill tool: run it after
scanner improvements you want applied to already-scanned books, after
mass edits in Calibre or on disk, or when metadata looks stale anywhere
in a library. It is deliberately slow on big libraries.
## Every scan control, and what it does
| Control | Where | Kind | Scope |
| --- | --- | --- | --- |
| **Force Rescan All Libraries** | Admin dashboard → Quick Actions | Force | Every library |
| **Force Rescan** (library row) | Admin → Libraries | Force | That library |
| **Scan this folder** (folder-row icon) | Admin → Libraries → a library's panel | Shallow | That folder's subtree |
| **Auto-Scan** + **Scan Interval (seconds)** | Admin → Settings → Scanning | Shallow | Every library |
| **Retry** / **Retry all** | Admin → Libraries → Processing Issues | Per-item | Failed items only |
| **Rescan** / **Reset to Scanned** | A book's detail page | Per-item | That one item |
The details behind the table:
- **Force Rescan All Libraries** loops over every library and starts a
force scan job for each. Libraries that already have a scan running are
left alone — the button reports which libraries started and which were
skipped because a scan was already in flight.
- **Force Rescan** on a library row is the same force rescan, scoped to
that one library. It shares the dashboard button's semantics exactly.
- **Scan this folder** is the only folder-sized scan, and the only shallow
one an admin triggers by hand: unchanged files are skipped, and only
that folder's subtree is walked. Because a partial scan can't vouch for
what it didn't look at, it never marks items from the library's *other*
folders as missing. Podcast download folders refuse this button — they
are managed by the feed system, not the scanner.
- **Auto-Scan** arms the two automatic triggers, both shallow: a
filesystem watcher that fires as files change, and a periodic poll that
runs every **Scan Interval (seconds)** (default 60, allowed 1–3600).
The same shallow pass also runs once at startup when auto-scan is on.
- **Retry** and **Retry all** on a library's Processing Issues page send
failed items back through the scanner one at a time — deliberately not
a library-wide scan, so fixing a few bad files never re-reads the whole
library.
- **Rescan** on a book's page re-extracts that item from its file and
recomputes its hashes. **Reset to Scanned** clears your manual metadata
edits first, so what lands is purely what the scanner derives from the
file.
## Rules worth knowing
- **One scan per library at a time.** Starting a second scan for a library
that already has one pending or running is refused — the dashboard
tells you a scan is active rather than stacking a duplicate. The
automatic triggers skip silently instead.
- **Scans run in the background.** The dashboard's Scanning panel shows
per-library progress while jobs run; **Cancel all scans** stops the ones
still queued or running, and you can keep working meanwhile.
- **Missing files archive after two consecutive scans.** When a
library-wide scan (shallow or force) can't find a file twice in a row,
the item is archived — reading history is kept in case the file comes
back. The Archived Items page in this section manages the results.
- **Metadata comes from the files themselves.** The scanner reads sidecar
files (Calibre's `metadata.opf` in particular), embedded tags, and
filenames — [Calibre Integration](../user/calibre-integration.md) covers
the sidecar story. What a scan extracts is exactly what a force rescan
re-extracts.