feat: persistent sessions, remove track_map use case, car characteristics DB
- Remove obsolete TrackMap use case variant (superseded by TrackMapping)
- Add session/run/analysis persistence: metadata to data/sessions/<id>.json,
frames to <id>.frames.json (split for lazy loading)
- Atomic writes (temp + rename), compact JSON, off-thread frame serialization
- load_all loads metadata only at startup; ensure_frames_loaded lazy-loads
frames before analysis
- Normalize Recording runs to Stopped on reload (stale ring-buffer markers)
- Cache car_name on UseCaseSession during run finalization
- Add characteristics.rs: aggregate shift-point data per car across sessions
- New API: GET /api/characteristics/cars, GET /api/characteristics/cars/{car}
- Add Deserialize to TelemetryFrame and FeedSource for session round-trip
This commit is contained in:
parent
937090681f
commit
ed7dbcf1c9
7 changed files with 477 additions and 17 deletions
23
src/api.rs
23
src/api.rs
|
|
@ -14,6 +14,7 @@ use std::sync::{Arc, Mutex, MutexGuard};
|
|||
use tower_http::cors::CorsLayer;
|
||||
|
||||
use crate::analysis;
|
||||
use crate::characteristics;
|
||||
use crate::feed_state::FeedState;
|
||||
use crate::recording::{Game, RecordingManager, RecordingStatus, StartRecordingRequest, UseCase};
|
||||
use crate::session::SessionManager;
|
||||
|
|
@ -267,7 +268,7 @@ async fn run_analysis(
|
|||
Path(id): Path<String>,
|
||||
) -> Response {
|
||||
let (use_case, frames_by_run, run_labels, recording_id) = {
|
||||
let mgr = lock_sessions(&state);
|
||||
let mut mgr = lock_sessions(&state);
|
||||
match mgr.get_session(&id) {
|
||||
Some(session) => {
|
||||
if session.status != crate::session::SessionStatus::Completed {
|
||||
|
|
@ -681,6 +682,24 @@ async fn list_games() -> Response {
|
|||
ok_json(Game::valid_choices())
|
||||
}
|
||||
|
||||
async fn list_car_profiles(
|
||||
State(state): State<Arc<AppState>>,
|
||||
) -> Response {
|
||||
let mgr = lock_sessions(&state);
|
||||
ok_json(characteristics::car_profiles(&mgr))
|
||||
}
|
||||
|
||||
async fn get_car_profile(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Path(car): Path<String>,
|
||||
) -> Response {
|
||||
let mgr = lock_sessions(&state);
|
||||
match characteristics::car_profile(&mgr, &car) {
|
||||
Some(profile) => ok_json(profile),
|
||||
None => err(StatusCode::NOT_FOUND, &format!("No data for car '{}'", car)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_router(state: Arc<AppState>) -> Router {
|
||||
Router::new()
|
||||
.route("/api/sessions", get(list_sessions).post(create_session))
|
||||
|
|
@ -714,6 +733,8 @@ pub fn build_router(state: Arc<AppState>) -> Router {
|
|||
.route("/api/tracks/build", post(build_track))
|
||||
.route("/api/use-cases", get(list_use_cases))
|
||||
.route("/api/games", get(list_games))
|
||||
.route("/api/characteristics/cars", get(list_car_profiles))
|
||||
.route("/api/characteristics/cars/{car}", get(get_car_profile))
|
||||
.layer(CorsLayer::permissive())
|
||||
.with_state(state)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue