backend: add force rescan parameter to scanner
- Add Force bool field to ScanLibraryRequest in handlers - Pass force param through job params to worker - Add forceRescan field and SetForce method to MediaScanner - Modify processMediaFile to delete and re-create existing items when force=true - Default behavior unchanged (force=false maintains skip-if-exists)
This commit is contained in:
@@ -89,6 +89,7 @@ func SetupRoutes(g *echo.Group, db *database.Queries, connManager *wsync.Connect
|
|||||||
type ScanLibraryRequest struct {
|
type ScanLibraryRequest struct {
|
||||||
FolderPaths []string `json:"folder_paths,omitempty"`
|
FolderPaths []string `json:"folder_paths,omitempty"`
|
||||||
LibraryID string `json:"library_id,omitempty"`
|
LibraryID string `json:"library_id,omitempty"`
|
||||||
|
Force bool `json:"force,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScanLibrary handles POST /api/scanner/scan (now runs in background)
|
// ScanLibrary handles POST /api/scanner/scan (now runs in background)
|
||||||
@@ -155,6 +156,7 @@ func (h *Handler) ScanLibrary(c echo.Context) error {
|
|||||||
"folders": folderPaths,
|
"folders": folderPaths,
|
||||||
"admin_id": userUUID.String(),
|
"admin_id": userUUID.String(),
|
||||||
"db": h.db,
|
"db": h.db,
|
||||||
|
"force": req.Force,
|
||||||
},
|
},
|
||||||
Status: services.JobStatusPending,
|
Status: services.JobStatusPending,
|
||||||
Context: h.ctx,
|
Context: h.ctx,
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ type MediaScanner struct {
|
|||||||
adminID pgtype.UUID
|
adminID pgtype.UUID
|
||||||
defaultLibraryID pgtype.UUID
|
defaultLibraryID pgtype.UUID
|
||||||
libraryTypes map[string][]string
|
libraryTypes map[string][]string
|
||||||
|
forceRescan bool
|
||||||
|
|
||||||
totalFiles int
|
totalFiles int
|
||||||
newItems int
|
newItems int
|
||||||
@@ -104,6 +105,10 @@ func (s *MediaScanner) SetAdminID(adminID pgtype.UUID) {
|
|||||||
s.adminID = adminID
|
s.adminID = adminID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MediaScanner) SetForce(force bool) {
|
||||||
|
s.forceRescan = force
|
||||||
|
}
|
||||||
|
|
||||||
func (s *MediaScanner) GetStats() (int, int, int) {
|
func (s *MediaScanner) GetStats() (int, int, int) {
|
||||||
return s.totalFiles, s.newItems, s.errors
|
return s.totalFiles, s.newItems, s.errors
|
||||||
}
|
}
|
||||||
@@ -356,7 +361,17 @@ func (s *MediaScanner) processMediaFile(ctx context.Context, path string) (bool,
|
|||||||
existingItem, err := s.getMediaItemByFilePath(ctx, path)
|
existingItem, err := s.getMediaItemByFilePath(ctx, path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("Media item already exists in database: %s (size: %d vs %d)\n", path, existingItem.FileSize.Int64, info.Size())
|
fmt.Printf("Media item already exists in database: %s (size: %d vs %d)\n", path, existingItem.FileSize.Int64, info.Size())
|
||||||
// Media item exists, check if file has changed (by size)
|
|
||||||
|
// If force rescan is enabled, always re-process
|
||||||
|
if s.forceRescan {
|
||||||
|
fmt.Printf("Force rescan enabled, re-processing existing media item: %s\n", path)
|
||||||
|
// Force update: delete existing and re-create
|
||||||
|
if err := s.db.DeleteMediaItem(ctx, existingItem.ID); err != nil {
|
||||||
|
fmt.Printf("Warning: failed to delete existing media item: %v\n", err)
|
||||||
|
}
|
||||||
|
// Continue to create new entry below
|
||||||
|
} else {
|
||||||
|
// Normal behavior: check if file has changed (by size)
|
||||||
if existingItem.FileSize.Int64 != info.Size() {
|
if existingItem.FileSize.Int64 != info.Size() {
|
||||||
fmt.Printf("File size changed, updating media item: %s\n", path)
|
fmt.Printf("File size changed, updating media item: %s\n", path)
|
||||||
_ = s.updateMediaItem(ctx, existingItem.ID, path, info)
|
_ = s.updateMediaItem(ctx, existingItem.ID, path, info)
|
||||||
@@ -364,6 +379,7 @@ func (s *MediaScanner) processMediaFile(ctx context.Context, path string) (bool,
|
|||||||
}
|
}
|
||||||
fmt.Printf("Media item already exists with same size, skipping: %s\n", path)
|
fmt.Printf("Media item already exists with same size, skipping: %s\n", path)
|
||||||
return false, nil
|
return false, nil
|
||||||
|
}
|
||||||
} else if err != pgx.ErrNoRows {
|
} else if err != pgx.ErrNoRows {
|
||||||
fmt.Printf("Database error checking media item existence: %v\n", err)
|
fmt.Printf("Database error checking media item existence: %v\n", err)
|
||||||
return false, fmt.Errorf("failed to check if media item exists: %v", err)
|
return false, fmt.Errorf("failed to check if media item exists: %v", err)
|
||||||
|
|||||||
@@ -194,6 +194,11 @@ func (w *Worker) processScanJob(job *Job) (interface{}, error) {
|
|||||||
return nil, fmt.Errorf("database queries required")
|
return nil, fmt.Errorf("database queries required")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
force := false
|
||||||
|
if forceVal, ok := job.Params["force"].(bool); ok {
|
||||||
|
force = forceVal
|
||||||
|
}
|
||||||
|
|
||||||
scanner := NewMediaScanner(db)
|
scanner := NewMediaScanner(db)
|
||||||
scanner.job = job
|
scanner.job = job
|
||||||
|
|
||||||
@@ -218,6 +223,7 @@ func (w *Worker) processScanJob(job *Job) (interface{}, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
scanner.SetAdminID(adminUUID)
|
scanner.SetAdminID(adminUUID)
|
||||||
|
scanner.SetForce(force)
|
||||||
|
|
||||||
if err := scanner.ScanFolders(job.Context); err != nil {
|
if err := scanner.ScanFolders(job.Context); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
Reference in New Issue
Block a user