feat(scan): add a per-folder deep rescan action#419
Conversation
Symptom A of issue #366: the scanner's fast path keys purely on (mtime, size) at scan.rs's Phase 1, so a tag or embedded-picture edit made by an external tool that preserves the file's mtime (Mp3tag's 'preserve modification time' option, among others) is never noticed — the file never even reaches the hash/re-extract step that would actually catch it. refresh_folder_covers already closed the sidecar cover.jpg half of this issue; this closes the remaining half. scan_folder_inner gains a deep: bool parameter that bypasses the Phase 1 fast path entirely when true, so every file in the folder is re-hashed and re-read. Every existing caller (the fs-watcher, the scan-on-start path, rescan_library, import_paths) passes false to keep normal re-scans fast; only the new scan_folder(folderId, deep) argument, wired to a per-folder action in the library's 'Dossiers' tab, can opt in. Deliberately scoped to per-folder rather than adding a matching deep option to rescan_library/import_paths or a global Settings card -- the reported problem is 'I edited one album's tags', not 'I need every scan to be slow by default'. i18n key propagated to all 17 locales. Refs #366
|
Warning Review limit reached
Next review available in: 11 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAjout d’un rescan approfondi par dossier, transmis de l’interface au backend. Ce mode relit et re-hache tous les fichiers, sans utiliser le filtrage mtime/taille. Les chemins de scan existants conservent le mode standard. ChangesRescan approfondi
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
actor Bibliothèque
participant LibraryView
participant scanFolder
participant scan_folder
participant scan_folder_inner
Bibliothèque->>LibraryView: Cliquer sur deep rescan
LibraryView->>scanFolder: scanFolder(folderId, true)
scanFolder->>scan_folder: invoke(folderId, deep)
scan_folder->>scan_folder_inner: deep.unwrap_or(false)
scan_folder_inner-->>LibraryView: ScanSummary
LibraryView-->>Bibliothèque: Terminer le spinner
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src-tauri/crates/app/src/commands/scan.rs`:
- Around line 553-579: Update the Phase 1 loop around `to_extract` and
`existing_meta` to remove each discovered path from `existing_meta`
unconditionally before the `!deep` fast-path check. Preserve the existing
metadata comparison and skip behavior, while ensuring deep scans and later
extraction failures cannot cause present files to be marked unavailable.
In `@src/components/views/LibraryView.tsx`:
- Around line 448-459: Update handleDeepRescanFolder so it refreshes the
LibraryContext after scanFolder completes, using the existing listFolders
refresh mechanism or the library:rescanned Tauri event. Preserve the current
guard, error logging, and finally cleanup while ensuring the last-scan date and
track count update in the view.
- Around line 2374-2393: Update the deep-rescan button’s className in the folder
list so it forces opacity-100 when deepRescanFolderId equals folder.id, while
preserving the existing opacity-0 and group-hover behavior for other folders.
Use the existing deepRescanFolderId state and folder.id comparison already used
for aria-busy and the spinner.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: dfb9c167-7409-46ec-b1c0-572313865339
📒 Files selected for processing (23)
src-tauri/crates/app/src/commands/library.rssrc-tauri/crates/app/src/commands/scan.rssrc-tauri/crates/app/src/lib.rssrc-tauri/crates/app/src/watcher.rssrc/components/views/LibraryView.tsxsrc/i18n/locales/ar.jsonsrc/i18n/locales/de.jsonsrc/i18n/locales/en.jsonsrc/i18n/locales/es.jsonsrc/i18n/locales/fr.jsonsrc/i18n/locales/hi.jsonsrc/i18n/locales/id.jsonsrc/i18n/locales/it.jsonsrc/i18n/locales/ja.jsonsrc/i18n/locales/ko.jsonsrc/i18n/locales/nl.jsonsrc/i18n/locales/pt-BR.jsonsrc/i18n/locales/pt.jsonsrc/i18n/locales/ru.jsonsrc/i18n/locales/tr.jsonsrc/i18n/locales/zh-CN.jsonsrc/i18n/locales/zh-TW.jsonsrc/lib/tauri/library.ts
Three review findings on the deep-rescan PR, all confirmed: 1. Phase 1 only removed a walked path from existing_meta on the fast-path skip branch; the consumer loop's own removal only fires on a SUCCESSFUL extraction. A file that's on disk but fails extraction (a lock, a transient I/O error, a malformed rewrite mid-scan) stayed in existing_meta and got swept into is_available = 0 by the end of the scan -- despite being present. Deep mode makes this far more likely to bite, since every file in the folder is now on that path instead of just the ones that happened to change. Fixed by removing each walked path unconditionally, before the deep/fast-path branch. 2. handleDeepRescanFolder never refreshed anything after scanFolder(..., true) resolved -- scan_folder doesn't emit library:rescanned (only folder removal and tag edits do), so a folder's last-scan date and track count stayed stale in the UI until some unrelated action refreshed them. Now refetches via the same listFolders(null) the mount effect already uses. 3. The deep-rescan button's row icon was opacity-0 unconditionally, only reaching opacity-100 on :hover -- so the spinner for the folder actually being rescanned was invisible the moment the mouse left that row, unlike the watch-toggle and delete buttons which both stay visible while active. Now forces opacity-100 when deepRescanFolderId matches the row.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Summary
Addresses the remaining half of issue #366's Symptom A (not auto-closing — this needs runtime confirmation, see Test plan).
The scanner's Phase 1 fast path in
scan_folder_innerskips a file whose(mtime, size)matches the stored row — cheap, and what makes re-scans of a large library fast. But it means a tag or embedded-picture edit made by an external tool that preserves the file's mtime (Mp3tag has a "preserve modification time" option, among others) is invisible: the file never reaches the hash/re-extract step that would actually notice the change.refresh_folder_coversalready closed the sidecarcover.jpghalf of this symptom (a prior PR). This closes the embedded tag/picture half — the part still open.Changes
scan_folder_innergains adeep: boolparameter. When true, Phase 1's(mtime, size)check is skipped entirely, so every file in the folder is re-hashed and re-read (hash_file's doc comment already notes a tag rewrite shifts bytes in the hashed window, so the hash-compare step downstream correctly picks up the edit — Phase 1 was the only thing standing in the way).rescan_library,import_paths) passesfalse, so normal scans are unaffected.deepargument on thescan_foldercommand, wired to a per-folder action (spinning refresh icon) in the library's "Dossiers" tab — the only place a user targets an individual folder today.rescan_library/global Settings option: the reported problem is "I edited one album's tags," not "make every scan slow by default."library.folderList.deepRescan) propagated to all 17 locales.Test plan
cargo check --workspace --all-targets— cleancargo test -p waveflow --lib— 120/120 passingbun run typecheck— cleanbun run lint— cleanSummary by CodeRabbit
Nouvelles fonctionnalités
Améliorations