Brummel 491b093b86 feat(watch): foreground SyncService with backoff worker loop
SyncWorkerLoop is the upload+poll core, mirrored from
doctate-client-core::server_sync::run. Pending uploads have priority
over polling (no point asking the server for state if we still hold
the doctor's audio). Backoff is in-process state — after restart it
drops back to 2s and gives the server one fresh chance, which beats
'wait 60s because we cancelled mid-backoff'.

Architecturally split into runOnce (single iteration, suspends only
on real I/O) and run (infinite loop, suspends on idle). The split
makes the loop directly testable on JVM virtual time without dealing
with advanceUntilIdle vs. infinite-while semantics — tests call
runOnce N times and assert in between.

Wired through:
- SyncService (foregroundServiceType=dataSync, low-importance silent
  notification, ServiceCompat.startForeground for API 34+)
- SyncServiceLauncher replaces NoopSyncTrigger in DoctateApp
- DoctateApp.onCreate kicks the service after StartupCleanup if the
  pending queue is non-empty (recovery from crash/reboot)
- AndroidManifest: FOREGROUND_SERVICE / FOREGROUND_SERVICE_DATA_SYNC /
  POST_NOTIFICATIONS perms; service declaration

6 SyncWorkerLoopTest cases (success/transient/terminal/idle/fifo plus
backoff-resets-after-success). 58 tests green total.
2026-04-26 23:51:58 +02:00
2026-04-26 14:36:22 +02:00
2026-04-18 10:03:40 +02:00
S
Description
No description provided
7.4 MiB
Languages
Rust 74%
Kotlin 12.7%
HTML 4.9%
Python 4.1%
Shell 3.8%
Other 0.5%