Watcher: Move manual-mode uploads to a dedicated worker thread - #113
Merged
Conversation
Manual-mode upload-queue polling ran on the heartbeat tick, so a slow or large upload delayed heartbeats and the dashboard flagged busy watchers as offline (prompting operator restarts). On stop, a long upload could also outlive the heartbeat join and write to the state DB after close, raising "Cannot operate on a closed database". Introduce `UploadQueueWorker`, a long-lived thread that owns the poll loop and shares a stop event with `Uploader` so shutdown can interrupt the retry backoff and abort between queued files. `stop_runtime` now stops the worker before closing the state DB, skipping the close if it can't stop in time, restoring the writer-threads-joined-before-close invariant. Bumps the watcher version to 0.4.0. Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Manual-mode upload-queue polling ran on the heartbeat tick, so a slow or large upload delayed heartbeats and the dashboard flagged busy watchers as offline (prompting operator restarts). On stop, a long-running upload could also outlive the heartbeat join and write to the state DB after
close(), raisingsqlite3.ProgrammingError: Cannot operate on a closed database.This moves manual-mode uploads off the heartbeat thread onto a dedicated long-lived worker and fixes the shutdown ordering.
UploadQueueWorker(inuploader.py): owns the poll loop on its own thread and polls everyUPLOAD_POLL_INTERVAL_SECONDS(60s), decoupled from the heartbeat.Uploaderan optional sharedstop_event: the retry backoff waits on it (interruptible),poll_upload_queuebails out between files on shutdown, and a stop mid-upload returnsFalse(defer, not a spurious failure event).runtime:build_runtimebuilds a worker in manual mode only (Nonein auto mode);start_runtimestarts it before the initial scan;_on_tickno longer polls.stop_runtimestops the worker beforestate_db.close(), and skips the close if the worker can't stop withinUPLOAD_WORKER_STOP_TIMEOUT_SECONDS(30s), restoring the writer-threads-joined-before-close invariantStateDB.closedocuments.0.4.0; updatedeveloper-docs/reference/watcher.md.Auto mode is unchanged: uploads still run on the monitor's stability-checker thread via the run detector's callback.
Test plan
make py-check(ruff format + lint + pyright) cleanstop_runtimeconditional-close orderingMade with Cursor