101 lines
2.9 KiB
Rust
101 lines
2.9 KiB
Rust
//! 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<AppState>) -> Result<impl IntoResponse, ApiErr> {
|
|
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<AppState>,
|
|
Path(segment_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, ApiErr> {
|
|
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<AppState>,
|
|
Path(station_id): Path<Uuid>,
|
|
) -> Result<impl IntoResponse, ApiErr> {
|
|
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,
|
|
})))
|
|
}
|