fix(mesh): refresh federation chat names + roster after sync without restart (#42)
A peer accepted via invite is seeded into the mesh peer table with name=None, so it shows as "Archipelago <pubkey8>" in chat. Federation sync later learns the real name (update_node_state writes it to nodes.json) and discovers transitive peers (merge_transitive_peers), but nothing pushed those into the live mesh peer table — the chat list stayed stale until the next mesh restart, and transitive peers never appeared as contacts at all. Add RpcHandler::refresh_federation_mesh_peers() (re-runs the idempotent, onion-deduped seed_federation_peers_into_mesh) and call it after every periodic sync cycle (server.rs) and after the manual federation.sync-all RPC. Names now correct themselves and the full roster meshes within a sync cycle, no restart needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
06cf80d4a2
commit
6de8173d18
@ -30,6 +30,25 @@ impl RpcHandler {
|
|||||||
mesh::upsert_federation_peer(&svc.shared_state(), pubkey_hex, did, name).await;
|
mesh::upsert_federation_peer(&svc.shared_state(), pubkey_hex, did, name).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-seed every federation node from disk into the mesh peer table so the
|
||||||
|
/// chat list reflects what the latest federation sync learned — display
|
||||||
|
/// names (landed in `nodes.json` by `update_node_state` when a peer
|
||||||
|
/// announces its name) and transitively-discovered peers (merged by
|
||||||
|
/// `merge_transitive_peers`) — WITHOUT waiting for a mesh restart.
|
||||||
|
///
|
||||||
|
/// Without this, a peer accepted via invite (seeded with `name = None`)
|
||||||
|
/// stays "Archipelago <pubkey8>" in chat until the next restart even after
|
||||||
|
/// sync has learned its real name, and transitive peers never appear as
|
||||||
|
/// chat contacts at all. `seed_federation_peers_into_mesh` is idempotent
|
||||||
|
/// and dedups by onion, so calling it after each sync is safe.
|
||||||
|
/// Best-effort: silently no-ops when mesh is off.
|
||||||
|
pub(crate) async fn refresh_federation_mesh_peers(&self) {
|
||||||
|
let svc = self.mesh_service.read().await;
|
||||||
|
if let Some(svc) = svc.as_ref() {
|
||||||
|
mesh::seed_federation_peers_into_mesh(&svc.shared_state(), &self.config.data_dir).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RpcHandler {
|
impl RpcHandler {
|
||||||
@ -341,6 +360,10 @@ impl RpcHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push any names/roster the sync just learned into the live mesh peer
|
||||||
|
// table so the chat list updates without a restart (#42).
|
||||||
|
self.refresh_federation_mesh_peers().await;
|
||||||
|
|
||||||
Ok(serde_json::json!({
|
Ok(serde_json::json!({
|
||||||
"synced": synced,
|
"synced": synced,
|
||||||
"failed": failed,
|
"failed": failed,
|
||||||
|
|||||||
@ -508,6 +508,7 @@ impl Server {
|
|||||||
{
|
{
|
||||||
let data_dir = config.data_dir.clone();
|
let data_dir = config.data_dir.clone();
|
||||||
let state = state_manager.clone();
|
let state = state_manager.clone();
|
||||||
|
let rpc = api_handler.rpc_handler().clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
// First run 60s after boot to let onboarding settle.
|
// First run 60s after boot to let onboarding settle.
|
||||||
tokio::time::sleep(Duration::from_secs(60)).await;
|
tokio::time::sleep(Duration::from_secs(60)).await;
|
||||||
@ -558,6 +559,10 @@ impl Server {
|
|||||||
}
|
}
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
|
// After syncing every peer, push the names/roster just
|
||||||
|
// learned (into nodes.json) into the live mesh peer table
|
||||||
|
// so chat contacts refresh without a restart (#42).
|
||||||
|
rpc.refresh_federation_mesh_peers().await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user