yggdrasil/api/database/
system_status.rs1#![allow(clippy::unused_unit, deprecated)]
2
3use crate::api::error::ApiError;
9use leptos::prelude::*;
10use serde::{Deserialize, Serialize};
11
12#[cfg(feature = "server")]
14use crate::api::auth::get_current_admin_user;
15#[cfg(feature = "server")]
16use crate::api::error::AppError;
17
18#[derive(Serialize, Deserialize, Debug, Clone)]
20pub struct CacheStat {
21 pub name: String,
22 pub entry_count: u64,
23 pub hits: u64,
24 pub misses: u64,
25 pub hit_rate: f64,
27}
28
29#[derive(Serialize, Deserialize, Debug, Clone)]
31pub struct ServerStatus {
32 pub uptime_secs: u64,
34 pub pool_size: usize,
36 pub pool_max_size: usize,
38 pub pool_available: usize,
40 pub pool_waiting: usize,
42 pub active_sessions: i64,
44 pub host: crate::models::system::SystemSnapshot,
46 pub caches: Vec<CacheStat>,
48}
49
50#[cfg(feature = "server")]
52static STARTED_AT: std::sync::LazyLock<std::time::Instant> =
53 std::sync::LazyLock::new(std::time::Instant::now);
54
55#[server(GetServerStatus, endpoint = "get_server_status", input = leptos::server_fn::codec::Json)]
57pub async fn get_server_status() -> Result<ServerStatus, ApiError> {
58 let _user = get_current_admin_user().await?;
59
60 #[cfg(feature = "server")]
61 {
62 use crate::cache::cache_stats;
63 use crate::db::pool::{get_conn, DB_POOL};
64
65 let pool_status = DB_POOL.status();
67 let pool_size = pool_status.size;
68 let pool_max_size = pool_status.max_size;
69 let pool_available = pool_status.available;
70 let pool_waiting = pool_status.waiting;
71
72 let client = get_conn().await.map_err(AppError::db_conn)?;
74 let active_sessions: i64 = client
75 .query_one(
76 "SELECT count(*) FROM sessions WHERE expires_at > now()",
77 &[],
78 )
79 .await
80 .map_err(AppError::query)?
81 .get(0);
82
83 let uptime_secs = STARTED_AT.elapsed().as_secs();
85
86 let host = crate::tasks::sysinfo_sampler::read_snapshot().await;
88
89 let caches = cache_stats()
91 .into_iter()
92 .map(|s| CacheStat {
93 name: s.name.to_string(),
94 entry_count: s.entry_count,
95 hits: s.hits,
96 misses: s.misses,
97 hit_rate: s.hit_rate,
98 })
99 .collect();
100
101 Ok(ServerStatus {
102 uptime_secs,
103 pool_size,
104 pool_max_size,
105 pool_available,
106 pool_waiting,
107 active_sessions,
108 host,
109 caches,
110 })
111 }
112 #[cfg(not(feature = "server"))]
113 {
114 Ok(ServerStatus {
115 uptime_secs: 0,
116 pool_size: 0,
117 pool_max_size: 0,
118 pool_available: 0,
119 pool_waiting: 0,
120 active_sessions: 0,
121 host: crate::models::system::SystemSnapshot::default(),
122 caches: vec![],
123 })
124 }
125}