diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 8eb1807..940d03b 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1517,7 +1517,7 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "mangalord" -version = "0.87.6" +version = "0.87.7" dependencies = [ "anyhow", "argon2", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 915c140..65f9274 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mangalord" -version = "0.87.6" +version = "0.87.7" edition = "2021" default-run = "mangalord" diff --git a/backend/src/app.rs b/backend/src/app.rs index 656addf..559d4f5 100644 --- a/backend/src/app.rs +++ b/backend/src/app.rs @@ -266,7 +266,8 @@ impl DaemonReloader for Supervisors { Arc::clone(&self.storage), &cfg, Arc::clone(&self.analysis_events), - )?; + ) + .await?; *guard = Some(handle); tracing::info!(model = %cfg.model, "analysis daemon (re)started from settings"); } else { @@ -405,12 +406,29 @@ async fn load_effective_analysis( /// Spawn the AI content-analysis worker daemon with the given config. Returns /// its handle. Independent of the crawler daemon (works for uploads with the /// crawler off). Uses a plain reqwest client — no cookie jar / proxy. -fn spawn_analysis_daemon( +async fn spawn_analysis_daemon( db: PgPool, storage: Arc, cfg: &AnalysisConfig, events: Arc, ) -> anyhow::Result { + // Reclaim jobs orphaned by a previous crash/kill. `crawler::jobs::reclaim_orphaned` + // is keyed only on `state='running' AND leased_until < now()`, so it + // covers any kind that uses the table — including this daemon's + // `analyze_page` jobs. Previously this ran only inside + // `spawn_crawler_daemon`, which meant a deploy with the crawler off + // (analysis-only) never refunded orphaned analysis leases until the + // lease expiry path lazily picked them up. Safe under multi-replica + // (only expired leases are touched) and idempotent (the crawler-side + // call happens-before this if both are running). + match crate::crawler::jobs::reclaim_orphaned(&db).await { + Ok(0) => {} + Ok(n) => tracing::info!( + reclaimed = n, + "analysis: reclaimed orphaned in-flight jobs at startup" + ), + Err(e) => tracing::warn!(?e, "analysis: reclaim_orphaned at startup failed"), + } let http = reqwest::Client::builder() .timeout(cfg.request_timeout) // Refuse to honour ambient HTTP_PROXY / HTTPS_PROXY container env. diff --git a/frontend/package.json b/frontend/package.json index 7106776..86a3bb1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "mangalord-frontend", - "version": "0.87.6", + "version": "0.87.7", "private": true, "type": "module", "scripts": {