mod context; mod health; mod shutdown; use context::AppContext; #[tokio::main] async fn main() -> anyhow::Result<()> { let ctx = AppContext::init().await?; tracing::info!("gitsync service starting"); let health_port = ctx.config.gitsync_health_port(); let health_server = health::start_health(health_port, ctx.db.clone(), ctx.cache.clone())?; let health_handle = health_server.handle(); let health_task = tokio::spawn(health_server); let sync_service = git::sync::ReceiveSyncService::new(ctx.redis_pool.clone()); let consumer = git::sync::consumer::SyncConsumer::new(sync_service, 5); let worker = git::sync::worker::SyncWorker::new( consumer, ctx.db.clone(), ctx.cache.clone(), ctx.redis_pool.clone(), ctx.config.clone(), format!("gitsync-{}", uuid::Uuid::new_v4()), ); let worker_task = tokio::spawn(async move { worker.run().await }); tokio::select! { result = health_task => { match result { Ok(Ok(())) => tracing::info!("health server stopped"), Ok(Err(e)) => tracing::error!("health server error: {}", e), Err(e) => tracing::error!("health task panicked: {}", e), } } _ = worker_task => { tracing::info!("sync worker stopped"); } _ = shutdown::wait_for_shutdown_signal() => { tracing::info!("shutdown signal received, stopping gitsync service"); health_handle.stop(true).await; } } Ok(()) }