objectstore_server/web/
server.rs1use std::net::SocketAddr;
2
3use anyhow::{Context, Result};
4use tokio::net::{TcpListener, TcpSocket};
5use tokio::signal::unix::SignalKind;
6
7use crate::config::Config;
8use crate::state::Services;
9use crate::web::app::App;
10
11const TCP_LISTEN_BACKLOG: u32 = 1024;
13
14pub async fn server(config: Config) -> Result<()> {
19 tracing::info!("Starting server");
20 merni::counter!("server.start": 1);
21
22 let listener = listen(&config).context("failed to start TCP listener")?;
23 let state = Services::spawn(config).await?;
24
25 let server_handle = tokio::spawn(async move {
26 App::new(state)
27 .graceful_shutdown(true)
28 .serve(listener)
29 .await
30 });
31
32 tokio::spawn(async move {
33 elegant_departure::get_shutdown_guard().wait().await;
34 tracing::info!("Shutting down ...");
35 });
36
37 elegant_departure::tokio::depart()
38 .on_termination()
39 .on_sigint()
40 .on_signal(SignalKind::hangup())
41 .on_signal(SignalKind::quit())
42 .await;
43
44 let server_result = server_handle.await.map_err(From::from).flatten();
45 tracing::info!("Shutdown complete");
46 server_result
47}
48
49fn listen(config: &Config) -> Result<TcpListener> {
50 let addr = config.http_addr;
51 let socket = match addr {
52 SocketAddr::V4(_) => TcpSocket::new_v4(),
53 SocketAddr::V6(_) => TcpSocket::new_v6(),
54 }?;
55
56 #[cfg(all(unix, not(target_os = "solaris"), not(target_os = "illumos")))]
57 socket.set_reuseport(true)?;
58 socket.bind(addr)?;
59
60 let listener = socket.listen(TCP_LISTEN_BACKLOG)?;
61 tracing::info!("HTTP server listening on {addr}");
62
63 Ok(listener)
64}