fix(ebooks): model targeted scans as file-only
This commit is contained in:
@@ -53,6 +53,7 @@ func (s *Scanner) ScanEbookFolder(ctx context.Context, folder *models.MediaFolde
|
||||
type ebookRootScan struct {
|
||||
root string
|
||||
files []string
|
||||
fileOnly bool // explicit single-file scan; index it but never reconcile a subtree
|
||||
rootErr error // root stat failed, or the root is not a directory
|
||||
walkFailures int // entries within the subtree the walk could not read or resolve
|
||||
}
|
||||
@@ -88,7 +89,11 @@ func collectEbookRootScans(ctx context.Context, folderID int, roots []string) ([
|
||||
// Unmounted/missing/permission-broken root: failed, not empty.
|
||||
scan.rootErr = fmt.Errorf("stat root: %w", statErr)
|
||||
case !info.IsDir():
|
||||
scan.rootErr = fmt.Errorf("root is not a directory after symlink resolution")
|
||||
if info.Mode().IsRegular() && SupportsEbookFile(cleanRoot) {
|
||||
scan.fileOnly = true
|
||||
} else {
|
||||
scan.rootErr = fmt.Errorf("root is not a directory after symlink resolution")
|
||||
}
|
||||
}
|
||||
if statErr == nil {
|
||||
if err := walkLogicalTree(ctx, cleanRoot, cleanRoot, walkModeEbook, visitedPhysicalDirs, &scan.files, &scan.walkFailures); err != nil {
|
||||
@@ -115,7 +120,7 @@ func splitEbookReconcileRoots(scans []ebookRootScan) (reconcileRoots []string, s
|
||||
reconcileRoots = make([]string, 0, len(scans))
|
||||
for i := range scans {
|
||||
scan := &scans[i]
|
||||
if scan.failed() {
|
||||
if scan.failed() || scan.fileOnly {
|
||||
continue
|
||||
}
|
||||
if len(scan.files) > 0 {
|
||||
@@ -370,7 +375,14 @@ func (s *Scanner) reconcileEbookScan(ctx context.Context, folder *models.MediaFo
|
||||
}
|
||||
reconcileRoots, _ := splitEbookReconcileRoots(scans)
|
||||
if len(reconcileRoots) == 0 {
|
||||
if len(scans) > 0 {
|
||||
allFailed := len(scans) > 0
|
||||
for i := range scans {
|
||||
if !scans[i].failed() {
|
||||
allFailed = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allFailed {
|
||||
slog.WarnContext(ctx, "ebook scan: every root walk failed; skipping missing-file reconciliation", "component", "scanner",
|
||||
"folder_id", folder.ID,
|
||||
)
|
||||
|
||||
@@ -1455,7 +1455,7 @@ func TestCollectEbookRootScansExcludesUnmountedRootFromReconciliation(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectEbookRootScansTreatsNonDirectoryRootAsFailed(t *testing.T) {
|
||||
func TestCollectEbookRootScansTreatsSingleFileRootAsNonReconciling(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
fileRoot := filepath.Join(dir, "book.epub")
|
||||
if err := os.WriteFile(fileRoot, []byte("x"), 0o644); err != nil {
|
||||
@@ -1466,8 +1466,8 @@ func TestCollectEbookRootScansTreatsNonDirectoryRootAsFailed(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("collectEbookRootScans: %v", err)
|
||||
}
|
||||
if len(scans) != 1 || !scans[0].failed() {
|
||||
t.Fatalf("scans = %+v, want one failed scan for a non-directory root", scans)
|
||||
if len(scans) != 1 || scans[0].failed() || !scans[0].fileOnly {
|
||||
t.Fatalf("scans = %+v, want one healthy file-only scan", scans)
|
||||
}
|
||||
// The file itself is still indexed; only reconciliation is withheld.
|
||||
if len(scans[0].files) != 1 {
|
||||
|
||||
Reference in New Issue
Block a user