refactor(server): plumb Arc<Settings> through workers and routes
Config sheds its 14 Bucket-B fields (retention, whisper, ollama, llm) and gains a sibling Arc<Settings> in AppState, loaded from settings.toml at startup via Settings::load_or_default. Workers (transcribe, analyze, recovery, auto_trigger) and routes (health, bulk, case_actions, user_web) take settings as a separate parameter or State<> extractor; Config::llm_configured moves to Settings::llm_configured. TestConfig::build_pair() returns (Arc<Config>, Arc<Settings>); the new create_router_with_settings / create_router_and_session_store_with_settings helpers wire both into integration tests that exercise LLM/Whisper/Ollama. The legacy single-Arc create_router falls back to Settings::default() so the 17 non-LLM tests stay untouched. Verified: cargo build clean, clippy --all-targets clean, 318 tests pass.
This commit is contained in:
@@ -4,11 +4,11 @@ use doctate_common::oneliners::OnelinerState;
|
||||
use tracing::{info, warn};
|
||||
|
||||
use super::{TranscribeJob, TranscribeSender};
|
||||
use crate::config::Config;
|
||||
use crate::events::EventSender;
|
||||
use crate::gazetteer::Gazetteer;
|
||||
use crate::oneliner_locks::OnelinerLocks;
|
||||
use crate::paths;
|
||||
use crate::settings::Settings;
|
||||
|
||||
/// Walk `data_path/*/` and enqueue every recording pending transcription for
|
||||
/// every user. Intended for startup; the same primitive backs the per-user
|
||||
@@ -204,7 +204,7 @@ async fn has_any_transcript(case_dir: &Path) -> bool {
|
||||
pub async fn regenerate_missing_oneliners(
|
||||
data_path: &Path,
|
||||
client: &reqwest::Client,
|
||||
config: &Config,
|
||||
settings: &Settings,
|
||||
vocab: &Gazetteer,
|
||||
events_tx: &EventSender,
|
||||
locks: &OnelinerLocks,
|
||||
@@ -215,7 +215,7 @@ pub async fn regenerate_missing_oneliners(
|
||||
}
|
||||
info!(count = cases.len(), "Regenerating missing oneliners");
|
||||
for (case_dir, slug) in cases {
|
||||
super::worker::update_oneliner(&case_dir, &slug, client, config, vocab, events_tx, locks)
|
||||
super::worker::update_oneliner(&case_dir, &slug, client, settings, vocab, events_tx, locks)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -228,7 +228,7 @@ pub async fn regenerate_missing_oneliners_for_user(
|
||||
user_root: &Path,
|
||||
slug: &str,
|
||||
client: &reqwest::Client,
|
||||
config: &Config,
|
||||
settings: &Settings,
|
||||
vocab: &Gazetteer,
|
||||
events_tx: &EventSender,
|
||||
locks: &OnelinerLocks,
|
||||
@@ -238,7 +238,7 @@ pub async fn regenerate_missing_oneliners_for_user(
|
||||
return;
|
||||
}
|
||||
for case_dir in cases {
|
||||
super::worker::update_oneliner(&case_dir, slug, client, config, vocab, events_tx, locks)
|
||||
super::worker::update_oneliner(&case_dir, slug, client, settings, vocab, events_tx, locks)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,18 @@ use crate::events::{self, CaseEventKind, EventSender};
|
||||
use crate::gazetteer::Gazetteer;
|
||||
use crate::oneliner_locks::OnelinerLocks;
|
||||
use crate::paths;
|
||||
use crate::settings::Settings;
|
||||
use crate::{BusyGuard, WorkerBusy};
|
||||
|
||||
const ONELINER_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
||||
/// Consume transcription jobs sequentially. Whisper holds the GPU, so parallelism
|
||||
/// here would only cause contention. One job in flight at a time.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn run(
|
||||
mut rx: TranscribeReceiver,
|
||||
config: Arc<Config>,
|
||||
settings: Arc<Settings>,
|
||||
client: reqwest::Client,
|
||||
worker_busy: WorkerBusy,
|
||||
vocab: Arc<Gazetteer>,
|
||||
@@ -30,7 +33,7 @@ pub async fn run(
|
||||
oneliner_locks: OnelinerLocks,
|
||||
) {
|
||||
info!("Transcription worker started");
|
||||
let timeout = Duration::from_secs(config.whisper_timeout_seconds);
|
||||
let timeout = Duration::from_secs(settings.whisper.timeout_seconds);
|
||||
|
||||
while let Some(job) = rx.recv().await {
|
||||
let _guard = BusyGuard::new(worker_busy.clone());
|
||||
@@ -44,7 +47,7 @@ pub async fn run(
|
||||
// Look up per-user Whisper settings live from the shared config so that
|
||||
// edits to users.toml (on next restart) reach in-flight jobs naturally.
|
||||
// Unknown slug → empty settings (service falls back to language=de).
|
||||
let settings: WhisperUserSettings = config
|
||||
let user_whisper: WhisperUserSettings = config
|
||||
.users
|
||||
.iter()
|
||||
.find(|u| u.slug == job.user_slug)
|
||||
@@ -70,10 +73,10 @@ pub async fn run(
|
||||
|
||||
let text = match whisper::transcribe(
|
||||
&client,
|
||||
&config.whisper_url,
|
||||
&settings.whisper.url,
|
||||
remuxed.path(),
|
||||
timeout,
|
||||
&settings,
|
||||
&user_whisper,
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -139,7 +142,7 @@ pub async fn run(
|
||||
case_dir,
|
||||
&job.user_slug,
|
||||
&client,
|
||||
&config,
|
||||
&settings,
|
||||
&vocab,
|
||||
&events_tx,
|
||||
&oneliner_locks,
|
||||
@@ -220,7 +223,7 @@ pub async fn update_oneliner(
|
||||
case_dir: &Path,
|
||||
user_slug: &str,
|
||||
client: &reqwest::Client,
|
||||
config: &Config,
|
||||
settings: &Settings,
|
||||
vocab: &Gazetteer,
|
||||
events_tx: &EventSender,
|
||||
locks: &OnelinerLocks,
|
||||
@@ -302,9 +305,9 @@ pub async fn update_oneliner(
|
||||
// during the call.
|
||||
let state = match ollama::generate_oneliner(
|
||||
client,
|
||||
&config.ollama_url,
|
||||
&config.ollama_model,
|
||||
config.ollama_keep_alive,
|
||||
&settings.ollama.url,
|
||||
&settings.ollama.model,
|
||||
settings.ollama.keep_alive,
|
||||
&transcript,
|
||||
ONELINER_TIMEOUT,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user