Abort superseded watch starts before they queue any uploads - #24
Conversation
Previously a start_watching superseded mid-scan (by a stop or a newer start) had already enqueued the scanned files, so the uploads went out even though the watch never committed. Worst case: pick a huge folder by mistake, hit stop during the scan, and the app uploads it anyway. The initial scan now only collects file paths; enqueueing happens after the commit point (watcher installed under the generation check). The scan checks the generation per entry so a stop takes effect almost immediately, the watcher-event drain task drops events once the watch is no longer the newest request, and the stop-existing-watcher step is now generation-checked under the lock so a stale start can never tear down a watcher a newer request installed. The touched functions are generic over tauri::Runtime and doc-hidden pub so integration tests can drive the supersede logic with MockRuntime. Tests live in tests/ rather than #[cfg(test)] because on Windows only integration test targets receive the Common Controls v6 manifest from build.rs (rustc-link-arg-tests does not apply to unit test binaries, which crash at load with STATUS_ENTRYPOINT_NOT_FOUND). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
Claude finished @cohogan's task in 2m 30s —— View job Code Review: Abort superseded watch starts before they queue any uploads
This is a well-designed fix for a real and potentially painful bug (user picks wrong folder, hits stop, app uploads everything anyway). The "collect-then-commit" pattern is clean, and the per-entry supersede checks make cancellation responsive. Here's my detailed review: ArchitectureThe three-phase approach — scan, commit, enqueue — is the right design. Separating data collection from side effects (queueing) means a superseded start leaves no trace. The generation counter with Particularly well done:
Potential Concerns1. Partial enqueue after commit is invisible to the caller ( After the commit point, 2. One-event race in the drain task ( The generation check is at the top of the loop, so if a supersede happens while 3. If the commit succeeds and some files are enqueued before the enqueue is superseded by a stop, those files remain in the upload queue and will be uploaded. This was also true before this PR (so no regression), and likely intentional, but worth documenting if it isn't already. upload.rs ChangesMinimal and correct — just widening three function signatures from TestsThe test suite is thorough and well-structured. Good coverage of:
The One gap: there's no test for the drain task's generation check (watcher events being dropped after supersede). This would require async test infrastructure and is harder to test with Minor Notes
VerdictLooks good. The concurrency model is sound, the separation of scan/commit/enqueue cleanly addresses the root cause, and the tests cover the important race scenarios. No blocking issues. |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Claude finished @cohogan's task in 1m 16s —— View job Code Review: Abort superseded watch starts before they queue any uploads
ArchitectureThe three-phase approach — scan → commit → enqueue — is a clean design that eliminates the root cause: a superseded start can no longer leave orphaned uploads in the queue. The Key design wins:
Findings1. After the commit point at line 244, 2. One-event slip in the drain task — The generation check is at the top of the 3. If the commit succeeds and some files are enqueued before
|
Problem
Follow-up to the resume-watching PR. A
start_watchingthat got superseded mid-scan (bystop_watchingor a newer start) had already enqueued the entire folder into the upload queue — the generation check only prevented the watcher from installing, not the side effects. Worst case: a user picks a huge folder by mistake, hits stop during the initial scan, and the app uploads everything anyway. There was also a brief window where the new watcher was live before the commit check, so events for the abandoned folder could slip into the queue, and a theoretical race where a stale start could tear down a watcher a newer request had just installed.Fix
Tests
New
tests/watch_supersede.rs(10 tests, all passing) driving the realstart_watching_implwith Tauri'sMockRuntime: normal start commits and queues (ignore patterns respected), stale starts abort with zero side effects and don't disturb the current watcher, stop-superseded starts leave the queue empty, plus a threaded race test. The touched functions are now generic overtauri::Runtimeand exposed#[doc(hidden)] pubto make this possible.Note: tests are an integration-test target rather than
#[cfg(test)]unit tests because on Windows only integration test targets get the Common Controls v6 manifest from build.rs — unit test binaries crash at load withSTATUS_ENTRYPOINT_NOT_FOUND(rustc-link-arg-testsdoesn't apply to them).cargo test,cargo check, andcargo clippy --all-targetsare all clean.🤖 Generated with Claude Code