From 108174e04036bf59a1d3cedee30df9c526f46d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Thu, 24 Apr 2025 09:40:39 +0200 Subject: [PATCH] session: Sleep between failed sync attempts --- src/session/model/session.rs | 68 +++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/src/session/model/session.rs b/src/session/model/session.rs index cb870c89..ab1f77c7 100644 --- a/src/session/model/session.rs +++ b/src/session/model/session.rs @@ -13,7 +13,7 @@ use ruma::{ }, assign, }; -use tokio::task::AbortHandle; +use tokio::{task::AbortHandle, time::sleep}; use tokio_stream::wrappers::BroadcastStream; use tracing::{debug, error, info}; @@ -38,7 +38,13 @@ use crate::{ const SESSION_PROFILE_KEY: &str = "session_profile"; /// The number of consecutive missed synchronizations before the session is /// marked as offline. -const MISSED_SYNC_MAX_COUNT: u8 = 3; +/// +/// Note that this is set to `2`, but the count begins at `0` so this would +/// match the third missed synchronization. +const MISSED_SYNC_OFFLINE_COUNT: usize = 2; +/// The delays in seconds to wait for when a sync fails, depending on the number +/// of missed attempts. +const MISSED_SYNC_DELAYS: &[u64] = &[1, 5, 10, 20, 30]; /// The state of the session. #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, glib::Enum)] @@ -104,8 +110,8 @@ mod imp { homeserver_reachable_source: RefCell>, /// The number of missed synchonizations in a row. /// - /// Capped at `MISSED_SYNC_MAX_COUNT - 1`. - missed_sync_count: Cell, + /// Capped at `MISSED_SYNC_DELAYS.len() - 1`. + missed_sync_count: Cell, } #[glib::object_subclass] @@ -272,6 +278,8 @@ mod imp { #[weak(rename_to = imp)] self, move || { + imp.homeserver_reachable_source.take(); + spawn!(async move { imp.update_homeserver_reachable().await; }); @@ -429,13 +437,24 @@ mod imp { while let Some(response) = sync_stream.next().await { let obj_weak = obj_weak.clone(); let ctx = glib::MainContext::default(); - ctx.spawn(async move { - spawn!(async move { - if let Some(obj) = obj_weak.upgrade() { - obj.imp().handle_sync_response(response); - } - }); - }); + let delay = ctx + .spawn(async move { + spawn!(async move { + if let Some(obj) = obj_weak.upgrade() { + obj.imp().handle_sync_response(response) + } else { + None + } + }) + .await + .expect("task was not aborted") + }) + .await + .expect("task was not aborted"); + + if let Some(delay) = delay { + sleep(delay).await; + } } }) .abort_handle(); @@ -444,7 +463,13 @@ mod imp { } /// Handle the response received via sync. - fn handle_sync_response(&self, response: Result) { + /// + /// Returns the delay to wait for before making the next sync, if + /// necessary. + fn handle_sync_response( + &self, + response: Result, + ) -> Option { let obj = self.obj(); let session_id = obj.session_id(); debug!(session = session_id, "Received sync response"); @@ -460,16 +485,27 @@ mod imp { self.set_offline(false); self.missed_sync_count.set(0); + + None } Err(error) => { - let missed_sync_count = self.missed_sync_count.get() + 1; + let missed_sync_count = self.missed_sync_count.get(); - if missed_sync_count >= MISSED_SYNC_MAX_COUNT { + // If there are too many failed attempts, mark the session as offline. + if missed_sync_count == MISSED_SYNC_OFFLINE_COUNT { self.set_offline(true); - } else { - self.missed_sync_count.set(missed_sync_count); } + + // Increase the count of missed syncs, if we have not reached the maximum value. + if missed_sync_count < 4 { + self.missed_sync_count.set(missed_sync_count + 1); + } + error!(session = session_id, "Could not perform sync: {error}"); + + // Sleep a little between attempts. + let delay = MISSED_SYNC_DELAYS[missed_sync_count]; + Some(Duration::from_secs(delay)) } } }