diff --git a/core/archipelago/src/container/prod_orchestrator.rs b/core/archipelago/src/container/prod_orchestrator.rs index 8ce7f62c..965386d2 100644 --- a/core/archipelago/src/container/prod_orchestrator.rs +++ b/core/archipelago/src/container/prod_orchestrator.rs @@ -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()) }