//! Runtime read endpoints (design doc ยง9.3). use axum::{ extract::{Path, State}, response::IntoResponse, Json, }; use serde_json::json; use uuid::Uuid; use plc_platform_core::util::response::ApiErr; use crate::{ service::{segment as segment_service, station as station_service}, AppState, }; pub async fn get_overview(State(state): State) -> Result { let segments = segment_service::list_segments(&state.platform.pool, None).await?; let runtimes = state.segment_runtime.get_all().await; let segment_payload: Vec<_> = segments .into_iter() .map(|seg| { let runtime = runtimes.get(&seg.id).cloned(); json!({ "segment": seg, "runtime": runtime, }) }) .collect(); let resource_snapshot = state.resource_registry.snapshot().await; let resources: Vec<_> = resource_snapshot .into_iter() .map(|(key, lease)| { json!({ "resource_key": key, "owner_segment_id": lease.owner_segment_id, "acquired_at": lease.acquired_at, "heartbeat_at": lease.heartbeat_at, }) }) .collect(); Ok(Json(json!({ "segments": segment_payload, "resources": resources, }))) } pub async fn get_segment_runtime( State(state): State, Path(segment_id): Path, ) -> Result { let segment = segment_service::get_segment_by_id(&state.platform.pool, segment_id) .await? .ok_or_else(|| ApiErr::NotFound("Segment not found".to_string(), None))?; let runtime = state.segment_runtime.get_or_init(segment_id).await; Ok(Json(json!({ "segment": segment, "runtime": runtime, }))) } pub async fn get_station_runtime( State(state): State, Path(station_id): Path, ) -> Result { let station = station_service::get_station_by_id(&state.platform.pool, station_id) .await? .ok_or_else(|| ApiErr::NotFound("Station not found".to_string(), None))?; let signals = station_service::list_station_signals(&state.platform.pool, station_id).await?; // Attach the latest monitor sample for each bound point. let monitor_guard = state .platform .connection_manager .get_point_monitor_data_read_guard() .await; let signal_payload: Vec<_> = signals .iter() .map(|sig| { let monitor = sig .point_id .and_then(|pid| monitor_guard.get(&pid).cloned()); json!({ "signal": sig, "point_monitor": monitor, }) }) .collect(); drop(monitor_guard); Ok(Json(json!({ "station": station, "signals": signal_payload, }))) }