(args: AdminServerArgs)
| 330 | reason = "Force shutdown on double ctrl-c is intentional" |
| 331 | )] |
| 332 | pub async fn admin_server(args: AdminServerArgs) -> Result<(), Report<GraphError>> { |
| 333 | if args.healthcheck.healthcheck { |
| 334 | return wait_healthcheck( |
| 335 | || healthcheck(args.config.address.clone()), |
| 336 | &args.healthcheck, |
| 337 | ) |
| 338 | .await |
| 339 | .change_context(GraphError); |
| 340 | } |
| 341 | |
| 342 | let pool = PostgresStorePool::new( |
| 343 | &args.db_info, |
| 344 | &args.pool_config, |
| 345 | NoTls, |
| 346 | PostgresStoreSettings::default(), |
| 347 | ) |
| 348 | .await |
| 349 | .change_context(GraphError) |
| 350 | .map_err(|report| { |
| 351 | tracing::error!(error = ?report, "Failed to connect to database"); |
| 352 | report |
| 353 | })?; |
| 354 | |
| 355 | let lifecycle = ServerLifecycle::new(); |
| 356 | start_admin_server(pool, args.config, &lifecycle); |
| 357 | |
| 358 | // Wait for shutdown signal or unexpected server exit |
| 359 | let aborted = tokio::select! { |
| 360 | result = signal::ctrl_c() => { |
| 361 | match result { |
| 362 | Ok(()) => false, |
| 363 | Err(error) => { |
| 364 | tracing::error!("Failed to install Ctrl+C handler: {error}"); |
| 365 | true |
| 366 | } |
| 367 | } |
| 368 | } |
| 369 | () = lifecycle.abort.cancelled() => { |
| 370 | tracing::error!("Admin server exited unexpectedly"); |
| 371 | true |
| 372 | } |
| 373 | }; |
| 374 | |
| 375 | // Double ctrl-c for force shutdown |
| 376 | tokio::select! { |
| 377 | () = lifecycle.shutdown_and_wait() => {} |
| 378 | result = signal::ctrl_c() => { |
| 379 | if let Err(error) = result { |
| 380 | tracing::error!("Failed to install Ctrl+C handler: {error}"); |
| 381 | } |
| 382 | tracing::warn!("Forced shutdown"); |
| 383 | std::process::exit(1); |
| 384 | } |
| 385 | } |
| 386 | |
| 387 | tracing::info!("Shutdown complete"); |
| 388 | |
| 389 | if aborted { |
no test coverage detected