Skip to main content

lilo_rm_core/
admin.rs

1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3
4use chrono::{DateTime, Utc};
5
6use crate::{Lifecycle, LostEvidence, VersionInfo};
7
8#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
9pub struct KillByPidRequest {
10    pub pid: u32,
11    pub signal: i32,
12    pub grace_secs: u64,
13}
14
15#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
16pub struct KillByPidResponse {
17    pub pid: u32,
18    pub signal: i32,
19    pub killed_after_grace: bool,
20}
21
22#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
23pub struct StatusFilter {
24    pub session_id: Option<Uuid>,
25    #[serde(default, skip_serializing_if = "Vec::is_empty")]
26    pub session_ids: Vec<Uuid>,
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub updated_since: Option<DateTime<Utc>>,
29    pub runtime: Option<String>,
30    pub state: Option<String>,
31}
32
33impl StatusFilter {
34    pub const fn empty() -> Self {
35        Self {
36            session_id: None,
37            session_ids: Vec::new(),
38            updated_since: None,
39            runtime: None,
40            state: None,
41        }
42    }
43
44    pub fn requested_session_ids(&self) -> Vec<Uuid> {
45        let mut ids = self.session_ids.clone();
46        if let Some(session_id) = self.session_id
47            && !ids.contains(&session_id)
48        {
49            ids.push(session_id);
50        }
51        ids
52    }
53}
54
55impl Default for StatusFilter {
56    fn default() -> Self {
57        Self::empty()
58    }
59}
60
61#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
62pub struct StatusResponse {
63    pub lifecycles: Vec<Lifecycle>,
64}
65
66#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
67pub struct WatcherCounts {
68    pub kqueue_watchers: usize,
69    pub shim_sockets: usize,
70}
71
72#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
73pub struct LifecycleCounts {
74    pub forking: u64,
75    pub running: u64,
76    pub exited: u64,
77    pub lost: u64,
78}
79
80#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
81pub struct MigrationState {
82    pub applied: usize,
83    pub total: usize,
84    pub applied_descriptions: Vec<String>,
85    pub pending_descriptions: Vec<String>,
86}
87
88#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
89pub struct RecentLostEvent {
90    pub session_id: Uuid,
91    pub evidence: LostEvidence,
92    pub occurred_at: DateTime<Utc>,
93}
94
95#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
96pub struct LauncherStatus {
97    pub runtime: String,
98    pub command: Option<String>,
99    pub error: Option<String>,
100}
101
102#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
103pub struct TmuxStatus {
104    pub available: bool,
105    pub version: Option<String>,
106    pub error: Option<String>,
107}
108
109/// Stable v0.2 daemon diagnostics JSON.
110///
111/// Clients may rely on the field names and JSON value kinds in this response.
112/// The concrete diagnostic values are host and process specific.
113#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
114pub struct DoctorResponse {
115    pub version: VersionInfo,
116    pub socket_path: String,
117    pub uptime_secs: u64,
118    pub sqlite: MigrationState,
119    pub lifecycles: LifecycleCounts,
120    pub watchers: WatcherCounts,
121    pub launchers: Vec<LauncherStatus>,
122    pub tmux: TmuxStatus,
123    pub last_probe_sweep: Option<DateTime<Utc>>,
124    pub recent_lost: Vec<RecentLostEvent>,
125}