summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2023-09-17 15:54:18 +0200
committerDavid Lönnhager <david.l@mullvad.net>2023-09-19 14:01:12 +0200
commitae6a4a1d9fba88aa6b3a23f6fe1252bf474e99eb (patch)
treeb358c0555b851df9b9ddbd8ec9bdf623b67d8ab0
parenta93b710585d97f47d577a442209cf6730af65ace (diff)
downloadmullvadvpn-ae6a4a1d9fba88aa6b3a23f6fe1252bf474e99eb.tar.xz
mullvadvpn-ae6a4a1d9fba88aa6b3a23f6fe1252bf474e99eb.zip
Define retry strategy constants
-rw-r--r--mullvad-daemon/src/device/service.rs41
-rw-r--r--mullvad-relay-selector/src/updater.rs12
-rw-r--r--talpid-core/src/future_retry.rs27
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;