mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-03-01 13:39:41 +00:00
3.7 KiB
3.7 KiB
Artifact Specification: Scanner Missing and Invalid Flag Reset Fix
1. Overview
This specification details the fixes implemented to resolve two major bugs regarding how the application's library scanner processes files and updates item statuses:
- Stuck "Issues" Status: Books and podcasts migrated from v1 databases could have a legacy
isInvalid: trueflag. Normal scans and rescans successfully clearedisMissingwhen files were found, butisInvalidwas never cleared. This forced items to permanently show up as having "issues" unless the user performed a heavy "Consolidate" action. - Scanner Path Duplication (Symlink Bug): When libraries were sourced from symlinked directories,
fileUtils.recurseFileswould inadvertently duplicate paths because the underlyingfs.realpathresolution of the symlink caused a string mismatch when stripping the root relative path.
2. API & Data Contracts
- Data Contracts: No changes to the database schemas. The existing
isMissingandisInvalidschema flags are preserved. - Scanner Output:
LibraryItemScanData,BookScanner, andPodcastScannerwill actively pushisInvalid: falseto the DB when files are detected.
3. Traceability (Files Modified)
| Category | File | Change Description |
|---|---|---|
| Backend | server/scanner/LibraryItemScanData.js |
Updated checkLibraryItemData to assert isMissing: false and isInvalid: false if either was true |
| Backend | server/scanner/BookScanner.js |
Updated rescanExistingBookLibraryItem to assert isMissing: false and isInvalid: false if either was true |
| Backend | server/scanner/PodcastScanner.js |
Updated rescanExistingPodcastLibraryItem to assert isMissing: false and isInvalid: false if either was true |
| Backend | server/utils/fileUtils.js |
Refactored recurseFiles to use fs.realpath() for relPathToReplace before string manipulation to ensure correct substring replacement inside symlinks |
4. Architectural Decisions
Scanner Flags
- Decision: Explicitly check
|| existingLibraryItem.isInvalidbefore attempting to unset the flags. - Reasoning: Rather than wiping
isInvalidindiscriminately, we check if the flag is activelytrueand the filesystem says the files exist and load correctly. If so, the item is restored to a fully healthy state. This aligns behavior seamlessly with theisMissinglogic.
Symlink Substring Removal
- Decision: Use
fs.realpath(relPathToReplace)before stripping prefixes. - Reasoning: The
recursiveReaddirAsyncutility was configured withrealPath: true. It inherently resolves all symlinks for deep-scanned objects. WhenfileUtilstried to truncate the root pathrelPathToReplaceusing string replacement, it failed on symlinked paths becauseitem.fullnamewas resolved butrelPathToReplacewas not. EnsuringrelPathToReplacealso runs throughfs.realpathfixes the root mismatch.
5. Verification Plan
- Invalid Items Recovery:
- Restart server.
- Re-scan an item that was historically tagged "invalid" via single-file root folders.
- Verify the UI "issues" count actively clears.
- Symlink Scans:
- Trigger a scan on a directory mapped via symlinks (e.g.,
/home/user/...->/mnt/docker/...). - Validate that item metadata and paths register with the scanner correctly without dumping duplicate paths (
/home/user/mnt/docker/user...) in logs or the DB.
- Trigger a scan on a directory mapped via symlinks (e.g.,
6. Limitations & Future Work
- Legacy v1
isInvaliditems are still expected to exist in long-lived databases until they are actively rescanned or a full-library scan captures them under the new rules. No background database migration was run to mass-clear them, to ensure the file scanner correctly assesses integrity.