use crate::app_state::AppState;
use crate::configuration::{Args, Configuration};
use anyhow::Error;
use clap::Parser;
use detcd::Service;
use detcd::registrar::Registrar;
use run::{http1, http2};
use std::time::Duration;
use tokio::sync::watch;
use tokio::time::sleep;
mod app_state;
mod configuration;
mod run;
mod trace;
mod mailbox;
mod util;
mod extract;
mod backend;
#[tokio::main]
async fn main() {
let configuration = match Configuration::build(&Args::parse()) {
Ok(c) => c,
Err(e) => {
println!("{:#}", e);
return;
}
};
println!("{:?}", configuration);
#[cfg(debug_assertions)]
let to_console = true;
#[cfg(not(debug_assertions))]
let to_console = false;
let _guard = trace::init(&configuration, false, to_console);
if let Err(e) = run(configuration).await {
tracing::error!("{:#}", e);
}
tracing::info!("server exit!!!!");
}
async fn run(configuration: Configuration) -> Result<(), Error> {
let (quit_tx, quit_rx) = watch::channel(false);
let mut app_state = AppState::build(&configuration, quit_rx).await?;
let mut registrar = Registrar::<Service>::from((
app_state.etcd_client.clone(),
configuration.service.new_register_service(),
));
registrar
.register()
.await
.map_err(|e| Error::new(e).context("register service error"))?;
app_state
.set_id(registrar.service().key.id.unwrap())
.set_namespace(configuration.service.namespace.clone())
.set_running(registrar.status().registered());
if configuration.server.is_http1() {
http1::run(app_state.clone(), &configuration).await?;
} else {
http2::run(app_state.clone(), &configuration).await?;
}
loop {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
let _ = quit_tx.send(true);
tracing::info!("waiting to exit gracefully");
break;
}
status = registrar.changed() => {
app_state.set_running(status.registered());
}
}
}
drop(registrar);
sleep(Duration::from_secs(5)).await;
tracing::info!("exit ok");
Ok(())
}