use std::sync::Arc;
use axum::{extract::State, response::IntoResponse};
use serde::Serialize;
use tracing::warn;
use crate::daemon::rpc::managed::outcome::RouteOutcome;
use crate::daemon::state::DaemonState;
use crate::session_manager::SessionRecord;
use super::{SessionSummary, checked_summaries};
#[derive(Debug, Serialize)]
pub struct FleetProjectGroup {
pub project_name: String,
pub repo_url: String,
pub sessions: Vec<SessionSummary>,
}
#[derive(Debug, Serialize)]
pub struct FleetByProjectResponse {
pub projects: Vec<FleetProjectGroup>,
}
pub async fn fleet_by_project_route(State(state): State<Arc<DaemonState>>) -> impl IntoResponse {
fleet_core(&state).await }
pub(crate) async fn fleet_core(state: &Arc<DaemonState>) -> RouteOutcome {
let mgr = state.session_manager().await;
let registry = state.project_registry().await;
let raw_sessions: Vec<SessionRecord> = mgr.list().await;
let projects = match registry.list().await {
Ok(p) => p,
Err(e) => {
warn!(
error = %e,
"fleet_by_project_route: project registry read failed; \
returning empty project list (sessions will not be grouped)"
);
vec![]
}
};
let fleet = crate::project::fleet_by_project(&raw_sessions, &projects);
let mut project_groups: Vec<FleetProjectGroup> = Vec::with_capacity(fleet.len());
for pf in fleet {
project_groups.push(FleetProjectGroup {
project_name: pf.project.name.clone(),
repo_url: pf.project.repo_url.clone(),
sessions: checked_summaries(&pf.sessions).await,
});
}
RouteOutcome::ok(&FleetByProjectResponse {
projects: project_groups,
})
}