use std::time::Duration;
use async_trait::async_trait;
use pingora::{
server::{ListenFds, ShutdownWatch},
services::Service,
};
use crate::stores::{self};
pub struct HealthService {}
impl HealthService {
pub fn new() -> Self {
Self {}
}
}
async fn run_health_check_loop() {
let mut interval = tokio::time::interval(Duration::from_secs(30));
interval.tick().await;
loop {
interval.tick().await;
let load_balancers = stores::get_routes()
.iter()
.flat_map(|(host, container)| {
container
.locations
.iter()
.map(|location| (host.clone(), location.load_balancer.clone()))
.collect::<Vec<_>>()
})
.chain(crate::tcp::load_balancers().iter().cloned())
.collect::<Vec<_>>();
for (host, load_balancer) in load_balancers {
tracing::trace!("Running health check for host {}", host);
load_balancer.update().await.ok();
load_balancer.backends().run_health_check(false).await;
}
}
}
#[async_trait]
impl Service for HealthService {
async fn start_service(
&mut self,
_fds: Option<ListenFds>,
_shutdown: ShutdownWatch,
_listeners_per_fd: usize,
) {
tracing::info!("Starting health check service");
run_health_check_loop().await;
}
fn name(&self) -> &'static str {
"health_check_service"
}
fn threads(&self) -> Option<usize> {
Some(1)
}
}