From c3a4164541bae20d662ab4c2d6a60f6a76a45b9b Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 25 Aug 2024 15:16:50 +0400 Subject: [PATCH] Debouncing of file updates in monitored dir Now updates to ZIM files that failed to be added to the library upon their appearance in a monitored dir are not handled immediately. Instead they are debounced (deferred/delayed by 1 second) and processed only after the file has been observed to be stable for some time (1 second as of this commit). --- src/contentmanager.cpp | 44 ++++++++++++++++++++++++++++++++++++++++-- src/contentmanager.h | 11 ++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 744ac29c..2fc6d3a9 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -928,7 +928,9 @@ const char* monitoredDirZimFileHandlingMsgs[] = { "it is being downloaded by us, ignoring...", "the file was added to the library", "the file could not be added to the library", - "it is an unchanged known bad zim file" + "it is an unchanged known bad zim file", + "deferring the check of an updated bad zim file", + "bad zim file was updated but a deferred request to check it is pending" }; #endif @@ -943,12 +945,26 @@ bool ContentManager::handleZimFileInMonitoredDirLogged(QString dir, QString file return status == MonitoredZimFileInfo::ADDED_TO_THE_LIBRARY; } +bool ContentManager::MonitoredZimFileInfo::fileKeepsBeingModified() const +{ + // A file is considered stable if it has stayed unchanged for at least + // this long. + const qint64 FILE_STABILITY_DURATION_MS = 1000; + + const QDateTime now = QDateTime::currentDateTime(); + return this->lastModified > now.addMSecs(-FILE_STABILITY_DURATION_MS); +} + void ContentManager::MonitoredZimFileInfo::updateStatus(const MonitoredZimFileInfo& prevInfo) { Q_ASSERT(prevInfo.status != ADDED_TO_THE_LIBRARY); if ( this->lastModified == prevInfo.lastModified ) { this->status = UNCHANGED_KNOWN_BAD_ZIM_FILE; + } else if ( prevInfo.status == PROCESS_LATER ) { + this->status = DEFERRED_PROCESSING_ALREADY_PENDING; + } else if ( this->fileKeepsBeingModified() ) { + this->status = PROCESS_LATER; } else { this->status = PROCESS_NOW; } @@ -980,7 +996,9 @@ int ContentManager::handleZimFileInMonitoredDir(QString dir, QString fileName) } MonitoredZimFileInfo zfi = getMonitoredZimFileInfo(dir, fileName); - if ( zfi.status == MonitoredZimFileInfo::PROCESS_NOW ) { + if ( zfi.status == MonitoredZimFileInfo::PROCESS_LATER ) { + deferHandlingOfZimFileInMonitoredDir(dir, fileName); + } else if ( zfi.status == MonitoredZimFileInfo::PROCESS_NOW ) { kiwix::Manager manager(mp_library->getKiwixLibrary()); const bool addedToLib = manager.addBookFromPath(bookPath.toStdString()); zfi.status = addedToLib @@ -1023,6 +1041,28 @@ void ContentManager::updateLibraryFromDir(QString dirPath) } } +void ContentManager::handleZimFileInMonitoredDirDeferred(QString dir, QString fileName) +{ + QMutexLocker locker(&m_updateFromDirMutex); + DBGOUT("ContentManager::handleZimFileInMonitoredDirDeferred(" << dir << ", " << fileName << ")"); + m_knownZimsInDir[dir][fileName].status = MonitoredZimFileInfo::PROCESS_NOW; + if ( handleZimFileInMonitoredDirLogged(dir, fileName) ) { + mp_library->save(); + emit(booksChanged()); + } +} + +void ContentManager::deferHandlingOfZimFileInMonitoredDir(QString dir, QString fname) +{ + const qint64 DEBOUNCING_DELAY_MILLISECONDS = 1000; + + m_knownZimsInDir[dir][fname].status = MonitoredZimFileInfo::PROCESS_LATER; + + QTimer::singleShot(DEBOUNCING_DELAY_MILLISECONDS, this, [=]() { + handleZimFileInMonitoredDirDeferred(dir, fname); + }); +} + bool ContentManager::handleDisappearedBook(QString bookId) { if ( KiwixApp::instance()->getTabWidget()->getTabZimIds().contains(bookId) ) diff --git a/src/contentmanager.h b/src/contentmanager.h index 6c209915..650db933 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -127,9 +127,16 @@ public slots: // the file couldn't be added to the library earlier and hasn't // changed since then - UNCHANGED_KNOWN_BAD_ZIM_FILE + UNCHANGED_KNOWN_BAD_ZIM_FILE, + + // try to add this file to the library at a later time + PROCESS_LATER, + + // this file is known to be enqueued for later processing + DEFERRED_PROCESSING_ALREADY_PENDING }; + bool fileKeepsBeingModified() const; void updateStatus(const MonitoredZimFileInfo& prevInfo); ZimFileStatus status = PROCESS_NOW; @@ -154,6 +161,8 @@ public slots: bool handleZimFileInMonitoredDirLogged(QString dirPath, QString fileName); int handleZimFileInMonitoredDir(QString dirPath, QString fileName); MonitoredZimFileInfo getMonitoredZimFileInfo(QString dir, QString fileName) const; + void deferHandlingOfZimFileInMonitoredDir(QString dir, QString fileName); + void handleZimFileInMonitoredDirDeferred(QString dirPath, QString fileName); bool handleDisappearedBook(QString bookId); // Get the book with the specified id from