fix: flush pending filename index tasks on service exit to avoid full rescan - #265
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: Johnson-zs The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Reviewer's GuideShutdown now attempts to drain small pending filename-index backlogs within a bounded timeout, preserving a clean index when successful while retaining the existing Dirty fallback for large, timed-out, or unstartable work. Sequence diagram for bounded filename-index flush during shutdownsequenceDiagram
participant Service as FileNameIndexDBus
participant Manager as TaskManager
participant Worker as WorkerThread
participant State as StateStore
Service->>Manager: flushPendingTasks(5000)
alt no pending work
Manager-->>Service: true
else backlog exceeds 5000 or task cannot start
Manager-->>Service: false
Service->>State: setIndexState(Dirty)
else pending work within threshold
loop until queue empty or timeout
Manager->>Manager: schedule()
Manager->>Worker: quit()
Manager->>Worker: wait(remaining)
Worker-->>Manager: task completed
Manager->>Manager: finalizeIndexState()
end
alt all tasks completed
Manager-->>Service: true
else timeout
Manager-->>Service: false
Service->>State: setIndexState(Dirty)
end
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src/index/task/taskmanager.cpp" line_range="1172-1185" />
<code_context>
+ // processed because the main thread was blocked in wait(). Finalize
+ // the index state and clean up manually to prevent a stale
+ // onTaskFinished from firing later.
+ if (currentTask) {
+ const auto type = currentTask->taskType();
+ const bool succeeded = (currentTask->status() == IndexTask::Status::Finished);
+
+ if (succeeded) {
+ HandlerResult result;
+ result.success = true;
+ finalizeIndexState(type, result);
+ }
+
+ currentTask->disconnect();
+ currentTask->deleteLater();
+ currentTask = nullptr;
+ m_currentIncrementalPending = 0;
+ }
+ }
</code_context>
<issue_to_address>
**issue (broader_impact):** The manual completion path bypasses `onTaskFinished`, so successful flushed tasks never execute `handleRootPathFailure`, `updateIndexStatusOnSuccess`, failure bookkeeping, completion signals, or the normal `cleanupTask` bookkeeping. A flushed Create/Update task therefore can leave index-status metadata or recovery state stale even though `finalizeIndexState` marks the index clean.
**Triggers:** When a task completes during shutdown and its queued `onTaskFinished` callback is replaced by this manual cleanup.
**Suggested fix:** Refactor the common task-completion handling into a synchronous helper and invoke it from both `onTaskFinished` and the flush path, rather than calling only `finalizeIndexState`.
</issue_to_address>
### Comment 2
<location path="src/index/task/taskmanager.cpp" line_range="1172-1185" />
<code_context>
+ // processed because the main thread was blocked in wait(). Finalize
+ // the index state and clean up manually to prevent a stale
+ // onTaskFinished from firing later.
+ if (currentTask) {
+ const auto type = currentTask->taskType();
+ const bool succeeded = (currentTask->status() == IndexTask::Status::Finished);
+
+ if (succeeded) {
+ HandlerResult result;
+ result.success = true;
+ finalizeIndexState(type, result);
+ }
+
+ currentTask->disconnect();
+ currentTask->deleteLater();
+ currentTask = nullptr;
+ m_currentIncrementalPending = 0;
+ }
+ }
</code_context>
<issue_to_address>
**issue (bug_risk):** The flush path calls `currentTask->deleteLater()` after stopping and waiting for `workerThread`, but the deferred-delete event belongs to that worker thread and is not processed while the thread is stopped. The task object consequently remains allocated until the thread is restarted or the process exits, leaking each task flushed during shutdown.
**Triggers:** When cleanup is the final service shutdown and the worker thread is not restarted before TaskManager destruction.
**Suggested fix:** Destroy the completed task safely after the worker thread has stopped, or ensure its deferred deletion is delivered before abandoning the worker thread.
</issue_to_address>| if (currentTask) { | ||
| const auto type = currentTask->taskType(); | ||
| const bool succeeded = (currentTask->status() == IndexTask::Status::Finished); | ||
|
|
||
| if (succeeded) { | ||
| HandlerResult result; | ||
| result.success = true; | ||
| finalizeIndexState(type, result); | ||
| } | ||
|
|
||
| currentTask->disconnect(); | ||
| currentTask->deleteLater(); | ||
| currentTask = nullptr; | ||
| m_currentIncrementalPending = 0; |
There was a problem hiding this comment.
issue (broader_impact): The manual completion path bypasses onTaskFinished, so successful flushed tasks never execute handleRootPathFailure, updateIndexStatusOnSuccess, failure bookkeeping, completion signals, or the normal cleanupTask bookkeeping. A flushed Create/Update task therefore can leave index-status metadata or recovery state stale even though finalizeIndexState marks the index clean.
Triggers: When a task completes during shutdown and its queued onTaskFinished callback is replaced by this manual cleanup.
Suggested fix: Refactor the common task-completion handling into a synchronous helper and invoke it from both onTaskFinished and the flush path, rather than calling only finalizeIndexState.
| if (currentTask) { | ||
| const auto type = currentTask->taskType(); | ||
| const bool succeeded = (currentTask->status() == IndexTask::Status::Finished); | ||
|
|
||
| if (succeeded) { | ||
| HandlerResult result; | ||
| result.success = true; | ||
| finalizeIndexState(type, result); | ||
| } | ||
|
|
||
| currentTask->disconnect(); | ||
| currentTask->deleteLater(); | ||
| currentTask = nullptr; | ||
| m_currentIncrementalPending = 0; |
There was a problem hiding this comment.
issue (bug_risk): The flush path calls currentTask->deleteLater() after stopping and waiting for workerThread, but the deferred-delete event belongs to that worker thread and is not processed while the thread is stopped. The task object consequently remains allocated until the thread is restarted or the process exits, leaking each task flushed during shutdown.
Triggers: When cleanup is the final service shutdown and the worker thread is not restarted before TaskManager destruction.
Suggested fix: Destroy the completed task safely after the worker thread has stopped, or ensure its deferred deletion is delivered before abandoning the worker thread.
… rescan Log: FileNameIndexDBus::cleanup() immediately marked Dirty and stopped all tasks on exit, forcing a full rescan on next startup even when only a few incremental tasks remained. Add TaskManager::flushPendingTasks() which drains the task queue within a bounded 5 s timeout before cleanup gives up. A warning is logged whenever a real flush actually occurs, so the event is visible in logs. Influence: When the service exits with a small backlog, pending tasks are completed and the index stays Clean — no full rescan on restart. Large backlogs (> 5000 queued incremental events) skip flushing and fall back to the existing Dirty + StopCurrentTask() path, so shutdown is never blocked for too long. PMS: BUG-505079
45047f1 to
e6f51ae
Compare
faf25c1
into
linuxdeepin:develop/snipe-20260923
fix: flush pending filename index tasks on service exit to avoid full rescan
Log: FileNameIndexDBus::cleanup() immediately marked Dirty and stopped
all tasks on exit, forcing a full rescan on next startup even when only
a few incremental tasks remained. Add TaskManager::flushPendingTasks()
which drains the task queue within a bounded 5 s timeout before cleanup
gives up. A warning is logged whenever a real flush actually occurs, so
the event is visible in logs.
Influence: When the service exits with a small backlog, pending tasks are
completed and the index stays Clean — no full rescan on restart. Large
backlogs (> 5000 queued incremental events) skip flushing and fall back
to the existing Dirty + StopCurrentTask() path, so shutdown is never
blocked for too long.
PMS: BUG-505079
Summary by Sourcery
Flush manageable filename index work during shutdown while retaining a bounded dirty-state fallback for large or stalled backlogs.
Bug Fixes:
Enhancements: