Compare commits
2 changed files with 8 additions and 35 deletions
|
|
@ -350,19 +350,17 @@ async fn cmd_serve(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Knowledge periodic pull: hourly fallback in case the webhook is
|
// Knowledge periodic pull: hourly fallback in case the webhook is
|
||||||
// missed (e.g. hive-c0re was down during a push). Deliberately does
|
// missed (e.g. hive-c0re was down during a push). First fires at
|
||||||
// NOT also fire an immediate pull at startup the way this task used
|
// startup (immediate pull after the clone is already present).
|
||||||
// to: `auto_update::run`'s `NodeKind::KnowledgePull` DAG node (spawned
|
|
||||||
// separately, a few lines up) already does that unconditionally on
|
|
||||||
// every boot. The two used to run concurrently with no lock between
|
|
||||||
// them, both `git pull --ff-only`-ing the same working tree — a real
|
|
||||||
// race, and the likely root cause of the "local changes would be
|
|
||||||
// overwritten" wedge this file's `pull()` now defends against
|
|
||||||
// (`reset --hard` before every pull). Removing the redundant caller
|
|
||||||
// fixes the race at its source instead of just self-healing after it.
|
|
||||||
let mut knowledge_shutdown = coord.shutdown_rx();
|
let mut knowledge_shutdown = coord.shutdown_rx();
|
||||||
let knowledge_coord = coord.clone();
|
let knowledge_coord = coord.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
// Initial pull — reconcile any commits that landed while c0re
|
||||||
|
// was offline. Not fed to the health tracker: a startup miss is
|
||||||
|
// expected (the clone may not exist yet) and is logged at debug.
|
||||||
|
if let Err(e) = knowledge::pull(&knowledge_coord).await {
|
||||||
|
tracing::debug!(error = ?e, "knowledge: startup pull skipped (no clone yet?)");
|
||||||
|
}
|
||||||
// Persistent-failure → banner. An hourly sweep that keeps failing for
|
// Persistent-failure → banner. An hourly sweep that keeps failing for
|
||||||
// several hours means the operator's `/knowledge` is drifting; raise a
|
// several hours means the operator's `/knowledge` is drifting; raise a
|
||||||
// warn banner after 3 consecutive misses so a one-off network blip
|
// warn banner after 3 consecutive misses so a one-off network blip
|
||||||
|
|
|
||||||
|
|
@ -254,31 +254,6 @@ pub async fn pull(coord: &Coordinator) -> Result<()> {
|
||||||
.args(["-C", LOCAL_DIR, "remote", "set-url", "origin", &plain])
|
.args(["-C", LOCAL_DIR, "remote", "set-url", "origin", &plain])
|
||||||
.output()
|
.output()
|
||||||
.await;
|
.await;
|
||||||
// Discard any local drift before pulling — both tracked (`reset --hard`)
|
|
||||||
// and untracked (`clean -fd`). Nothing in this codebase writes to
|
|
||||||
// `LOCAL_DIR` after the initial clone (`seed_readme` runs once, at
|
|
||||||
// creation, before any pull) — this working tree exists to mirror
|
|
||||||
// `origin/main`, not to be edited in place. A tracked file left dirty
|
|
||||||
// by any other means (a stray manual edit on the host, an interrupted
|
|
||||||
// prior operation, or — the actual root cause here — two unsynchronized
|
|
||||||
// boot-time pull callers racing on this same working tree, since fixed
|
|
||||||
// in `main.rs`) would otherwise abort the `--ff-only` merge below with
|
|
||||||
// "local changes would be overwritten"; an untracked file left behind
|
|
||||||
// the same ways aborts it with "untracked working tree files would be
|
|
||||||
// overwritten" instead — same wedge, just `clean`'s failure message
|
|
||||||
// rather than `reset`'s. Either way it wedges every future pull
|
|
||||||
// identically until someone notices and resets it by hand. Best-effort:
|
|
||||||
// a failure here surfaces through the pull's own error below rather
|
|
||||||
// than needing its own branch.
|
|
||||||
let _ = crate::lifecycle::git_command()
|
|
||||||
.args(["-C", LOCAL_DIR, "reset", "--hard", "HEAD"])
|
|
||||||
.output()
|
|
||||||
.await;
|
|
||||||
let _ = crate::lifecycle::git_command()
|
|
||||||
.args(["-C", LOCAL_DIR, "clean", "-fd"])
|
|
||||||
.output()
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let before = head_sha().await;
|
let before = head_sha().await;
|
||||||
// The repo is public (`ensure_knowledge_repo` makes it so), so an
|
// The repo is public (`ensure_knowledge_repo` makes it so), so an
|
||||||
// unauthenticated pull is enough — but authenticate when a token is around,
|
// unauthenticated pull is enough — but authenticate when a token is around,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue