lenso-platform-core 0.1.3

Core runtime primitives for the Lenso backend framework.
Documentation
use crate::error::AppResult;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::sync::Arc;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum HealthStatus {
    Healthy,
    Degraded,
    Unhealthy,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct HealthReport {
    pub name: String,
    pub status: HealthStatus,
    pub message: Option<String>,
}

#[async_trait]
pub trait HealthCheck: Debug + Send + Sync {
    fn name(&self) -> &'static str;
    async fn check(&self) -> AppResult<HealthReport>;
}

#[derive(Clone, Default)]
pub struct HealthRegistry {
    checks: Arc<Vec<Arc<dyn HealthCheck>>>,
}

impl Debug for HealthRegistry {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        formatter
            .debug_struct("HealthRegistry")
            .field("checks", &self.checks.len())
            .finish()
    }
}

impl HealthRegistry {
    pub fn new(checks: Vec<Arc<dyn HealthCheck>>) -> Self {
        Self {
            checks: Arc::new(checks),
        }
    }

    pub fn checks(&self) -> &[Arc<dyn HealthCheck>] {
        &self.checks
    }

    pub async fn check_all(&self) -> Vec<HealthReport> {
        let mut reports = Vec::with_capacity(self.checks.len());
        for check in self.checks.iter() {
            match check.check().await {
                Ok(report) => reports.push(report),
                Err(error) => reports.push(HealthReport {
                    name: check.name().to_owned(),
                    status: HealthStatus::Unhealthy,
                    message: Some(error.public_message),
                }),
            }
        }
        reports
    }
}