60 lines
2.3 KiB
Rust
60 lines
2.3 KiB
Rust
//! MCP socket listener reconcile loop.
|
|
//!
|
|
//! Periodically checks that every running agent container has a bound
|
|
//! MCP listener registered in the `Coordinator`. Any agent that is running
|
|
//! but whose listener has gone (e.g. after a hive-c0re restart that cleared
|
|
//! `/run/hyperhive/agents/`) gets re-registered automatically.
|
|
//!
|
|
//! Same shape as `agent_sockets::spawn_poll` — a simple 10 s tick loop that
|
|
//! converges "agent container running ⇒ MCP listener bound". The self-healing
|
|
//! guarantee means no callsite needs to call `register_agent` directly;
|
|
//! `lifecycle::ensure_agent_runtime_dir` (called inside `lifecycle::spawn`
|
|
//! and `converge_start_preamble`) creates the bind-mount source, and the
|
|
//! reconcile loop picks up the listener binding on the next tick.
|
|
|
|
use std::sync::Arc;
|
|
|
|
use crate::coordinator::Coordinator;
|
|
|
|
/// Spawn the MCP socket listener reconcile loop.
|
|
///
|
|
/// Every 10 s the loop lists running agent containers and calls
|
|
/// `register_agent` for any that lack a bound listener. The first tick fires
|
|
/// immediately so hive-c0re restarts re-register all running agents without
|
|
/// waiting a full interval.
|
|
pub fn spawn_poll(coord: Arc<Coordinator>) {
|
|
tokio::spawn(async move {
|
|
let mut interval = tokio::time::interval(std::time::Duration::from_secs(10));
|
|
loop {
|
|
interval.tick().await;
|
|
reconcile_once(&coord).await;
|
|
}
|
|
});
|
|
}
|
|
|
|
async fn reconcile_once(coord: &Arc<Coordinator>) {
|
|
let running = match crate::lifecycle::list().await {
|
|
Ok(names) => names,
|
|
Err(e) => {
|
|
tracing::debug!(error = ?e, "mcp_sockets poll: failed to list agents");
|
|
return;
|
|
}
|
|
};
|
|
let registered = coord.list_agents();
|
|
for container in running {
|
|
let Some(name) = container.strip_prefix(crate::lifecycle::AGENT_PREFIX) else {
|
|
continue;
|
|
};
|
|
if !registered.contains(&name.to_owned()) {
|
|
if let Err(e) = coord.register_agent(name) {
|
|
tracing::warn!(
|
|
agent = %name,
|
|
error = ?e,
|
|
"mcp_sockets poll: register_agent failed"
|
|
);
|
|
} else {
|
|
tracing::debug!(agent = %name, "mcp_sockets poll: registered missing listener");
|
|
}
|
|
}
|
|
}
|
|
}
|