Refactor: Track analysis jobs via InFlight struct
This commit replaces the disk-based `analysis_input.json` marker for in-progress analysis jobs with an in-memory `Arc<RwLock<HashSet<PathBuf>>>`. Previously, the existence of `analysis_input.json` was used as a signal that a case was queued or being analyzed. This led to stale "Queued" states after server restarts, as the disk file would persist while the server process tracking it had vanished. The new `InFlight` struct, held in `AppState`, provides a process-local marker. This ensures that: - Server restarts correctly reset the state, as the `HashSet` is cleared. - Race conditions for triggering analysis are handled by the `try_claim` method, replacing the previous reliance on file system `O_EXCL` flags. - The `AnalyzeJob` payload now travels with the job over the channel, eliminating the need for workers to re-read `analysis_input.json` from disk. This change simplifies state management and improves the reliability of analysis job tracking.
This commit is contained in:
+34
-3
@@ -26,7 +26,7 @@ use axum::extract::FromRef;
|
||||
use axum::http::{HeaderName, HeaderValue};
|
||||
use tower_http::set_header::SetResponseHeaderLayer;
|
||||
|
||||
use analyze::AnalyzeSender;
|
||||
use analyze::{AnalyzeSender, InFlight};
|
||||
use config::Config;
|
||||
use gazetteer::Gazetteer;
|
||||
use magic_link::MagicLinkStore;
|
||||
@@ -114,6 +114,10 @@ pub struct AppState {
|
||||
pub http_client: reqwest::Client,
|
||||
pub vocab: Arc<Gazetteer>,
|
||||
pub boot_time: BootTime,
|
||||
/// Process-local set of cases currently queued or being analyzed.
|
||||
/// Replaces the old "does `analysis_input.json` exist on disk?"
|
||||
/// marker so a server restart never reports stale `Queued` states.
|
||||
pub analyze_in_flight: InFlight,
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for Arc<Config> {
|
||||
@@ -213,6 +217,12 @@ impl FromRef<AppState> for BootTime {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for InFlight {
|
||||
fn from_ref(state: &AppState) -> Self {
|
||||
state.analyze_in_flight.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Test/simple entrypoint: jobs pushed into either channel are dropped
|
||||
/// because the receivers are not retained. Use [`create_router_with_state`]
|
||||
/// from `main.rs` where real workers own the receivers.
|
||||
@@ -241,9 +251,29 @@ pub fn create_router_and_session_store_with_settings(
|
||||
config: Arc<Config>,
|
||||
settings: Arc<Settings>,
|
||||
) -> (Router, SessionStore) {
|
||||
let (router, session_store, _, _) = create_router_with_full_handles(config, settings);
|
||||
(router, session_store)
|
||||
}
|
||||
|
||||
/// Test-friendly variant: returns the router, session store, the
|
||||
/// process-local [`InFlight`] set, and the receiver half of the
|
||||
/// analyze channel. Tests that need to inspect the [`AnalyzeJob`]
|
||||
/// payload (recordings, backend_id) consume the receiver to read the
|
||||
/// job a handler just sent. Tests that only care about the HTTP
|
||||
/// response keep using [`create_router_and_session_store_with_settings`].
|
||||
pub fn create_router_with_full_handles(
|
||||
config: Arc<Config>,
|
||||
settings: Arc<Settings>,
|
||||
) -> (
|
||||
Router,
|
||||
SessionStore,
|
||||
analyze::InFlight,
|
||||
analyze::AnalyzeReceiver,
|
||||
) {
|
||||
let (transcribe_tx, _transcribe_rx) = transcribe::channel();
|
||||
let (analyze_tx, _analyze_rx) = analyze::channel();
|
||||
let (analyze_tx, analyze_rx) = analyze::channel();
|
||||
let session_store = web_session::new_store();
|
||||
let in_flight = InFlight::new();
|
||||
let router = create_router_with_state(AppState {
|
||||
config,
|
||||
settings,
|
||||
@@ -263,8 +293,9 @@ pub fn create_router_and_session_store_with_settings(
|
||||
// anyway. Tests that exercise the grace-window itself construct
|
||||
// an `AppState` with an explicit recent `BootTime`.
|
||||
boot_time: BootTime(std::time::SystemTime::UNIX_EPOCH),
|
||||
analyze_in_flight: in_flight.clone(),
|
||||
});
|
||||
(router, session_store)
|
||||
(router, session_store, in_flight, analyze_rx)
|
||||
}
|
||||
|
||||
pub fn create_router_with_state(state: AppState) -> Router {
|
||||
|
||||
Reference in New Issue
Block a user