fix: get_connectivity(): Get rid of locking SchedulerState::inner (#7124)

`get_connectivity()` is expected to return immediately, not when the scheduler finishes updating its
state in `start_io()/stop_io()/pause_io()`, otherwise it causes app non-responsiveness.

Instead of read-locking `SchedulerState::inner`, store the `ConnectivityStore` collection in
`Context` and fetch it from there in `get_connectivity()`. Update it every time we release a write
lock on `SchedulerState::inner`.
This commit is contained in:
iequidoo
2025-08-20 11:59:15 -03:00
committed by iequidoo
parent 3656337d41
commit 6837874d43
6 changed files with 44 additions and 33 deletions

View File

@@ -272,16 +272,7 @@ impl Context {
///
/// If the connectivity changes, a DC_EVENT_CONNECTIVITY_CHANGED will be emitted.
pub async fn get_connectivity(&self) -> Connectivity {
let lock = self.scheduler.inner.read().await;
let stores: Vec<_> = match *lock {
InnerSchedulerState::Started(ref sched) => sched
.boxes()
.map(|b| b.conn_state.state.connectivity.clone())
.collect(),
_ => return Connectivity::NotConnected,
};
drop(lock);
let stores = self.connectivities.lock().clone();
let mut connectivities = Vec::new();
for s in stores {
if let Some(connectivity) = s.get_basic().await {
@@ -291,7 +282,18 @@ impl Context {
connectivities
.into_iter()
.min()
.unwrap_or(Connectivity::Connected)
.unwrap_or(Connectivity::NotConnected)
}
pub(crate) fn update_connectivities(&self, sched: &InnerSchedulerState) {
let stores: Vec<_> = match sched {
InnerSchedulerState::Started(sched) => sched
.boxes()
.map(|b| b.conn_state.state.connectivity.clone())
.collect(),
_ => Vec::new(),
};
*self.connectivities.lock() = stores;
}
/// Get an overview of the current connectivity, and possibly more statistics.