Refactor upload and polling logic

This commit consolidates the upload and polling functionalities into a
single `ServerSync` worker. The `oneliner_poller` and `uploader` modules
have been removed, and their responsibilities are now handled by
`server_sync`.

The `ServerSync` worker manages both uploading pending recordings and
polling the `/api/oneliners` endpoint. Uploads take precedence, and
polling only occurs when the pending upload directory is empty. The
worker now uses a unified HTTP client and a single `tokio::select!` loop
for managing these tasks.

Key changes include:
- Removal of `oneliner_poller.rs` and `uploader.rs`.
- Introduction of `server_sync.rs` and `upload.rs` in
  `doctate-client-core`.
- `ServerSync` now handles upload events (`UploadEvent`) and provides a
  `WorkerSnapshot` for UI feedback.
- Upload logic has been refactored to handle transient and terminal
  errors more robustly, including file deletion for terminal failures.
- Polling logic is integrated into the `ServerSync` loop, utilizing the
  existing `SnapshotCache` and `CaseStore`.
- The `App` component in `client-desktop` has been updated to use
  `ServerSync` instead of the separate poller and uploader.
- Documentation comments have been updated to reflect the new structure.
This commit is contained in:
2026-04-18 13:24:38 +02:00
parent cab71e6a26
commit 305d739f56
10 changed files with 1473 additions and 1169 deletions
+4 -3
View File
@@ -648,9 +648,10 @@ async fn undo_delete_restores_latest_batch_only() {
// Two separate delete clicks → two distinct batches.
let _ = app.clone().oneshot(delete_request(case_a, &cookie)).await.unwrap();
// Ensure timestamps differ at sub-second resolution (RFC3339 includes
// fractional seconds via the Rfc3339 well-known format).
tokio::time::sleep(Duration::from_millis(20)).await;
// Batch IDs derive from `now_rfc3339()`, which rounds to whole
// seconds — so the sleep must cross a second boundary for the two
// deletes to land in distinct batches.
tokio::time::sleep(Duration::from_millis(1100)).await;
let _ = app.clone().oneshot(delete_request(case_b, &cookie)).await.unwrap();
let undo = app