fix: decouple oneliner-heal from request handler tasks

heal_orphans_if_idle called regenerate_missing_oneliners_for_user
inline on the request task, blocking the browser for up to N×60s
when orphans existed (observed with 16 cases after manual cleanup).

Now: CAS on new OnelinerHealBusy flag + tokio::spawn + BusyGuard
reset-on-drop. Handler returns immediately; the existing
OnelinerUpdated SSE event delivers results via the usual reload.
Startup recovery shares the flag so a concurrent page-load during
boot cannot fire a parallel regen loop against Ollama.

Regression test uses wiremock + timeout(150ms) + .expect(5) to
verify both non-blocking return and dedup of parallel invocations.
This commit is contained in:
2026-04-21 12:56:02 +02:00
parent e5c8c5e3aa
commit 3d42d1da82
5 changed files with 193 additions and 16 deletions
+4 -1
View File
@@ -11,7 +11,9 @@ use tower::util::ServiceExt;
use doctate_common::API_KEY_HEADER;
use doctate_server::config::{Config, User};
use doctate_server::magic_link::{MagicLinkStore, PendingMagicLink};
use doctate_server::{AnalyzeBusy, AppState, TranscribeBusy, analyze, transcribe, web_session};
use doctate_server::{
AnalyzeBusy, AppState, OnelinerHealBusy, TranscribeBusy, analyze, transcribe, web_session,
};
const API_KEY: &str = "key-dr_a";
@@ -55,6 +57,7 @@ fn build_state() -> (AppState, Arc<Config>) {
magic_link_store,
analyze_busy: AnalyzeBusy(Arc::new(AtomicBool::new(false))),
transcribe_busy: TranscribeBusy(Arc::new(AtomicBool::new(false))),
oneliner_heal_busy: OnelinerHealBusy(Arc::new(AtomicBool::new(false))),
events_tx: doctate_server::events::channel(),
http_client: reqwest::Client::new(),
vocab: Arc::new(doctate_server::gazetteer::Gazetteer::empty()),