fix(orchestrator): drop legacy mempool umbrella manifest on catalog-driven nodes

The split-mempool-stack guard that skips the legacy monolithic `mempool`
manifest (whose container collides with its split-stack frontend member
`archy-mempool-web`) only ran over DISK manifests. On catalog-driven nodes
(no disk manifests — e.g. the Phase-3/registry-manifest path), the legacy
`mempool` manifest arrives via the registry-catalog overlay AFTER that
guard, so both `mempool` and `archy-mempool-web` end up owning container
`mempool` and rewrite+restart each other forever ("port binding drift" /
"network alias drift" loop observed on .228, leaving mempool down).

Enforce the guard once more over the merged (disk + catalog) manifest set:
drop the `mempool` umbrella whenever all three split members are present.
Installing `mempool` assembles the split stack, so `archy-mempool-web`
owns the frontend container either way.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago 2026-06-28 14:04:41 -04:00
parent 05c22b6085
commit 83344b9f3a

View File

@ -1230,6 +1230,26 @@ impl ProdContainerOrchestrator {
if overlaid > 0 {
tracing::info!("registry catalog overlaid {overlaid} manifest(s) over disk");
}
// The legacy monolithic `mempool` umbrella manifest renders the same
// `mempool` container as its split-stack frontend member
// `archy-mempool-web`. When the split stack is present, the two render
// conflicting quadlet bodies for one container and rewrite+restart each
// other forever ("port binding drift"/"network alias drift" loop observed
// on catalog-driven .228). The disk-only guard above misses manifests that
// arrive via the registry-catalog overlay, so enforce it here over the
// merged set: drop the umbrella whenever all three split members exist
// (from disk OR catalog). Installing `mempool` assembles the split stack,
// so the frontend container is owned by `archy-mempool-web` either way.
if ["archy-mempool-db", "mempool-api", "archy-mempool-web"]
.iter()
.all(|id| state.manifests.contains_key(*id))
{
if state.manifests.remove("mempool").is_some() {
tracing::info!(
"dropped legacy `mempool` umbrella manifest (split mempool stack present) to avoid container ownership conflict with archy-mempool-web"
);
}
}
Ok(state.manifests.len())
}