2023-01-19 17:18:41 +00:00
|
|
|
mod http;
|
|
|
|
mod prelude;
|
2023-01-19 17:58:56 +00:00
|
|
|
mod tcp;
|
2023-01-19 17:18:41 +00:00
|
|
|
|
|
|
|
use crate::prelude::*;
|
2023-01-27 20:43:20 +00:00
|
|
|
use prometheus::{IntCounter, Opts, Registry};
|
2023-01-19 17:58:56 +00:00
|
|
|
use tcp::ClientSocketActor;
|
2023-01-19 14:25:52 +00:00
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::future::Future;
|
|
|
|
use std::net::SocketAddr;
|
2023-01-27 20:43:20 +00:00
|
|
|
use std::sync::Arc;
|
2023-01-19 14:25:52 +00:00
|
|
|
|
|
|
|
use figment::providers::Format;
|
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
|
|
|
|
use figment::{providers::Toml, Figment};
|
|
|
|
use serde::Deserialize;
|
2023-01-26 21:11:28 +00:00
|
|
|
use tokio::io::BufWriter;
|
|
|
|
use tokio::sync::mpsc::Sender;
|
2023-01-19 14:25:52 +00:00
|
|
|
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
struct ServerConfig {
|
|
|
|
cluster: ClusterConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
struct ClusterConfig {
|
|
|
|
name: String,
|
|
|
|
servers: Vec<SocketAddr>,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn load_config() -> Result<ServerConfig> {
|
|
|
|
let raw_config = Figment::new().merge(Toml::file("config.toml"));
|
|
|
|
let config: ServerConfig = raw_config.extract()?;
|
|
|
|
Ok(config)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<()> {
|
|
|
|
set_up_logging()?;
|
|
|
|
let sleep = ctrl_c()?;
|
|
|
|
let config = load_config()?;
|
|
|
|
dbg!(config);
|
|
|
|
tracing::info!("Booting up");
|
2023-01-27 20:43:20 +00:00
|
|
|
let registry = Arc::new(Registry::new());
|
|
|
|
let counter = IntCounter::with_opts(Opts::new("actor_count", "Number of alive actors"))?;
|
|
|
|
registry.register(Box::new(counter.clone()))?;
|
|
|
|
|
2023-01-19 14:25:52 +00:00
|
|
|
let listener = TcpListener::bind("127.0.0.1:3721").await?;
|
2023-01-19 17:18:41 +00:00
|
|
|
let listener_http = TcpListener::bind("127.0.0.1:8080").await?;
|
2023-01-27 20:43:20 +00:00
|
|
|
let http_server_actor = http::HttpServerActor::launch(listener_http, registry.clone()).await?;
|
2023-01-19 17:18:41 +00:00
|
|
|
|
2023-01-19 14:25:52 +00:00
|
|
|
tracing::info!("Started");
|
|
|
|
|
|
|
|
run(listener, sleep).await?;
|
|
|
|
|
|
|
|
// sleep.await;
|
|
|
|
tracing::info!("Begin shutdown");
|
2023-01-19 17:18:41 +00:00
|
|
|
http_server_actor.terminate().await?;
|
2023-01-19 14:25:52 +00:00
|
|
|
tracing::info!("Shutdown complete");
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ctrl_c() -> Result<impl Future<Output = ()>> {
|
|
|
|
use tokio::signal::unix::*;
|
|
|
|
let chan = signal(SignalKind::interrupt())?;
|
|
|
|
async fn recv(mut chan: Signal) {
|
|
|
|
let _ = chan.recv().await;
|
|
|
|
}
|
|
|
|
Ok(recv(chan))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_up_logging() -> Result<()> {
|
|
|
|
tracing_subscriber::fmt::init();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn run(listener: TcpListener, shutdown: impl Future<Output = ()>) -> Result<()> {
|
|
|
|
tokio::pin!(shutdown);
|
|
|
|
|
|
|
|
let mut counter: u32 = 0;
|
|
|
|
let mut conns: HashMap<u32, _> = HashMap::new();
|
|
|
|
|
|
|
|
let (sender, mut chan) = tokio::sync::mpsc::channel(32);
|
|
|
|
|
|
|
|
loop {
|
|
|
|
let accept = listener.accept();
|
|
|
|
tokio::select! {
|
|
|
|
id = chan.recv() => {
|
|
|
|
match id {
|
|
|
|
Some(id) => {
|
|
|
|
conns.remove(&id);
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
result = accept => {
|
|
|
|
let (connect, address) = result?;
|
|
|
|
let id = counter;
|
|
|
|
counter += 1;
|
|
|
|
let fiber = handle_connection(connect, address, id, sender.clone()).await?;
|
|
|
|
conns.insert(id, fiber);
|
|
|
|
},
|
|
|
|
_ = &mut shutdown => break,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (_, i) in conns {
|
|
|
|
dbg!(i.terminate().await?);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn handle_connection(
|
|
|
|
connect: TcpStream,
|
|
|
|
address: SocketAddr,
|
|
|
|
id: u32,
|
|
|
|
updater: Sender<u32>,
|
|
|
|
) -> Result<ClientSocketActor> {
|
|
|
|
tracing::info!("Incoming socket #{} from {}", id, address);
|
|
|
|
let writer = BufWriter::new(connect);
|
|
|
|
Ok(ClientSocketActor::launch(writer, updater, id)?)
|
|
|
|
}
|