feat(#2290): split ensure_runtime — dirs to lifecycle, listeners to mcp_sockets supervisor
- lifecycle::ensure_agent_runtime_dir(name): pure filesystem op, no
Coordinator dep. Creates /run/hyperhive/agents/<name> without touching
the MCP listener map.
- workers/mcp_sockets::spawn_poll(coord): 10 s reconcile loop (same shape
as agent_sockets::spawn_poll). Converges 'agent running => MCP listener
bound'. First tick is immediate so hive-c0re restarts re-register all
running agents without waiting a full interval. Fixes the dead-listener-
after-daemon-restart gap.
- All ensure_runtime() call sites updated:
- Prebuild/Swap/WriteDropin: Coordinator::agent_dir() (pure, no IO)
- Reconcile-Start: ensure_agent_runtime_dir + agent_dir (dir may be
missing after reboot; listener deferred to supervisor)
- run_create / handle_spawn: ensure_agent_runtime_dir + register_agent
(eager on first spawn so socket ready before harness first turn)
- apply_commit / merge_config_pr: ensure_agent_runtime_dir + agent_dir
- Manager (auto_update): ensure_agent_runtime_dir + agent_dir
(manager has no MCP listener; socket_server::start_manager owns it)
- ensure_runtime() retained in Coordinator with updated doc pointing at
the preferred split form. No callers remain outside tests.
This commit is contained in:
parent
b1243f149f
commit
3d919b596f
10 changed files with 147 additions and 30 deletions
|
|
@ -97,9 +97,10 @@ async fn run_prebuild(
|
|||
relock: bool,
|
||||
) -> Result<NodeOutput> {
|
||||
let name = &claim.agent;
|
||||
let agent_dir = coord
|
||||
.ensure_runtime(name)
|
||||
.with_context(|| format!("ensure_runtime {name}"))?;
|
||||
// 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).
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
crate::lifecycle::prepare_rebuild_dirs(name, &paths).await?;
|
||||
|
|
@ -131,7 +132,9 @@ async fn run_prebuild(
|
|||
/// `Reconcile` runs after this node terminal ok *or* fail.
|
||||
async fn run_swap(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Result<NodeOutput> {
|
||||
let name = &claim.agent;
|
||||
let agent_dir = coord.ensure_runtime(name)?;
|
||||
// Swap runs on an already-existing (stopped) container — runtime dir
|
||||
// and listener were created earlier. Pure path accessor suffices.
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
let result =
|
||||
|
|
@ -178,7 +181,12 @@ async fn run_swap(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Res
|
|||
/// build+create — no prebuild needed).
|
||||
async fn run_create(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Result<NodeOutput> {
|
||||
let name = &claim.agent;
|
||||
let agent_dir = coord.ensure_runtime(name)?;
|
||||
// First-spawn: create the bind-mount source dir (tmpfs — empty after
|
||||
// reboot). Register the MCP listener eagerly so it's ready when the
|
||||
// tail Reconcile starts the container and the harness connects.
|
||||
crate::lifecycle::ensure_agent_runtime_dir(name)?;
|
||||
coord.register_agent(name)?;
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
ctx.step("nixos-container create");
|
||||
|
|
@ -254,7 +262,13 @@ async fn run_reconcile(
|
|||
// Prebuild/Swap nodes; the bare-Reconcile templates (boot
|
||||
// reconcile, plain start/restart) otherwise start with
|
||||
// nothing under /run and fail.
|
||||
let agent_dir = coord.ensure_runtime(name)?;
|
||||
//
|
||||
// Dir creation is the pure-filesystem part (no Coordinator
|
||||
// dep). The MCP listener is reconciled by mcp_sockets::spawn_poll
|
||||
// whose first tick fires immediately on daemon start — the
|
||||
// container boot takes longer than the 10 s interval anyway.
|
||||
crate::lifecycle::ensure_agent_runtime_dir(name)?;
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
crate::lifecycle::write_dropins(name, &hive, &paths).await?;
|
||||
|
|
@ -336,7 +350,10 @@ async fn run_drain(coord: &Arc<Coordinator>, claim: &Claim, ctx: &Ctx<'_>) -> Re
|
|||
/// `set_nspawn_flags` + `set_resource_limits` + daemon-reload.
|
||||
async fn run_write_dropin(coord: &Arc<Coordinator>, claim: &Claim) -> Result<NodeOutput> {
|
||||
let name = &claim.agent;
|
||||
let agent_dir = coord.ensure_runtime(name)?;
|
||||
// write_dropins only needs the path value to build AgentPaths; the
|
||||
// dir doesn't need to exist at this point (created by ensure_runtime
|
||||
// on the upstream Prebuild/Start node).
|
||||
let agent_dir = Coordinator::agent_dir(name);
|
||||
let hive = coord.hive_env();
|
||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||
crate::lifecycle::write_dropins(name, &hive, &paths).await?;
|
||||
|
|
|
|||
Loading…
Reference in a new issue