fix(#2369): skip statically-configured accounts in matrix token discovery to silence spurious sidecar warning
This commit is contained in:
parent
dcd559e7c7
commit
7069732e01
1 changed files with 75 additions and 8 deletions
|
|
@ -100,14 +100,13 @@ pub fn configured() -> anyhow::Result<Vec<AccountCfg>> {
|
|||
// its `matrix-account-<name>.json` homeserver sidecar) that aren't
|
||||
// already declared in config, so an account logged in via the dashboard
|
||||
// form works without a `matrixAccounts` edit + rebuild. Explicit config
|
||||
// wins on name collision.
|
||||
// wins on name collision — pass the configured set so discovery skips
|
||||
// those names silently (a statically-configured account keeps its token
|
||||
// on disk but is brought up from config, not discovery, so it must not
|
||||
// log a spurious "no homeserver sidecar" warning).
|
||||
let configured: std::collections::HashSet<String> =
|
||||
accounts.iter().map(|a| a.name.clone()).collect();
|
||||
for disc in discover_token_accounts() {
|
||||
if !configured.contains(&disc.name) {
|
||||
accounts.push(disc);
|
||||
}
|
||||
}
|
||||
accounts.extend(discover_token_accounts(&configured));
|
||||
Ok(accounts)
|
||||
}
|
||||
|
||||
|
|
@ -120,11 +119,25 @@ pub fn configured() -> anyhow::Result<Vec<AccountCfg>> {
|
|||
/// Best-effort: an unreadable dir or malformed sidecar yields fewer
|
||||
/// accounts, never an error — explicit `HIVE_MATRIX_ACCOUNTS` config stays
|
||||
/// authoritative.
|
||||
fn discover_token_accounts() -> Vec<AccountCfg> {
|
||||
///
|
||||
/// `configured` is the set of names already declared in
|
||||
/// `HIVE_MATRIX_ACCOUNTS`; those are brought up from config regardless of
|
||||
/// their on-disk sidecar, so discovery skips them silently rather than
|
||||
/// warning about a missing sidecar for an account that isn't actually down.
|
||||
fn discover_token_accounts(configured: &std::collections::HashSet<String>) -> Vec<AccountCfg> {
|
||||
let token_path = paths::token_file();
|
||||
let Some(state_dir) = token_path.parent() else {
|
||||
return Vec::new();
|
||||
};
|
||||
discover_token_accounts_in(state_dir, configured)
|
||||
}
|
||||
|
||||
/// Body of [`discover_token_accounts`] with the state dir injected, so the
|
||||
/// scan (and the configured-name skip) is unit-testable against a tempdir.
|
||||
fn discover_token_accounts_in(
|
||||
state_dir: &Path,
|
||||
configured: &std::collections::HashSet<String>,
|
||||
) -> Vec<AccountCfg> {
|
||||
let Ok(rd) = std::fs::read_dir(state_dir) else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
|
@ -142,6 +155,13 @@ fn discover_token_accounts() -> Vec<AccountCfg> {
|
|||
if name.is_empty() {
|
||||
continue;
|
||||
}
|
||||
// Already declared in config: it's brought up from `HIVE_MATRIX_ACCOUNTS`,
|
||||
// not discovery, and its on-disk token needs no sidecar. Skip silently so
|
||||
// a statically-configured account doesn't log a spurious missing-sidecar
|
||||
// warning.
|
||||
if configured.contains(name) {
|
||||
continue;
|
||||
}
|
||||
let sidecar = state_dir.join(format!("matrix-account-{name}.json"));
|
||||
let Some(homeserver) = read_account_homeserver(&sidecar) else {
|
||||
tracing::warn!(
|
||||
|
|
@ -392,7 +412,54 @@ fn write_accounts_snapshot_inner(
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AccountStatus, heartbeat_accounts_snapshot, pick_name, write_accounts_snapshot};
|
||||
use std::collections::HashSet;
|
||||
|
||||
use super::{
|
||||
AccountStatus, discover_token_accounts_in, heartbeat_accounts_snapshot, pick_name,
|
||||
write_accounts_snapshot,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn discovery_skips_configured_names_and_orphan_tokens() {
|
||||
let dir = std::env::temp_dir().join(format!(
|
||||
"hh-acct-disc-{}-{}",
|
||||
std::process::id(),
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos()
|
||||
));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
|
||||
// A statically-configured account: token on disk, NO sidecar.
|
||||
std::fs::write(dir.join("matrix-token-catgirl"), "tok").unwrap();
|
||||
// An orphan dashboard token: no sidecar, not configured.
|
||||
std::fs::write(dir.join("matrix-token-orphan"), "tok").unwrap();
|
||||
// A fully dashboard-provisioned account: token + sidecar.
|
||||
std::fs::write(dir.join("matrix-token-good"), "tok").unwrap();
|
||||
std::fs::write(
|
||||
dir.join("matrix-account-good.json"),
|
||||
r#"{"homeserver":"https://good.example"}"#,
|
||||
)
|
||||
.unwrap();
|
||||
// The hive account's own token must never be treated as an extra.
|
||||
std::fs::write(dir.join("matrix-token"), "tok").unwrap();
|
||||
|
||||
let configured: HashSet<String> = ["main", "catgirl"]
|
||||
.iter()
|
||||
.map(|s| (*s).to_owned())
|
||||
.collect();
|
||||
let mut found: Vec<String> = discover_token_accounts_in(&dir, &configured)
|
||||
.into_iter()
|
||||
.map(|a| a.name)
|
||||
.collect();
|
||||
found.sort();
|
||||
|
||||
// catgirl (configured) + orphan (no sidecar) skipped; only `good` discovered.
|
||||
assert_eq!(found, vec!["good".to_owned()]);
|
||||
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pick_name_single_account_defaults_to_primary() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue