feat: Add API endpoint for listing oneliners
This commit introduces a new API endpoint `/api/oneliners` that allows authenticated users to retrieve a list of their recent oneliners. The endpoint supports conditional GET requests using the `ETag` header for efficient caching. It also allows specifying a time window for the oneliners via the `hours` query parameter, with sensible defaults and clamping. The implementation includes: - A new route handler `handle_oneliners`. - A new type `OnelinerWatermark` for tracking user-specific timestamps. - Logic for scanning user data directories, filtering by time, and handling deleted cases. - Test cases to cover various scenarios, including caching, time windowing, and edge cases.
This commit is contained in:
@@ -9,17 +9,27 @@ pub mod routes;
|
||||
pub mod transcribe;
|
||||
pub mod web_session;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::extract::FromRef;
|
||||
use axum::Router;
|
||||
use time::OffsetDateTime;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use analyze::AnalyzeSender;
|
||||
use config::Config;
|
||||
use transcribe::TranscribeSender;
|
||||
use web_session::SessionStore;
|
||||
|
||||
/// Per-user UTC timestamp of the last successful oneliner write.
|
||||
/// Read on every `/api/oneliners` request to build the ETag; written
|
||||
/// from the transcribe worker and the boot recovery scan. Missing entry
|
||||
/// → the user has no known oneliner activity yet; the endpoint returns
|
||||
/// a full response and sets an ETag based on a `0` seed.
|
||||
pub type OnelinerWatermark = Arc<RwLock<HashMap<String, OffsetDateTime>>>;
|
||||
|
||||
/// Live "is this worker currently processing a job?" flag.
|
||||
/// Set true before each job, false after. UI uses it to distinguish a real
|
||||
/// in-flight job from a stale on-disk marker (orphan input, missing
|
||||
@@ -60,6 +70,7 @@ pub struct AppState {
|
||||
pub session_store: SessionStore,
|
||||
pub analyze_busy: AnalyzeBusy,
|
||||
pub transcribe_busy: TranscribeBusy,
|
||||
pub oneliner_watermark: OnelinerWatermark,
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for Arc<Config> {
|
||||
@@ -98,6 +109,12 @@ impl FromRef<AppState> for TranscribeBusy {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for OnelinerWatermark {
|
||||
fn from_ref(state: &AppState) -> Self {
|
||||
state.oneliner_watermark.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.
|
||||
@@ -111,6 +128,7 @@ pub fn create_router(config: Arc<Config>) -> Router {
|
||||
session_store: web_session::new_store(),
|
||||
analyze_busy: AnalyzeBusy(Arc::new(AtomicBool::new(false))),
|
||||
transcribe_busy: TranscribeBusy(Arc::new(AtomicBool::new(false))),
|
||||
oneliner_watermark: Arc::new(RwLock::new(HashMap::new())),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user