Refactor analyze recovery and worker busy status

The analyze recovery scan has been refactored to iterate through user
directories and enqueue pending analysis jobs more efficiently. The
`WorkerBusy` status has been introduced as an `Arc<AtomicBool>` to track
whether the analyze worker is currently processing a job.

This `WorkerBusy` flag is used in the `analyze::worker::run` function
and managed by a `BusyGuard` RAII struct, ensuring the flag is correctly
set and unset even in case of panics.

The `handle_my_cases` and `handle_case_detail` handlers in `user_web.rs`
now utilize the `WorkerBusy` flag to accurately display the "analyzing"
status and to trigger a self-heal of orphaned analysis inputs when the
worker is idle.

Additionally, the `WorkerBusy` type is now exported from
`server/src/lib.rs` to be accessible by other modules. The test cases
have been updated to include the `WorkerBusy` parameter when spawning
the analyze worker.
This commit is contained in:
2026-04-16 00:19:08 +02:00
parent 4e145dd167
commit 9072d7a833
7 changed files with 191 additions and 84 deletions
+4 -2
View File
@@ -327,7 +327,8 @@ async fn analyze_worker_writes_document_via_wiremock() {
let config = config_with_llm(tmp.clone(), mock.uri());
let (tx, rx) = analyze::channel();
let client = reqwest::Client::new();
let handle = tokio::spawn(analyze::worker::run(rx, config, client));
let busy = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
let handle = tokio::spawn(analyze::worker::run(rx, config, client, busy));
tx.send(analyze::AnalyzeJob {
case_dir: case_dir.clone(),
@@ -480,7 +481,8 @@ async fn analyze_v2_worker_writes_document_v2_via_wiremock() {
let config = config_with_llm(tmp.clone(), mock.uri());
let (tx, rx) = analyze::channel();
let handle = tokio::spawn(analyze::worker::run(rx, config, reqwest::Client::new()));
let busy = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
let handle = tokio::spawn(analyze::worker::run(rx, config, reqwest::Client::new(), busy));
tx.send(analyze::AnalyzeJob {
case_dir: case_dir.clone(),