yggdrasil/api/database/
system_status.rs1#![allow(clippy::unused_unit, deprecated)]
2
3use dioxus::prelude::*;
9use serde::{Deserialize, Serialize};
10
11#[cfg(feature = "server")]
13use crate::api::auth::get_current_admin_user;
14#[cfg(feature = "server")]
15use crate::api::error::AppError;
16
17#[derive(Serialize, Deserialize, Debug, Clone)]
19pub struct CacheStat {
20 pub name: String,
21 pub entry_count: u64,
22 pub hits: u64,
23 pub misses: u64,
24 pub hit_rate: f64,
26}
27
28#[derive(Serialize, Deserialize, Debug, Clone)]
30pub struct ServerStatus {
31 pub uptime_secs: u64,
33 pub pool_size: usize,
35 pub pool_max_size: usize,
37 pub pool_available: usize,
39 pub pool_waiting: usize,
41 pub active_sessions: i64,
43 pub host: crate::sysinfo_sampler::SystemSnapshot,
45 pub caches: Vec<CacheStat>,
47}
48
49#[cfg(feature = "server")]
51static STARTED_AT: std::sync::LazyLock<std::time::Instant> =
52 std::sync::LazyLock::new(std::time::Instant::now);
53
54#[server(GetServerStatus, "/api")]
56pub async fn get_server_status() -> Result<ServerStatus, ServerFnError> {
57 let _user = get_current_admin_user().await?;
58
59 #[cfg(feature = "server")]
60 {
61 use crate::cache::cache_stats;
62 use crate::db::pool::{get_conn, DB_POOL};
63
64 let pool_status = DB_POOL.status();
66 let pool_size = pool_status.size;
67 let pool_max_size = pool_status.max_size;
68 let pool_available = pool_status.available;
69 let pool_waiting = pool_status.waiting;
70
71 let client = get_conn().await.map_err(AppError::db_conn)?;
73 let active_sessions: i64 = client
74 .query_one(
75 "SELECT count(*) FROM sessions WHERE expires_at > now()",
76 &[],
77 )
78 .await
79 .map_err(AppError::query)?
80 .get(0);
81
82 let uptime_secs = STARTED_AT.elapsed().as_secs();
84
85 let host = crate::sysinfo_sampler::read_snapshot().await;
87
88 let caches = cache_stats()
90 .into_iter()
91 .map(|s| CacheStat {
92 name: s.name.to_string(),
93 entry_count: s.entry_count,
94 hits: s.hits,
95 misses: s.misses,
96 hit_rate: s.hit_rate,
97 })
98 .collect();
99
100 Ok(ServerStatus {
101 uptime_secs,
102 pool_size,
103 pool_max_size,
104 pool_available,
105 pool_waiting,
106 active_sessions,
107 host,
108 caches,
109 })
110 }
111 #[cfg(not(feature = "server"))]
112 {
113 Ok(ServerStatus {
114 uptime_secs: 0,
115 pool_size: 0,
116 pool_max_size: 0,
117 pool_available: 0,
118 pool_waiting: 0,
119 active_sessions: 0,
120 host: crate::sysinfo_sampler::read_snapshot().await,
121 caches: vec![],
122 })
123 }
124}