coven/handle_sync.rs
1//! Starting, stopping and requesting sync passes on the handle's loop (E5).
2use crate::*;
3
4impl CovenHandle {
5 /// Start syncing; the first pass builds an absent client from custody
6 /// credentials and backs off like any failed pass. Already running or
7 /// unconfigured stores do nothing.
8 pub async fn start_sync(&self) -> Result<(), SyncError> {
9 self.storage.start().await
10 }
11 /// Stop syncing: `coven_retry_effect` says sync isn't running and the
12 /// waiting retries are answered `NotSyncing` first; then the active pass
13 /// and transfers finish, the provider client is released and the
14 /// location recorded as custody holds it, and this returns. Once it has,
15 /// no pass or upload runs until sync starts again, whatever connects the
16 /// handle meanwhile. Keys remain unlocked for the
17 /// handle session. A `start_sync` asked meanwhile starts after it, and
18 /// dropping this future leaves stopping to finish. Stopping changes
19 /// nothing the sync state reads; a release failure is recorded as the
20 /// last pass's failure and returned. A failure writing either row has
21 /// failed the handle; stopping goes on and the failure is returned.
22 pub async fn stop_sync(&self) -> Result<(), SyncError> {
23 self.storage.stop().await
24 }
25 /// Request a pass while started. Requests during a pass, and local writes
26 /// committed during it, retain one more pass; the pass's own bookkeeping
27 /// retains none. A failed connection's backoff and a provider cooldown
28 /// hold requests until they end.
29 pub fn sync_now(&self) {
30 self.storage.sync_now();
31 }
32 /// The person asked to retry everything now, such as by pulling to
33 /// refresh. Every ordinary backoff ends, answered or not: the
34 /// connection's, operations' and uploads'; a pass runs now. Provider cooldowns hold, and failures that never retry stay. An
35 /// ended wait keeps its failure count, so a retry that fails again waits
36 /// the next longer delay. Requests coalesce as `sync_now` requests do.
37 ///
38 /// The retry takes effect once this returns, with the answer as a
39 /// future, which resolves at once as `coven_retry_effect` says when no
40 /// pass runs for it: `CoolingDown` with when the provider cooldown ends,
41 /// `Failed` with a failure only the person can clear, or `NotSyncing`
42 /// while sync is stopped. Otherwise it resolves when the first pass
43 /// after the retry ends: `Synced`, or `Failed` with why. A closed handle
44 /// answers `NotSyncing`. Dropping the future leaves the retry in place.
45 /// Deciding the answer writes the retry effect's row; a failed write has
46 /// failed the handle, and is returned.
47 pub async fn retry_now(&self) -> Result<RetryAnswer, SyncError> {
48 Ok(self.waits.retry_requested().await?)
49 }
50 /// Hold the connection's passes, or let them run again, with sync left
51 /// as it is: a test runs uploads with no pass beside them so.
52 #[cfg(test)]
53 pub(crate) async fn test_hold_passes(&self, held: bool) {
54 self.storage.hold_passes(held).await;
55 }
56 /// Follow `coven_retry_effect` with a live query, as an app does (E5).
57 #[cfg(any(test, feature = "test-utils"))]
58 pub fn test_retry_effect(&self) -> coven_database::test_utils::Followed<RetryEffect, DbError> {
59 RetryEffect::follow(&self.database)
60 }
61 /// Run idle passes at most `interval` apart, instead of every 30
62 /// seconds, until the returned guard drops, such as while a screen
63 /// waits for another device. With several guards held, the shortest
64 /// interval wins; once the last drops, idle passes return to every 30
65 /// seconds. The next idle pass comes `interval` after the last pass
66 /// ended, so one that is already due runs at once. Connection backoff
67 /// and provider cooldowns still hold every pass. The request outlives
68 /// stopping and starting sync, and does nothing while sync is stopped.
69 pub fn sync_often(&self, interval: std::time::Duration) -> SyncOftenGuard {
70 self.state.sync_often(interval)
71 }
72}
73
74#[cfg(test)]
75#[path = "handle_sync_tests.rs"]
76mod tests;