summaryrefslogtreecommitdiffhomepage
path: root/mullvad-api/src
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2022-04-27 15:23:46 +0200
committerDavid Lönnhager <david.l@mullvad.net>2022-04-29 10:38:11 +0200
commit18da51d971eebb19ff889d4ff8e6bc6b955a8a4f (patch)
tree520192429fab3612d73560cd25ce75945bec7bce /mullvad-api/src
parent9014cb5201fb8b47a495ac23abb9dbc309dff25b (diff)
downloadmullvadvpn-18da51d971eebb19ff889d4ff8e6bc6b955a8a4f.tar.xz
mullvadvpn-18da51d971eebb19ff889d4ff8e6bc6b955a8a4f.zip
Pause API requests when the daemon hasn't received any commands for 3 days
Diffstat (limited to 'mullvad-api/src')
-rw-r--r--mullvad-api/src/availability.rs87
1 files changed, 84 insertions, 3 deletions
diff --git a/mullvad-api/src/availability.rs b/mullvad-api/src/availability.rs
index 23c5e9f32b..f66fb4053a 100644
--- a/mullvad-api/src/availability.rs
+++ b/mullvad-api/src/availability.rs
@@ -1,11 +1,16 @@
use std::{
future::Future,
sync::{Arc, Mutex},
+ time::Duration,
};
use tokio::sync::broadcast;
const CHANNEL_CAPACITY: usize = 100;
+/// Pause background requests if [ApiAvailabilityHandle::reset_inactivity_timer] hasn't been
+/// called for this long.
+const INACTIVITY_TIME: Duration = Duration::from_secs(3 * 24 * 60 * 60);
+
#[derive(err_derive::Error, Debug)]
pub enum Error {
/// The [`ApiAvailability`] instance was dropped, or the receiver lagged behind.
@@ -18,6 +23,7 @@ pub struct State {
suspended: bool,
pause_background: bool,
offline: bool,
+ inactive: bool,
}
impl State {
@@ -26,7 +32,7 @@ impl State {
}
pub fn is_background_paused(&self) -> bool {
- self.offline || self.pause_background || self.suspended
+ self.offline || self.pause_background || self.suspended || self.inactive
}
pub fn is_offline(&self) -> bool {
@@ -37,13 +43,22 @@ impl State {
pub struct ApiAvailability {
state: Arc<Mutex<State>>,
tx: broadcast::Sender<State>,
+
+ inactivity_timer: Arc<Mutex<Option<tokio::task::JoinHandle<()>>>>,
}
impl ApiAvailability {
pub fn new(initial_state: State) -> Self {
let (tx, _rx) = broadcast::channel(CHANNEL_CAPACITY);
let state = Arc::new(Mutex::new(initial_state));
- ApiAvailability { state, tx }
+
+ let availability = ApiAvailability {
+ state,
+ tx,
+ inactivity_timer: Arc::new(Mutex::new(None)),
+ };
+ availability.handle().reset_inactivity_timer();
+ availability
}
pub fn get_state(&self) -> State {
@@ -54,6 +69,15 @@ impl ApiAvailability {
ApiAvailabilityHandle {
state: self.state.clone(),
tx: self.tx.clone(),
+ inactivity_timer: self.inactivity_timer.clone(),
+ }
+ }
+}
+
+impl Drop for ApiAvailability {
+ fn drop(&mut self) {
+ if let Some(timer) = self.inactivity_timer.lock().unwrap().take() {
+ timer.abort();
}
}
}
@@ -62,9 +86,45 @@ impl ApiAvailability {
pub struct ApiAvailabilityHandle {
state: Arc<Mutex<State>>,
tx: broadcast::Sender<State>,
+ inactivity_timer: Arc<Mutex<Option<tokio::task::JoinHandle<()>>>>,
}
impl ApiAvailabilityHandle {
+ /// Reset task that automatically pauses API requests due inactivity,
+ /// starting it if it's not currently running.
+ pub fn reset_inactivity_timer(&self) {
+ log::trace!("Restarting API inactivity check");
+
+ let self_ = self.clone();
+
+ let mut inactivity_timer = self.inactivity_timer.lock().unwrap();
+ if let Some(timer) = inactivity_timer.take() {
+ timer.abort();
+ }
+
+ self.set_active();
+
+ *inactivity_timer = Some(tokio::spawn(async move {
+ talpid_time::sleep(INACTIVITY_TIME).await;
+ self_.set_inactive();
+ }));
+ }
+
+ /// Stops timer that pauses API requests due to inactivity.
+ pub fn stop_inactivity_timer(&self) {
+ log::trace!("Stopping API inactivity check");
+
+ let mut inactivity_timer = self.inactivity_timer.lock().unwrap();
+ if let Some(timer) = inactivity_timer.take() {
+ timer.abort();
+ }
+ self.set_active();
+ }
+
+ fn inactivity_timer_running(&self) -> bool {
+ self.inactivity_timer.lock().unwrap().is_some()
+ }
+
pub fn suspend(&self) {
let mut state = self.state.lock().unwrap();
if !state.suspended {
@@ -96,15 +156,36 @@ impl ApiAvailabilityHandle {
}
pub fn resume_background(&self) {
+ if self.inactivity_timer_running() {
+ self.reset_inactivity_timer();
+ }
+
let mut state = self.state.lock().unwrap();
if state.pause_background {
log::debug!("Resuming background API requests");
-
state.pause_background = false;
let _ = self.tx.send(*state);
}
}
+ fn set_inactive(&self) {
+ let mut state = self.state.lock().unwrap();
+ if !state.inactive {
+ log::debug!("Pausing background API requests due to inactivity");
+ state.inactive = true;
+ let _ = self.tx.send(*state);
+ }
+ }
+
+ fn set_active(&self) {
+ let mut state = self.state.lock().unwrap();
+ if state.inactive {
+ log::debug!("Resuming background API requests due to activity");
+ state.inactive = false;
+ let _ = self.tx.send(*state);
+ }
+ }
+
pub fn set_offline(&self, offline: bool) {
let mut state = self.state.lock().unwrap();
if state.offline != offline {