diff --git a/core/archipelago/src/api/rpc/package/stacks.rs b/core/archipelago/src/api/rpc/package/stacks.rs index 7899edf8..3fa5f3ee 100644 --- a/core/archipelago/src/api/rpc/package/stacks.rs +++ b/core/archipelago/src/api/rpc/package/stacks.rs @@ -621,8 +621,33 @@ async fn install_stack_via_orchestrator( )) .await; + // Phase: PullingImage — each member's orchestrator.install covers its + // whole pipeline (pull + create + start + health wait), and on a fresh + // node the pull dominates wall-clock. The X-of-N counter below is what + // the UI interpolates across the PullingImage band (20→70%); without + // these updates an orchestrator-installed stack sat at "Preparing… 5%" + // for the entire multi-gigabyte pull (indeedhub: 7 images). + let total = app_ids.len() as u64; + handler + .set_install_phase(stack_name, InstallPhase::PullingImage) + .await; + let mut installed = 0usize; - for app_id in app_ids { + for (idx, app_id) in app_ids.iter().enumerate() { + handler + .set_install_progress(stack_name, idx as u64, total) + .await; + // Message after progress: set_install_progress resets the label, + // set_install_message preserves the phase + counters just written. + let component = app_id + .strip_prefix(&format!("{stack_name}-")) + .unwrap_or(app_id); + handler + .set_install_message( + stack_name, + &format!("Installing {} ({} of {})…", component, idx + 1, total), + ) + .await; match orchestrator.install(app_id).await { Ok(container_name) => { installed += 1; @@ -672,6 +697,20 @@ async fn install_stack_via_orchestrator( } } + // Truthful end-of-install signal, mirroring the legacy stack installers: + // the real readiness gate is the scanner's next sweep, this just settles + // the bar at 95→100→done instead of leaving it mid-band. + handler + .set_install_progress(stack_name, total, total) + .await; + handler + .set_install_phase(stack_name, InstallPhase::PostInstall) + .await; + handler + .set_install_phase(stack_name, InstallPhase::Done) + .await; + handler.clear_install_progress(stack_name).await; + install_log(&format!("INSTALL ORCH OK: {} stack", stack_name)).await; Ok(Some(serde_json::json!({ "success": true,