use std::sync::Arc;
use hyphae::{JoinExt, MapExt, flat};
use crate::{
entities::client::GetAllClients,
prelude::*,
report::{ReportContext, ReportHandler},
};
#[myko_item]
pub struct Server {
pub version: String,
#[searchable]
pub address: String,
pub port: u16,
pub started_at: String, }
#[myko_query(Server)]
pub struct GetConnectedServer {}
impl QueryHandler for GetConnectedServer {
fn test_entity(ctx: QueryTestCtx<Self>) -> bool {
let item_id = ctx.item.id.to_string();
let host_id = ctx.query_context.req.host_id.to_string();
item_id == host_id
}
}
#[myko_query(Server)]
pub struct GetPeerServers {}
impl QueryHandler for GetPeerServers {
fn test_entity(ctx: QueryTestCtx<Self>) -> bool {
let item_id = ctx.item.id.to_string();
let host_id = ctx.query_context.req.host_id.to_string();
item_id != host_id
}
}
#[myko_macros::myko_report_output]
pub struct ServerStatsOutput {
pub server: Option<Arc<Server>>,
pub client_count: usize,
pub uptime_seconds: Option<i64>,
}
#[myko_macros::myko_report(ServerStatsOutput)]
pub struct ServerStats {}
impl ReportHandler for ServerStats {
type Output = ServerStatsOutput;
fn compute(&self, ctx: ReportContext) -> impl MaterializeDefinite<Arc<Self::Output>> {
ctx.query_map(GetConnectedServer {})
.entries()
.join(&ctx.query_map(GetAllClients {}).entries())
.map(flat!(|servers, clients| {
let server = servers.first().map(|(_, server)| server.clone());
let uptime_seconds = server.as_ref().and_then(|s| {
chrono::DateTime::parse_from_rfc3339(&s.started_at)
.ok()
.map(|started| {
let now = chrono::Utc::now();
(now - started.with_timezone(&chrono::Utc)).num_seconds()
})
});
Arc::new(ServerStatsOutput {
server,
client_count: clients.len(),
uptime_seconds,
})
}))
}
}