refactor(#2290): replace mcp_sockets poll with event-driven register_agent
mara: the background worker is redundant if c0re knows when its own sockets go missing. damocles: 10s poll latency and redundancy are two faces of the same issue — poll adds a reconnect window and does redundant work when c0re could react directly. design: c0re owns the MCP listener lifecycle, so the only time a listener disappears without c0re knowing is when c0re itself restarts. - replace spawn_poll (recurring 10s loop) with sync_on_start (one-shot sweep at daemon boot): re-registers all running agents on startup after /run/hyperhive/agents/ is cleared by the tmpfs reset. - run_reconcile (reconcile-start path): add coord.register_agent(name) immediately after start_with_fallback — event-driven, no poll delay. - run_create already calls register_agent eagerly; kill/destroy paths already call unregister_agent — no changes needed there. tracker: #2290
This commit is contained in:
parent
44dd9d45f0
commit
73f1020a7e
3 changed files with 38 additions and 43 deletions
|
|
@ -99,7 +99,7 @@ async fn run_prebuild(
|
|||
let name = &claim.agent;
|
||||
// Prebuild runs while the agent is still up — the runtime dir and
|
||||
// MCP listener already exist. Use the pure path accessor; no need
|
||||
// to re-register the listener (the mcp_sockets supervisor owns that).
|
||||
// to re-register the listener (event-driven: registered at start/create).
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
|
|
@ -190,8 +190,8 @@ async fn run_create(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> R
|
|||
// deploy-window gate so that commit can't land inside another
|
||||
// node's staged deploy window.
|
||||
// Runtime dir creation and MCP listener registration are deferred to
|
||||
// the tail Reconcile's converge_start_preamble / mcp_sockets supervisor
|
||||
// so this node stays purely "provision + create", not "create + start".
|
||||
// the tail Reconcile (converge_start_preamble + register_agent) so this
|
||||
// node stays purely "provision + create", not "create + start".
|
||||
let _window = crate::meta::exclusive().await;
|
||||
crate::lifecycle::create_container(name, &hive, &paths).await?;
|
||||
Ok(NodeOutput::default())
|
||||
|
|
@ -255,15 +255,18 @@ async fn run_reconcile(
|
|||
// exists and writes the nspawn/resource-limits drop-ins.
|
||||
// The returned StartableAgent token is the only way to call
|
||||
// start_with_fallback — omitting this becomes a compile error.
|
||||
// MCP listener registration is handled by mcp_sockets::spawn_poll
|
||||
// (first tick immediate); the container boot takes longer than
|
||||
// the 10 s interval so the listener is ready in time.
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
let token = crate::lifecycle::converge_start_preamble(name, &hive, &paths).await?;
|
||||
ctx.step("nixos-container start");
|
||||
crate::lifecycle::start_with_fallback(token).await?;
|
||||
// Bind the MCP listener immediately after starting the container.
|
||||
// The preamble created the runtime dir; the container is now
|
||||
// coming up and will connect to this socket on its first turn.
|
||||
// Event-driven (no background poll) — c0re owns the listener
|
||||
// lifecycle, so register here rather than waiting for a sweep.
|
||||
coord.register_agent(name)?;
|
||||
coord.kick_agent(name, "container started");
|
||||
coord.rescan_containers_and_emit().await;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue