mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-04-23 16:47:54 -04:00
Throttle our retries when attempting cross-signing reset, and give up after a time limit (#6325)
Related to https://github.com/element-hq/element-x-android/pull/6420 Part of https://github.com/element-hq/element-x-android/issues/5075 I noticed when investigating a bug about resetting your identity when using a MAS login that we poll the server checking whether the user has given us permission with no limit on how fast we poll, and with no ability to give up if it's not working. This change causes us to retry only twice per second, and give up after 2 minutes. These are guesses as to the right values and I am open to discussion.
This commit is contained in:
@@ -8,6 +8,9 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
### Features
|
||||
|
||||
- [**breaking**] `matrix_sdk::error::Error` has a new variant `Timeout` which occurs when
|
||||
a cross-signing reset does not succeed after some period of time.
|
||||
([#6325](https://github.com/matrix-org/matrix-rust-sdk/pull/6325))
|
||||
- The `beacon_info` start event ([MSC3672](https://github.com/matrix-org/matrix-spec-proposals/pull/3672))
|
||||
is now included when computing the latest event for a room, so live location sharing
|
||||
sessions can be surfaced as a room's most recent activity.
|
||||
|
||||
@@ -25,6 +25,7 @@ use std::{
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use eyeball::{SharedObservable, Subscriber};
|
||||
@@ -48,6 +49,7 @@ use matrix_sdk_base::{
|
||||
},
|
||||
},
|
||||
},
|
||||
sleep::sleep,
|
||||
};
|
||||
use matrix_sdk_common::{executor::spawn, locks::Mutex as StdMutex};
|
||||
use ruma::{
|
||||
@@ -298,27 +300,50 @@ impl CrossSigningResetHandle {
|
||||
/// authentication to be done on the side of the OAuth 2.0 server or by
|
||||
/// providing additional [`AuthData`] the homeserver requires.
|
||||
pub async fn auth(&self, auth: Option<AuthData>) -> Result<()> {
|
||||
let mut upload_request = self.upload_request.clone();
|
||||
upload_request.auth = auth;
|
||||
// Poll to see whether the reset has been authorized twice per second.
|
||||
const RETRY_EVERY: Duration = Duration::from_millis(500);
|
||||
|
||||
while let Err(e) = self.client.send(upload_request.clone()).await {
|
||||
if *self.is_cancelled.lock().await {
|
||||
return Ok(());
|
||||
}
|
||||
// Give up after two minutes of polling.
|
||||
const TIMEOUT: Duration = Duration::from_mins(2);
|
||||
|
||||
match e.as_uiaa_response() {
|
||||
Some(uiaa_info) => {
|
||||
if uiaa_info.auth_error.is_some() {
|
||||
return Err(e.into());
|
||||
}
|
||||
tokio::time::timeout(TIMEOUT, async {
|
||||
let mut upload_request = self.upload_request.clone();
|
||||
upload_request.auth = auth;
|
||||
|
||||
debug!(
|
||||
"Repeatedly PUTting to keys/device_signing/upload until it works \
|
||||
or we hit a permanent failure."
|
||||
);
|
||||
while let Err(e) = self.client.send(upload_request.clone()).await {
|
||||
if *self.is_cancelled.lock().await {
|
||||
return Ok(());
|
||||
}
|
||||
None => return Err(e.into()),
|
||||
|
||||
match e.as_uiaa_response() {
|
||||
Some(uiaa_info) => {
|
||||
if uiaa_info.auth_error.is_some() {
|
||||
return Err(e.into());
|
||||
}
|
||||
}
|
||||
None => return Err(e.into()),
|
||||
}
|
||||
|
||||
debug!(
|
||||
"PUT to keys/device_signing/upload failed with 401. Retrying after \
|
||||
a short delay."
|
||||
);
|
||||
sleep(RETRY_EVERY).await;
|
||||
}
|
||||
}
|
||||
|
||||
self.client.send(self.signatures_request.clone()).await?;
|
||||
self.client.send(self.signatures_request.clone()).await?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
.unwrap_or_else(|_| {
|
||||
warn!("Timed out waiting for keys/device_signing/upload to succeed.");
|
||||
Err(Error::Timeout)
|
||||
})
|
||||
}
|
||||
|
||||
/// Cancel the ongoing identity reset process
|
||||
|
||||
@@ -417,6 +417,10 @@ pub enum Error {
|
||||
/// An error happened while attempting to change power levels.
|
||||
#[error("power levels error: {0}")]
|
||||
PowerLevels(#[from] PowerLevelsError),
|
||||
|
||||
/// We timed out attempting to complete an operation.
|
||||
#[error("timed out")]
|
||||
Timeout,
|
||||
}
|
||||
|
||||
#[rustfmt::skip] // stop rustfmt breaking the `<code>` in docs across multiple lines
|
||||
|
||||
Reference in New Issue
Block a user