use std::net::SocketAddr;
use std::sync::Arc;
use sqlx::PgPool;
use tokio::net::TcpListener;
use tokio::sync::mpsc;
use uuid::Uuid;
use crate::api::{create_router, AdminAuth, ConnectionManager};
use crate::db::DataPlanesRepository;
const STALE_SWEEP_INTERVAL_SECS: u64 = 60;
const STALE_THRESHOLD_MINUTES: i64 = 2;
const OFFLINE_RETENTION_MINUTES: i64 = 24 * 60;
pub struct ServerConfig {
pub listen_addr: SocketAddr,
pub pool: PgPool,
pub admin_auth: AdminAuth,
}
pub async fn run(config: ServerConfig) -> anyhow::Result<()> {
let repo = DataPlanesRepository::new(config.pool.clone());
let marked = repo.mark_all_offline().await?;
if marked > 0 {
tracing::info!(
count = marked,
"Marked stale data planes as offline on startup"
);
}
let (tx, rx) = mpsc::channel::<Uuid>(100);
let worker_pool = config.pool.clone();
tokio::spawn(async move {
crate::compiler::run_worker(worker_pool, rx).await;
});
let sweep_pool = config.pool.clone();
tokio::spawn(async move {
run_stale_sweep(sweep_pool).await;
});
let connection_manager = Arc::new(ConnectionManager::new());
let app = create_router(config.pool, Some(tx), connection_manager, config.admin_auth);
let listener = TcpListener::bind(config.listen_addr).await?;
tracing::info!("Control plane listening on {}", config.listen_addr);
axum::serve(listener, app).await?;
Ok(())
}
async fn run_stale_sweep(pool: PgPool) {
let repo = DataPlanesRepository::new(pool);
let mut interval =
tokio::time::interval(std::time::Duration::from_secs(STALE_SWEEP_INTERVAL_SECS));
interval.tick().await;
loop {
interval.tick().await;
match repo.mark_stale_offline(STALE_THRESHOLD_MINUTES).await {
Ok(0) => {}
Ok(count) => {
tracing::info!(count, "Marked stale data planes as offline");
}
Err(e) => {
tracing::error!(error = %e, "Failed to sweep stale data planes");
}
}
match repo
.delete_offline_older_than(OFFLINE_RETENTION_MINUTES)
.await
{
Ok(0) => {}
Ok(count) => {
tracing::info!(count, "Deleted long-offline data planes past retention");
}
Err(e) => {
tracing::error!(error = %e, "Failed to reap offline data planes");
}
}
}
}