diff options
| author | David Lönnhager <david.l@mullvad.net> | 2023-09-17 15:54:18 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2023-09-19 14:01:12 +0200 |
| commit | ae6a4a1d9fba88aa6b3a23f6fe1252bf474e99eb (patch) | |
| tree | b358c0555b851df9b9ddbd8ec9bdf623b67d8ab0 | |
| parent | a93b710585d97f47d577a442209cf6730af65ace (diff) | |
| download | mullvadvpn-ae6a4a1d9fba88aa6b3a23f6fe1252bf474e99eb.tar.xz mullvadvpn-ae6a4a1d9fba88aa6b3a23f6fe1252bf474e99eb.zip | |
Define retry strategy constants
| -rw-r--r-- | mullvad-daemon/src/device/service.rs | 41 | ||||
| -rw-r--r-- | mullvad-relay-selector/src/updater.rs | 12 | ||||
| -rw-r--r-- | talpid-core/src/future_retry.rs | 27 |
3 files changed, 35 insertions, 45 deletions
diff --git a/mullvad-daemon/src/device/service.rs b/mullvad-daemon/src/device/service.rs index c1aba7b748..74dc15b94f 100644 --- a/mullvad-daemon/src/device/service.rs +++ b/mullvad-daemon/src/device/service.rs @@ -21,9 +21,10 @@ use talpid_core::future_retry::{ const RETRY_ACTION_INTERVAL: Duration = Duration::ZERO; const RETRY_ACTION_MAX_RETRIES: usize = 2; -const RETRY_BACKOFF_INTERVAL_INITIAL: Duration = Duration::from_secs(4); -const RETRY_BACKOFF_INTERVAL_FACTOR: u32 = 5; -const RETRY_BACKOFF_INTERVAL_MAX: Duration = Duration::from_secs(24 * 60 * 60); +const RETRY_BACKOFF_STRATEGY: Jittered<ExponentialBackoff> = Jittered::jitter( + ExponentialBackoff::new(Duration::from_secs(4), 5) + .max_delay(Some(Duration::from_secs(24 * 60 * 60))), +); #[derive(Clone)] pub struct DeviceService { @@ -87,7 +88,7 @@ impl DeviceService { let (device, addresses) = retry_future( move || api_handle.when_online(proxy.create(token_copy.clone(), pubkey.clone())), should_retry_backoff, - retry_strategy(), + RETRY_BACKOFF_STRATEGY, ) .await .map_err(map_rest_error)?; @@ -141,18 +142,12 @@ impl DeviceService { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); - let retry_strategy = Jittered::jitter( - ExponentialBackoff::new( - RETRY_BACKOFF_INTERVAL_INITIAL, - RETRY_BACKOFF_INTERVAL_FACTOR, - ), // Not setting a maximum interval - ); - retry_future( // NOTE: Not honoring "paused" state, because the account may have no time on it. move || api_handle.when_online(proxy.remove(token.clone(), device.clone())), should_retry_backoff, - retry_strategy, + // Not setting a maximum interval + RETRY_BACKOFF_STRATEGY.clone().max_delay(None), ) .await .map_err(map_rest_error)?; @@ -197,6 +192,8 @@ impl DeviceService { let api_handle = self.api_availability.clone(); let pubkey = private_key.public_key(); + let rotate_retry_strategy = std::iter::repeat(Duration::from_secs(24 * 60 * 60)); + let addresses = retry_future( move || { api_handle.when_bg_resumes(proxy.replace_wg_key( @@ -206,7 +203,7 @@ impl DeviceService { )) }, should_retry_backoff, - rotate_retry_strategy(), + rotate_retry_strategy, ) .await .map_err(map_rest_error)?; @@ -241,7 +238,7 @@ impl DeviceService { retry_future( move || api_handle.when_online(proxy.list(token.clone())), should_retry_backoff, - retry_strategy(), + RETRY_BACKOFF_STRATEGY, ) .await .map_err(map_rest_error) @@ -361,7 +358,7 @@ pub fn spawn_account_service( async move { handle_expiry_result_inner(&expiry_fut.await, &api_availability_copy) } }; let should_retry = move |state_was_updated: &bool| -> bool { !*state_was_updated }; - retry_future(future_generator, should_retry, retry_strategy()).await; + retry_future(future_generator, should_retry, RETRY_BACKOFF_STRATEGY).await; }); tokio::spawn(future); @@ -433,17 +430,3 @@ fn map_rest_error(error: rest::Error) -> Error { error => Error::OtherRestError(error), } } - -fn retry_strategy() -> Jittered<ExponentialBackoff> { - Jittered::jitter( - ExponentialBackoff::new( - RETRY_BACKOFF_INTERVAL_INITIAL, - RETRY_BACKOFF_INTERVAL_FACTOR, - ) - .max_delay(RETRY_BACKOFF_INTERVAL_MAX), - ) -} - -fn rotate_retry_strategy() -> impl Iterator<Item = Duration> { - std::iter::repeat(RETRY_BACKOFF_INTERVAL_MAX) -} diff --git a/mullvad-relay-selector/src/updater.rs b/mullvad-relay-selector/src/updater.rs index 31299eea14..6600efb02f 100644 --- a/mullvad-relay-selector/src/updater.rs +++ b/mullvad-relay-selector/src/updater.rs @@ -23,8 +23,10 @@ const UPDATE_CHECK_INTERVAL: Duration = Duration::from_secs(60 * 15); /// How old the cached relays need to be to trigger an update const UPDATE_INTERVAL: Duration = Duration::from_secs(60 * 60); -const EXPONENTIAL_BACKOFF_INITIAL: Duration = Duration::from_secs(16); -const EXPONENTIAL_BACKOFF_FACTOR: u32 = 8; +const DOWNLOAD_RETRY_STRATEGY: Jittered<ExponentialBackoff> = Jittered::jitter( + ExponentialBackoff::new(Duration::from_secs(16), 8) + .max_delay(Some(Duration::from_secs(2 * 60 * 60))), +); #[derive(Clone)] pub struct RelayListUpdaterHandle { @@ -161,14 +163,10 @@ impl RelayListUpdater { } }; - let exponential_backoff = - ExponentialBackoff::new(EXPONENTIAL_BACKOFF_INITIAL, EXPONENTIAL_BACKOFF_FACTOR) - .max_delay(UPDATE_INTERVAL * 2); - retry_future( download_futures, |result| result.is_err(), - Jittered::jitter(exponential_backoff), + DOWNLOAD_RETRY_STRATEGY, ) } diff --git a/talpid-core/src/future_retry.rs b/talpid-core/src/future_retry.rs index 604e4513e1..f5dc7a8f72 100644 --- a/talpid-core/src/future_retry.rs +++ b/talpid-core/src/future_retry.rs @@ -1,5 +1,5 @@ use rand::{distributions::OpenClosed01, Rng}; -use std::{future::Future, time::Duration}; +use std::{future::Future, ops::Deref, time::Duration}; use talpid_time::sleep; /// Convenience function that works like [`retry_future`] but limits the number @@ -50,6 +50,7 @@ pub fn constant_interval(interval: Duration) -> impl Iterator<Item = Duration> { } /// Provides an exponential back-off timer to delay the next retry of a failed operation. +#[derive(Clone)] pub struct ExponentialBackoff { next: Duration, factor: u32, @@ -61,7 +62,7 @@ impl ExponentialBackoff { /// /// All else staying the same, the first delay will be `initial` long, the second /// one will be `initial * factor`, third `initial * factor^2` and so on. - pub fn new(initial: Duration, factor: u32) -> ExponentialBackoff { + pub const fn new(initial: Duration, factor: u32) -> ExponentialBackoff { ExponentialBackoff { next: initial, factor, @@ -71,8 +72,8 @@ impl ExponentialBackoff { /// Set the maximum delay. By default, there is no maximum value set. The limit is /// `Duration::MAX`. - pub fn max_delay(mut self, duration: Duration) -> ExponentialBackoff { - self.max_delay = Some(duration); + pub const fn max_delay(mut self, duration: Option<Duration>) -> ExponentialBackoff { + self.max_delay = duration; self } @@ -100,13 +101,13 @@ impl Iterator for ExponentialBackoff { } /// Adds jitter to a duration iterator -pub struct Jittered<I: Iterator<Item = Duration>> { +pub struct Jittered<I> { inner: I, } -impl<I: Iterator<Item = Duration>> Jittered<I> { +impl<I> Jittered<I> { /// Create an iterator of jittered durations - pub fn jitter(inner: I) -> Self { + pub const fn jitter(inner: I) -> Self { Self { inner } } } @@ -119,6 +120,14 @@ impl<I: Iterator<Item = Duration>> Iterator for Jittered<I> { } } +impl<I> Deref for Jittered<I> { + type Target = I; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + /// Apply a jitter to a duration. fn jitter(dur: Duration) -> Duration { apply_jitter(dur, rand::thread_rng().sample(OpenClosed01)) @@ -158,7 +167,7 @@ mod test { #[test] fn test_maximum_bound() { let mut backoff = ExponentialBackoff::new(Duration::from_millis(2), 3) - .max_delay(Duration::from_millis(7)); + .max_delay(Some(Duration::from_millis(7))); assert_eq!(backoff.next(), Some(Duration::from_millis(2))); assert_eq!(backoff.next(), Some(Duration::from_millis(6))); @@ -207,7 +216,7 @@ mod test { || async { 0 }, |_| true, ExponentialBackoff::new(retry_interval_initial, retry_interval_factor) - .max_delay(retry_interval_max), + .max_delay(Some(retry_interval_max)), 5, ) .await; |
