matrix multi-account: isolate per-account stale-token failure so a bad secondary token doesn't kill the daemon
This commit is contained in:
parent
c27f915e47
commit
e5cd4e58f1
2 changed files with 44 additions and 26 deletions
|
|
@ -64,6 +64,7 @@ pub async fn build_and_restore(
|
|||
homeserver: &str,
|
||||
token_file: &Path,
|
||||
state_dir: &Path,
|
||||
is_primary: bool,
|
||||
) -> Result<Client> {
|
||||
let token = fs::read_to_string(token_file)
|
||||
.await
|
||||
|
|
@ -80,31 +81,42 @@ pub async fn build_and_restore(
|
|||
let msg = format!("{e:#}");
|
||||
if msg.contains("M_UNKNOWN_TOKEN") {
|
||||
// Homeserver rejected our token — stale session after a homeserver
|
||||
// state wipe or token expiry. Delete the token file (and the
|
||||
// matrix-sdk sqlite state keyed to the now-invalid session) so
|
||||
// hive-c0re's periodic `ensure_all` sweep re-provisions the account.
|
||||
// Exit 0: systemd's Restart=on-failure must not loop us here; the
|
||||
// systemd.paths watcher restarts us once the new token file appears.
|
||||
// state wipe or token expiry. Delete the stale token file so we
|
||||
// don't loop on it. The rest of the handling depends on whether
|
||||
// this is the primary (hive-internal) account or a secondary one,
|
||||
// because a single bad secondary token must NOT take down the
|
||||
// whole daemon (and with it every healthy account).
|
||||
tracing::warn!(
|
||||
path = %token_file.display(),
|
||||
"matrix token rejected (M_UNKNOWN_TOKEN); deleting stale token + \
|
||||
sdk state for re-provisioning"
|
||||
is_primary,
|
||||
"matrix token rejected (M_UNKNOWN_TOKEN); removing stale token"
|
||||
);
|
||||
let _ = fs::remove_file(token_file).await;
|
||||
if let Err(re) = fs::remove_dir_all(state_dir).await {
|
||||
tracing::warn!(
|
||||
path = %state_dir.display(),
|
||||
err = %re,
|
||||
"failed to remove sdk state dir; next startup may fail with stale state"
|
||||
);
|
||||
if is_primary {
|
||||
// Primary: also drop the matrix-sdk sqlite state keyed to the
|
||||
// now-invalid session, then exit 0 so hive-c0re's `ensure_all`
|
||||
// re-provisions the account and the systemd.paths watcher
|
||||
// restarts us once the fresh token file appears. Exit 0 (not
|
||||
// Err) keeps systemd's Restart=on-failure from looping; the
|
||||
// call site is before any tasks are spawned so there's
|
||||
// nothing to clean up.
|
||||
if let Err(re) = fs::remove_dir_all(state_dir).await {
|
||||
tracing::warn!(
|
||||
path = %state_dir.display(),
|
||||
err = %re,
|
||||
"failed to remove sdk state dir; next startup may fail with stale state"
|
||||
);
|
||||
}
|
||||
std::process::exit(0);
|
||||
}
|
||||
// Exit 0 rather than returning Err: `hive-matrix-daemon` is a
|
||||
// single-purpose process binary; the call site is before any
|
||||
// tasks are spawned so there are no resources to clean up.
|
||||
// Using exit(0) (not Err) keeps systemd's Restart=on-failure
|
||||
// from looping — the systemd.paths watcher re-launches us
|
||||
// once hive-c0re writes a fresh token file.
|
||||
std::process::exit(0);
|
||||
// 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 Err(e);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue