diff --git a/client/components/tables/library/LibraryItem.vue b/client/components/tables/library/LibraryItem.vue index 25b581c9..8dd3e260 100644 --- a/client/components/tables/library/LibraryItem.vue +++ b/client/components/tables/library/LibraryItem.vue @@ -125,7 +125,7 @@ export default { this.$store .dispatch('libraries/requestLibraryScan', { libraryId: this.library.id, force }) .then(() => { - this.$toast.success(this.$strings.ToastLibraryScanStarted) + // this.$toast.success(this.$strings.ToastLibraryScanStarted) }) .catch((error) => { console.error('Failed to start scan', error) diff --git a/server/Watcher.js b/server/Watcher.js index 577460a4..3ce6a5f5 100644 --- a/server/Watcher.js +++ b/server/Watcher.js @@ -3,6 +3,8 @@ const EventEmitter = require('events') const Watcher = require('./libs/watcher/watcher') const Logger = require('./Logger') const LibraryScanner = require('./scanner/LibraryScanner') +const Task = require('./objects/Task') +const TaskManager = require('./managers/TaskManager') const { filePathToPOSIX } = require('./utils/fileUtils') @@ -22,7 +24,10 @@ class FolderWatcher extends EventEmitter { /** @type {PendingFileUpdate[]} */ this.pendingFileUpdates = [] this.pendingDelay = 4000 + /** @type {NodeJS.Timeout} */ this.pendingTimeout = null + /** @type {Task} */ + this.pendingTask = null /** @type {string[]} */ this.ignoreDirs = [] @@ -202,6 +207,13 @@ class FolderWatcher extends EventEmitter { Logger.debug(`[Watcher] Modified file in library "${libwatcher.name}" and folder "${folder.id}" with relPath "${relPath}"`) + if (!this.pendingTask) { + const taskData = { + libraryId, + libraryName: libwatcher.name + } + this.pendingTask = TaskManager.createAndAddTask('watcher-scan', `Scanning file changes in "${libwatcher.name}"`, null, true, taskData) + } this.pendingFileUpdates.push({ path, relPath, @@ -213,8 +225,8 @@ class FolderWatcher extends EventEmitter { // Notify server of update after "pendingDelay" clearTimeout(this.pendingTimeout) this.pendingTimeout = setTimeout(() => { - // this.emit('files', this.pendingFileUpdates) - LibraryScanner.scanFilesChanged(this.pendingFileUpdates) + LibraryScanner.scanFilesChanged(this.pendingFileUpdates, this.pendingTask) + this.pendingTask = null this.pendingFileUpdates = [] }, this.pendingDelay) } diff --git a/server/scanner/LibraryScanner.js b/server/scanner/LibraryScanner.js index b7f9093e..11a88bd4 100644 --- a/server/scanner/LibraryScanner.js +++ b/server/scanner/LibraryScanner.js @@ -13,6 +13,7 @@ const TaskManager = require('../managers/TaskManager') const LibraryItemScanner = require('./LibraryItemScanner') const LibraryScan = require('./LibraryScan') const LibraryItemScanData = require('./LibraryItemScanData') +const Task = require('../objects/Task') class LibraryScanner { constructor() { @@ -20,7 +21,7 @@ class LibraryScanner { this.librariesScanning = [] this.scanningFilesChanged = false - /** @type {import('../Watcher').PendingFileUpdate[][]} */ + /** @type {[import('../Watcher').PendingFileUpdate[], Task][]} */ this.pendingFileUpdatesToScan = [] } @@ -335,18 +336,25 @@ class LibraryScanner { /** * Scan files changed from Watcher * @param {import('../Watcher').PendingFileUpdate[]} fileUpdates + * @param {Task} pendingTask */ - async scanFilesChanged(fileUpdates) { + async scanFilesChanged(fileUpdates, pendingTask) { if (!fileUpdates?.length) return // If already scanning files from watcher then add these updates to queue if (this.scanningFilesChanged) { - this.pendingFileUpdatesToScan.push(fileUpdates) + this.pendingFileUpdatesToScan.push([fileUpdates, pendingTask]) Logger.debug(`[LibraryScanner] Already scanning files from watcher - file updates pushed to queue (size ${this.pendingFileUpdatesToScan.length})`) return } this.scanningFilesChanged = true + const results = { + added: 0, + updated: 0, + removed: 0 + } + // files grouped by folder const folderGroups = this.getFileUpdatesGrouped(fileUpdates) @@ -377,17 +385,42 @@ class LibraryScanner { const folderScanResults = await this.scanFolderUpdates(library, folder, fileUpdateGroup) Logger.debug(`[LibraryScanner] Folder scan results`, folderScanResults) + // Tally results to share with client + let resetFilterData = false + Object.values(folderScanResults).forEach((scanResult) => { + if (scanResult === ScanResult.ADDED) { + resetFilterData = true + results.added++ + } else if (scanResult === ScanResult.REMOVED) { + resetFilterData = true + results.removed++ + } else if (scanResult === ScanResult.UPDATED) { + resetFilterData = true + results.updated++ + } + }) + // If something was updated then reset numIssues filter data for library - if (Object.values(folderScanResults).some(scanResult => scanResult !== ScanResult.NOTHING && scanResult !== ScanResult.UPTODATE)) { + if (resetFilterData) { await Database.resetLibraryIssuesFilterData(libraryId) } } + // Complete task and send results to client + const resultStrs = [] + if (results.added) resultStrs.push(`${results.added} added`) + if (results.updated) resultStrs.push(`${results.updated} updated`) + if (results.removed) resultStrs.push(`${results.removed} missing`) + let scanResultStr = 'Scan finished with no changes' + if (resultStrs.length) scanResultStr = resultStrs.join(', ') + pendingTask.setFinished(scanResultStr) + TaskManager.taskFinished(pendingTask) + this.scanningFilesChanged = false if (this.pendingFileUpdatesToScan.length) { Logger.debug(`[LibraryScanner] File updates finished scanning with more updates in queue (${this.pendingFileUpdatesToScan.length})`) - this.scanFilesChanged(this.pendingFileUpdatesToScan.shift()) + this.scanFilesChanged(...this.pendingFileUpdatesToScan.shift()) } }