dashboard: lifecycle_action helper collapses start/stop/restart/rebuild
five POST handlers (post_kill / post_restart / post_start / post_rebuild) were all repeating the same boilerplate: strip prefix, set_transient, call lifecycle::X, clear_transient, match the result. extract one helper that takes the transient kind, error-message verb, the work body, and an optional 'on success' tail (used by kill to also unregister + emit HelperEvent::Killed). each handler shrinks to a single lifecycle_action(..) call. zero behavior change.
This commit is contained in:
parent
89ccc5e6c5
commit
7b4adea325
3 changed files with 76 additions and 47 deletions
|
|
@ -114,7 +114,6 @@ impl EventStore {
|
|||
out.reverse();
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -172,7 +171,6 @@ impl Bus {
|
|||
};
|
||||
store.recent(HISTORY_CAPACITY).unwrap_or_default()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Default for Bus {
|
||||
|
|
|
|||
|
|
@ -456,15 +456,51 @@ async fn post_rebuild(State(state): State<AppState>, AxumPath(name): AxumPath<St
|
|||
"rebuild: hyperhive_flake has no canonical path; manual rebuild only via `hive-c0re rebuild`",
|
||||
);
|
||||
};
|
||||
let logical = strip_container_prefix(&name);
|
||||
state
|
||||
.coord
|
||||
.set_transient(&logical, crate::coordinator::TransientKind::Rebuilding);
|
||||
let result = crate::auto_update::rebuild_agent(&state.coord, &logical, ¤t_rev).await;
|
||||
let coord = state.coord.clone();
|
||||
lifecycle_action(
|
||||
&state,
|
||||
&name,
|
||||
crate::coordinator::TransientKind::Rebuilding,
|
||||
"rebuild",
|
||||
move |n| {
|
||||
let coord = coord.clone();
|
||||
let rev = current_rev.clone();
|
||||
async move { crate::auto_update::rebuild_agent(&coord, &n, &rev).await }
|
||||
},
|
||||
|_, _| {},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Common shape for the simple lifecycle action handlers (start /
|
||||
/// stop / restart / rebuild): strip the container prefix, mark
|
||||
/// transient for the duration so the dashboard can spinner, run the
|
||||
/// lifecycle op, clear transient, redirect on success or surface the
|
||||
/// error. `verb` only appears in the error message; `extra` runs on
|
||||
/// success after `clear_transient` for handlers that need follow-up
|
||||
/// (e.g. `kill` also unregisters the agent + fires `HelperEvent`).
|
||||
async fn lifecycle_action<F, Fut>(
|
||||
state: &AppState,
|
||||
name: &str,
|
||||
kind: crate::coordinator::TransientKind,
|
||||
verb: &str,
|
||||
body: F,
|
||||
extra: impl FnOnce(&AppState, &str),
|
||||
) -> Response
|
||||
where
|
||||
F: FnOnce(String) -> Fut,
|
||||
Fut: std::future::Future<Output = anyhow::Result<()>>,
|
||||
{
|
||||
let logical = strip_container_prefix(name);
|
||||
state.coord.set_transient(&logical, kind);
|
||||
let result = body(logical.clone()).await;
|
||||
state.coord.clear_transient(&logical);
|
||||
match result {
|
||||
Ok(()) => Redirect::to("/").into_response(),
|
||||
Err(e) => error_response(&format!("rebuild {logical} failed: {e:#}")),
|
||||
Ok(()) => {
|
||||
extra(state, &logical);
|
||||
Redirect::to("/").into_response()
|
||||
}
|
||||
Err(e) => error_response(&format!("{verb} {logical} failed: {e:#}")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -473,49 +509,44 @@ async fn post_kill(State(state): State<AppState>, AxumPath(name): AxumPath<Strin
|
|||
if logical == lifecycle::MANAGER_NAME {
|
||||
return error_response("kill: refusing to stop the manager");
|
||||
}
|
||||
state
|
||||
.coord
|
||||
.set_transient(&logical, crate::coordinator::TransientKind::Stopping);
|
||||
let result = lifecycle::kill(&logical).await;
|
||||
state.coord.clear_transient(&logical);
|
||||
match result {
|
||||
Ok(()) => {
|
||||
state.coord.unregister_agent(&logical);
|
||||
state
|
||||
.coord
|
||||
.notify_manager(&hive_sh4re::HelperEvent::Killed {
|
||||
agent: logical.clone(),
|
||||
});
|
||||
Redirect::to("/").into_response()
|
||||
}
|
||||
Err(e) => error_response(&format!("kill {logical} failed: {e:#}")),
|
||||
}
|
||||
lifecycle_action(
|
||||
&state,
|
||||
&name,
|
||||
crate::coordinator::TransientKind::Stopping,
|
||||
"kill",
|
||||
|n| async move { lifecycle::kill(&n).await },
|
||||
|s, n| {
|
||||
s.coord.unregister_agent(n);
|
||||
s.coord.notify_manager(&hive_sh4re::HelperEvent::Killed {
|
||||
agent: n.to_owned(),
|
||||
});
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn post_restart(State(state): State<AppState>, AxumPath(name): AxumPath<String>) -> Response {
|
||||
let logical = strip_container_prefix(&name);
|
||||
state
|
||||
.coord
|
||||
.set_transient(&logical, crate::coordinator::TransientKind::Restarting);
|
||||
let result = lifecycle::restart(&logical).await;
|
||||
state.coord.clear_transient(&logical);
|
||||
match result {
|
||||
Ok(()) => Redirect::to("/").into_response(),
|
||||
Err(e) => error_response(&format!("restart {logical} failed: {e:#}")),
|
||||
}
|
||||
lifecycle_action(
|
||||
&state,
|
||||
&name,
|
||||
crate::coordinator::TransientKind::Restarting,
|
||||
"restart",
|
||||
|n| async move { lifecycle::restart(&n).await },
|
||||
|_, _| {},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn post_start(State(state): State<AppState>, AxumPath(name): AxumPath<String>) -> Response {
|
||||
let logical = strip_container_prefix(&name);
|
||||
state
|
||||
.coord
|
||||
.set_transient(&logical, crate::coordinator::TransientKind::Starting);
|
||||
let result = lifecycle::start(&logical).await;
|
||||
state.coord.clear_transient(&logical);
|
||||
match result {
|
||||
Ok(()) => Redirect::to("/").into_response(),
|
||||
Err(e) => error_response(&format!("start {logical} failed: {e:#}")),
|
||||
}
|
||||
lifecycle_action(
|
||||
&state,
|
||||
&name,
|
||||
crate::coordinator::TransientKind::Starting,
|
||||
"start",
|
||||
|n| async move { lifecycle::start(&n).await },
|
||||
|_, _| {},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn post_update_all(State(state): State<AppState>) -> Response {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ mod broker;
|
|||
mod client;
|
||||
mod coordinator;
|
||||
mod dashboard;
|
||||
mod lifecycle;
|
||||
mod events_vacuum;
|
||||
mod lifecycle;
|
||||
mod manager_server;
|
||||
mod operator_questions;
|
||||
mod server;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue