fix(#2095): retry secondary matrix account bring-up on transient failure
On a transient error (network blip, DNS not ready, homeserver 5xx) a secondary account's bring-up was immediately skipped for the entire daemon lifetime. This bit janet's catgirl account repeatedly when the host DNS resolver wasn't ready at daemon start — the account would silently disappear until the next restart. Add a PermanentBringUpError sentinel in client.rs so callers can distinguish M_UNKNOWN_TOKEN (stale/expired token — permanent, don't retry) from transient network/homeserver errors. In main.rs, replace the immediate skip with a bounded retry loop for secondary accounts: up to 4 attempts with 2s/5s/15s/30s backoffs (~52s total wait). On a transient error the daemon now stays alive serving the primary and any other healthy accounts while the failing secondary gets another chance. Permanent failures (PermanentBringUpError) still skip immediately with no retry. The primary account keep its existing behaviour: fatal on non-permanent error so systemd restarts the whole daemon (systemd is the right retry mechanism for primary bring-up failure).
This commit is contained in:
parent
6f3e400903
commit
a1cd50610a
2 changed files with 97 additions and 8 deletions
|
|
@ -29,6 +29,25 @@ use matrix_sdk::{
|
|||
use serde::Deserialize;
|
||||
use tokio::fs;
|
||||
|
||||
/// Sentinel returned when `build_and_restore` detects that the token is
|
||||
/// permanently invalid (M_UNKNOWN_TOKEN). The token has already been
|
||||
/// removed from disk. Callers should NOT retry — the account needs
|
||||
/// re-provisioning by hive-c0re.
|
||||
///
|
||||
/// Distinct from the general `anyhow::Error` path so callers can use
|
||||
/// `err.downcast_ref::<PermanentBringUpError>()` to distinguish "retry
|
||||
/// won't help" from a transient network/DNS/5xx failure.
|
||||
#[derive(Debug)]
|
||||
pub struct PermanentBringUpError(pub String);
|
||||
|
||||
impl std::fmt::Display for PermanentBringUpError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for PermanentBringUpError {}
|
||||
|
||||
/// Subset of the `/_matrix/client/v3/account/whoami` response we care
|
||||
/// about. matrix-spec field names; `device_id` is optional per spec
|
||||
/// (servers MAY omit it for legacy bearer scopes) but tuwunel always
|
||||
|
|
@ -112,11 +131,11 @@ pub async fn build_and_restore(
|
|||
// Secondary: token removed (so it's cleanly skipped next boot
|
||||
// rather than re-erroring); leave the sdk state in place in case
|
||||
// the operator re-provisions a fresh token for the same device.
|
||||
// Return Err so the caller logs + skips this one account and the
|
||||
// daemon keeps serving the primary and any other healthy account.
|
||||
return Err(anyhow!(
|
||||
"matrix token rejected (M_UNKNOWN_TOKEN); removed stale token, skipping account"
|
||||
));
|
||||
// Return a PermanentBringUpError so the caller can distinguish
|
||||
// "don't retry" from a transient network/DNS failure.
|
||||
return Err(anyhow::Error::new(PermanentBringUpError(
|
||||
"matrix token rejected (M_UNKNOWN_TOKEN); removed stale token, skipping account".into(),
|
||||
)));
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue