fix(#1989): don't relock on meta-update cascade rebuilds (was reverting the bump)
This commit is contained in:
parent
527dff0200
commit
1f0cc010ad
4 changed files with 36 additions and 6 deletions
|
|
@ -67,11 +67,17 @@ pub fn agent_config_pending(name: &str, deployed_sha: Option<&str>) -> bool {
|
||||||
/// the `rebuild_queue` worker (lets the function annotate its phase via
|
/// the `rebuild_queue` worker (lets the function annotate its phase via
|
||||||
/// `coord.set_queue_step`) and `None` when called directly (e.g. the
|
/// `coord.set_queue_step`) and `None` when called directly (e.g. the
|
||||||
/// root-agent migration nudge in `ensure_root_agent`).
|
/// root-agent migration nudge in `ensure_root_agent`).
|
||||||
|
///
|
||||||
|
/// `relock` bumps the agent's meta input to `applied/<n>/main` before
|
||||||
|
/// the container rebuild. Pass `false` only for meta-update cascade
|
||||||
|
/// rebuilds, where re-locking would revert the bump the cascade just
|
||||||
|
/// committed (see `lifecycle::rebuild`).
|
||||||
pub async fn rebuild_agent(
|
pub async fn rebuild_agent(
|
||||||
coord: &Arc<Coordinator>,
|
coord: &Arc<Coordinator>,
|
||||||
name: &str,
|
name: &str,
|
||||||
current_rev: &str,
|
current_rev: &str,
|
||||||
queue_entry_id: Option<u64>,
|
queue_entry_id: Option<u64>,
|
||||||
|
relock: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
tracing::info!(%name, rev = %current_rev, "rebuild agent");
|
tracing::info!(%name, rev = %current_rev, "rebuild agent");
|
||||||
let agent_dir = coord
|
let agent_dir = coord
|
||||||
|
|
@ -88,6 +94,7 @@ pub async fn rebuild_agent(
|
||||||
name,
|
name,
|
||||||
&hive,
|
&hive,
|
||||||
&paths,
|
&paths,
|
||||||
|
relock,
|
||||||
&|step| coord.set_queue_step(queue_entry_id, step),
|
&|step| coord.set_queue_step(queue_entry_id, step),
|
||||||
&|log_id| {
|
&|log_id| {
|
||||||
if let Some(qid) = queue_entry_id
|
if let Some(qid) = queue_entry_id
|
||||||
|
|
@ -176,7 +183,9 @@ pub async fn ensure_root_agent(coord: &Arc<Coordinator>) -> Result<()> {
|
||||||
"manager container exists but no applied flake — forcing rebuild to migrate"
|
"manager container exists but no applied flake — forcing rebuild to migrate"
|
||||||
);
|
);
|
||||||
let coord_clone = coord.clone();
|
let coord_clone = coord.clone();
|
||||||
if let Err(e) = rebuild_agent(&coord_clone, MANAGER_NAME, rev.as_str(), None).await {
|
if let Err(e) =
|
||||||
|
rebuild_agent(&coord_clone, MANAGER_NAME, rev.as_str(), None, true).await
|
||||||
|
{
|
||||||
tracing::warn!(error = ?e, "manager migration rebuild failed");
|
tracing::warn!(error = ?e, "manager migration rebuild failed");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -413,6 +413,7 @@ pub async fn rebuild(
|
||||||
name: &str,
|
name: &str,
|
||||||
hive: &HiveEnv,
|
hive: &HiveEnv,
|
||||||
paths: &AgentPaths,
|
paths: &AgentPaths,
|
||||||
|
relock: bool,
|
||||||
on_step: &(dyn Fn(&str) + Send + Sync),
|
on_step: &(dyn Fn(&str) + Send + Sync),
|
||||||
on_build_log_id: &(dyn Fn(i64) + Send + Sync),
|
on_build_log_id: &(dyn Fn(i64) + Send + Sync),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|
@ -426,7 +427,16 @@ pub async fn rebuild(
|
||||||
// Then bump just this agent's input — picks up whatever
|
// Then bump just this agent's input — picks up whatever
|
||||||
// `applied/<n>/main` currently points at (deployed/<latest>).
|
// `applied/<n>/main` currently points at (deployed/<latest>).
|
||||||
// Commits the lock if it changed.
|
// Commits the lock if it changed.
|
||||||
crate::meta::lock_update_for_rebuild(name).await?;
|
//
|
||||||
|
// `relock = false` skips this: a meta-update cascade has *just* set
|
||||||
|
// the meta lock deliberately, and `lock_update_for_rebuild` re-runs
|
||||||
|
// `nix flake update agent-<name>`, which re-resolves the agent's
|
||||||
|
// transitive inputs back to the agent's own flake.lock — reverting
|
||||||
|
// the input the meta-update just bumped. Cascade rebuilds therefore
|
||||||
|
// build against the freshly-set on-disk lock as-is.
|
||||||
|
if relock {
|
||||||
|
crate::meta::lock_update_for_rebuild(name).await?;
|
||||||
|
}
|
||||||
rebuild_no_meta(name, hive, paths, on_step, on_build_log_id).await
|
rebuild_no_meta(name, hive, paths, on_step, on_build_log_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -886,8 +886,19 @@ async fn dispatch(
|
||||||
(QueueKind::Rebuild, None) => {
|
(QueueKind::Rebuild, None) => {
|
||||||
let current_rev =
|
let current_rev =
|
||||||
crate::auto_update::current_flake_rev(&coord.hyperhive_flake).unwrap_or_default();
|
crate::auto_update::current_flake_rev(&coord.hyperhive_flake).unwrap_or_default();
|
||||||
crate::auto_update::rebuild_agent(coord, &entry.agent, ¤t_rev, Some(entry.id))
|
// A meta-update cascade has just set the meta lock; re-locking
|
||||||
.await
|
// in the per-agent rebuild would revert it (the agent's own
|
||||||
|
// flake.lock wins). Every other source wants the relock so it
|
||||||
|
// advances to applied/<n>/main.
|
||||||
|
let relock = entry.source != QueueSource::MetaUpdate;
|
||||||
|
crate::auto_update::rebuild_agent(
|
||||||
|
coord,
|
||||||
|
&entry.agent,
|
||||||
|
¤t_rev,
|
||||||
|
Some(entry.id),
|
||||||
|
relock,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
(QueueKind::MetaUpdate, Some(approval_id)) => {
|
(QueueKind::MetaUpdate, Some(approval_id)) => {
|
||||||
crate::actions::run_approval_update_meta_inputs(coord, Some(entry.id), approval_id)
|
crate::actions::run_approval_update_meta_inputs(coord, Some(entry.id), approval_id)
|
||||||
|
|
@ -987,7 +998,7 @@ async fn dispatch(
|
||||||
// env var takes effect in the container.
|
// env var takes effect in the container.
|
||||||
let current_rev =
|
let current_rev =
|
||||||
crate::auto_update::current_flake_rev(&coord.hyperhive_flake).unwrap_or_default();
|
crate::auto_update::current_flake_rev(&coord.hyperhive_flake).unwrap_or_default();
|
||||||
crate::auto_update::rebuild_agent(coord, name, ¤t_rev, Some(entry.id)).await
|
crate::auto_update::rebuild_agent(coord, name, ¤t_rev, Some(entry.id), true).await
|
||||||
}
|
}
|
||||||
(QueueKind::GracefulStop, _) => run_graceful_stop(coord, entry).await,
|
(QueueKind::GracefulStop, _) => run_graceful_stop(coord, entry).await,
|
||||||
(QueueKind::Start, _) => run_start(coord, entry).await,
|
(QueueKind::Start, _) => run_start(coord, entry).await,
|
||||||
|
|
|
||||||
|
|
@ -425,7 +425,7 @@ async fn handle_rebuild(coord: &Arc<Coordinator>, name: &str) -> Result<HostResp
|
||||||
let agent_dir = coord.ensure_runtime(name)?;
|
let agent_dir = coord.ensure_runtime(name)?;
|
||||||
let hive = coord.hive_env();
|
let hive = coord.hive_env();
|
||||||
let paths = Coordinator::agent_paths(name, agent_dir);
|
let paths = Coordinator::agent_paths(name, agent_dir);
|
||||||
let result = lifecycle::rebuild(name, &hive, &paths, &|_| (), &|_| ()).await;
|
let result = lifecycle::rebuild(name, &hive, &paths, true, &|_| (), &|_| ()).await;
|
||||||
// Mirror auto_update::rebuild_agent — the manager wants to know
|
// Mirror auto_update::rebuild_agent — the manager wants to know
|
||||||
// about every rebuild attempt regardless of which surface triggered
|
// about every rebuild attempt regardless of which surface triggered
|
||||||
// it, especially failures (build error → manager can adjust the
|
// it, especially failures (build error → manager can adjust the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue