fix(analysis): emit Cancelled event + assert lock-release after cancel (0.87.13)

Two 0.87.4 follow-ups:

1. Cron tick: existing shutdown-on-cancel test now also asserts the
   advisory lock is re-acquirable after cancel-during-tick. Without
   this, a refactor moving `pg_advisory_unlock` under the cancel arm
   would ship green and break multi-replica safety.

2. Analysis worker: cancel-mid-dispatch left the dashboard banner stuck
   on the cancelled page until a later page overwrote it. Add a
   `Cancelled` AnalysisEvent variant, publish on the cancel-release
   branch, wire the analysis and admin overview dashboards to clear
   on it. Per-page chip rolls back from `analyzing` to `queued`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-23 08:01:53 +02:00
parent 95b98eebf1
commit 651fb27522
9 changed files with 88 additions and 5 deletions

View File

@@ -276,7 +276,23 @@ impl WorkerContext {
);
let _ = jobs::release(&self.pool, lease.id).await;
// Don't publish Failed (the page didn't actually fail) and
// don't write a duration row — neither outcome is true.
// don't write a duration row — neither outcome is true. DO
// publish Cancelled so the dashboard's "now analyzing" banner
// can clear the page we previously sent Started for. Without
// this the banner stuck on the cancelled page until a later
// page kicked off and overwrote it.
if let Some((manga_id, manga_title, chapter_id, chapter_number, page_number)) =
breadcrumb
{
self.events.publish(AnalysisEvent::Cancelled {
page_id,
manga_id,
manga_title,
chapter_id,
chapter_number,
page_number,
});
}
return;
};

View File

@@ -54,6 +54,20 @@ pub enum AnalysisEvent {
chapter_number: i32,
page_number: i32,
},
/// The worker cancelled an in-flight dispatch (daemon shutdown or
/// settings reload toggling analysis off). The lease was released,
/// not failed — but the dashboard banner already saw `Started` and
/// only clears on `Completed`/`Failed`/`Cancelled`. Without this
/// variant the banner stuck on the cancelled page forever (until a
/// later page kicked off and overwrote it).
Cancelled {
page_id: Uuid,
manga_id: Uuid,
manga_title: String,
chapter_id: Uuid,
chapter_number: i32,
page_number: i32,
},
}
/// Broadcaster shared on `AppState`. Cheap to clone via `Arc`. Publishing