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:
@@ -25,6 +25,7 @@ use crate::gazetteer::Gazetteer;
|
||||
use crate::paths;
|
||||
use crate::routes::case_actions::read_document;
|
||||
use crate::routes::web::{RecordingView, scan_recordings};
|
||||
use crate::settings::Settings;
|
||||
use crate::transcribe::recovery as transcribe_recovery;
|
||||
use crate::{BusyGuard, PipelineState};
|
||||
|
||||
@@ -429,7 +430,7 @@ impl PipelineState {
|
||||
user_root: &Path,
|
||||
slug: &str,
|
||||
http_client: &reqwest::Client,
|
||||
config: &Arc<Config>,
|
||||
settings: &Arc<Settings>,
|
||||
vocab: &Arc<Gazetteer>,
|
||||
events_tx: &EventSender,
|
||||
) {
|
||||
@@ -456,7 +457,7 @@ impl PipelineState {
|
||||
let user_root = user_root.to_path_buf();
|
||||
let slug_owned = slug.to_owned();
|
||||
let http_client = http_client.clone();
|
||||
let config = Arc::clone(config);
|
||||
let settings = Arc::clone(settings);
|
||||
let vocab = Arc::clone(vocab);
|
||||
let events_tx = events_tx.clone();
|
||||
let busy = Arc::clone(&self.oneliner_heal_busy.0);
|
||||
@@ -472,7 +473,7 @@ impl PipelineState {
|
||||
&user_root,
|
||||
&slug_owned,
|
||||
&http_client,
|
||||
&config,
|
||||
&settings,
|
||||
&vocab,
|
||||
&events_tx,
|
||||
&locks,
|
||||
@@ -484,9 +485,11 @@ impl PipelineState {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn handle_my_cases(
|
||||
user: AuthenticatedWebUser,
|
||||
State(config): State<Arc<Config>>,
|
||||
State(settings): State<Arc<Settings>>,
|
||||
State(pipeline): State<PipelineState>,
|
||||
State(events_tx): State<EventSender>,
|
||||
State(http_client): State<reqwest::Client>,
|
||||
@@ -499,7 +502,7 @@ pub async fn handle_my_cases(
|
||||
&user_root,
|
||||
&user.slug,
|
||||
&http_client,
|
||||
&config,
|
||||
&settings,
|
||||
&vocab,
|
||||
&events_tx,
|
||||
)
|
||||
@@ -508,7 +511,7 @@ pub async fn handle_my_cases(
|
||||
// render. The common case is "nothing to do" and costs a handful of
|
||||
// stat-calls per case; actual enqueues happen only when pre-conditions
|
||||
// flip (new transcripts in, stale document, ...).
|
||||
auto_trigger::try_enqueue_all_for_user(&user_root, &pipeline.analyze_tx, &config, &events_tx)
|
||||
auto_trigger::try_enqueue_all_for_user(&user_root, &pipeline.analyze_tx, &settings, &events_tx)
|
||||
.await;
|
||||
|
||||
// Lazy retention sweep: at most one disk scan per /web/cases visit,
|
||||
@@ -531,6 +534,7 @@ pub async fn handle_my_cases(
|
||||
busy,
|
||||
show_closed,
|
||||
retention.auto_delete_days,
|
||||
settings.llm_configured(),
|
||||
)
|
||||
.await;
|
||||
let total = cases.len();
|
||||
@@ -579,6 +583,7 @@ pub async fn handle_my_cases(
|
||||
pub async fn handle_case_page(
|
||||
user: AuthenticatedWebUser,
|
||||
State(config): State<Arc<Config>>,
|
||||
State(settings): State<Arc<Settings>>,
|
||||
State(pipeline): State<PipelineState>,
|
||||
State(events_tx): State<EventSender>,
|
||||
State(http_client): State<reqwest::Client>,
|
||||
@@ -592,7 +597,7 @@ pub async fn handle_case_page(
|
||||
&user_root,
|
||||
&user.slug,
|
||||
&http_client,
|
||||
&config,
|
||||
&settings,
|
||||
&vocab,
|
||||
&events_tx,
|
||||
)
|
||||
@@ -619,7 +624,7 @@ pub async fn handle_case_page(
|
||||
// Auto-analysis trigger for deep-link navigation: same evaluation as
|
||||
// the list view. Document render below still wins the race if the
|
||||
// worker happens to finish synchronously.
|
||||
auto_trigger::try_enqueue(&case_dir, &pipeline.analyze_tx, &config, &events_tx).await;
|
||||
auto_trigger::try_enqueue(&case_dir, &pipeline.analyze_tx, &settings, &events_tx).await;
|
||||
let case_id_str = case_id.to_string();
|
||||
info!(slug = %user.slug, case_id = %case_id, "case page viewed");
|
||||
|
||||
@@ -634,7 +639,7 @@ pub async fn handle_case_page(
|
||||
let (oneliner, oneliner_is_manual) = compute_oneliner_display(&case_dir, &recordings).await;
|
||||
|
||||
let a_busy = pipeline.analyze_busy.0.load(Ordering::Acquire);
|
||||
let flags = compute_flags(&case_dir, &recordings, config.llm_configured(), a_busy).await;
|
||||
let flags = compute_flags(&case_dir, &recordings, settings.llm_configured(), a_busy).await;
|
||||
|
||||
let recordings_count = recordings.len();
|
||||
let transcribed_count = recordings
|
||||
@@ -681,9 +686,11 @@ pub async fn handle_case_page(
|
||||
///
|
||||
/// Read-only sub-page showing all `.m4a` + transcript pairs for the case.
|
||||
/// Useful for power-users/admins; not part of the day-to-day workflow.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn handle_case_recordings(
|
||||
user: AuthenticatedWebUser,
|
||||
State(config): State<Arc<Config>>,
|
||||
State(settings): State<Arc<Settings>>,
|
||||
State(pipeline): State<PipelineState>,
|
||||
State(events_tx): State<EventSender>,
|
||||
State(http_client): State<reqwest::Client>,
|
||||
@@ -696,7 +703,7 @@ pub async fn handle_case_recordings(
|
||||
&user_root,
|
||||
&user.slug,
|
||||
&http_client,
|
||||
&config,
|
||||
&settings,
|
||||
&vocab,
|
||||
&events_tx,
|
||||
)
|
||||
@@ -810,9 +817,9 @@ async fn scan_user_cases(
|
||||
worker_busy: bool,
|
||||
include_closed: bool,
|
||||
auto_delete_days: u32,
|
||||
llm_configured: bool,
|
||||
) -> Vec<UserCaseView> {
|
||||
let user_root = config.data_path.join(slug);
|
||||
let llm_configured = config.llm_configured();
|
||||
let mut cases = Vec::new();
|
||||
let now = OffsetDateTime::now_utc();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user