Watch
0
0
Fork
You've already forked hyperhive
0

hive-matrix-mcp: quieter retries, unique snapshot tmp file, accurate comments

Audit follow-ups on the secondary-account retry.

The accounts snapshot is written by the heartbeat task and, now, by the
retry loop. Both used one fixed tmp path, so concurrent writers could
clobber it or fail the rename. Each write now names its own tmp file
(pid + counter); a test hammers it from four threads.

A permanently bad secondary logged three warnings per attempt, every 16
minutes, for as long as the daemon ran. DownAccounts::failed now reports
whether a failure is news (first, or a different reason from the last);
only that is a warning, repeats are debug. The two per-attempt warnings
in client.rs and credential.rs are covered by that line, which names the
reason, so the store-token one drops to debug.

The comments in client.rs and a credential.rs test, and persistence.md,
still described the old skip-until-restart behaviour or implied that a
store-listed account without a credential is retried here; that case is
handled by the linked-name set changing, not by this loop.
This commit is contained in:
atlas 2026-10-13 21:38:37 +02:00 • committed by mara
commit 53049962b8
5 changed files with 110 additions and 33 deletions

View file

@ -172,7 +172,7 @@ impl Token {
Origin::File(p) => {
let _ = tokio::fs::remove_file(p).await;
}
Origin::Store(path) => tracing::warn!(
Origin::Store(path) => tracing::debug!(
credential = %path,
"the stored matrix credential was rejected; leaving it alone (this agent may only read it)"
),
@ -543,8 +543,8 @@ mod tests {
#[tokio::test]
async fn an_unprovisioned_account_has_no_token_rather_than_an_error() {
// The daemon skips such an account (a secondary) or waits on the path
// watcher (the primary); neither is a failure.
// The daemon leaves such a secondary down and retries it, or waits on
// the path watcher (the primary); neither is a failure.
let missing = std::env::temp_dir().join("hh-cred-definitely-not-here/matrix-token");
assert!(Token::from_file(&missing).await.unwrap().is_none());
}