forked from lavina/lavina
1
0
Fork 0
lavina/src/main.rs

105 lines
2.8 KiB
Rust

#![feature(
generators,
generator_trait,
type_alias_impl_trait,
impl_trait_in_assoc_type
)]
mod core;
mod prelude;
mod projections;
mod protos;
mod util;
use std::future::Future;
use figment::providers::Format;
use figment::{providers::Toml, Figment};
use prometheus::Registry as MetricsRegistry;
use serde::Deserialize;
use crate::core::player::PlayerRegistry;
use crate::core::repo::Storage;
use crate::core::room::RoomRegistry;
use crate::prelude::*;
#[derive(Deserialize, Debug)]
struct ServerConfig {
telemetry: util::telemetry::ServerConfig,
irc: projections::irc::ServerConfig,
xmpp: projections::xmpp::ServerConfig,
storage: core::repo::StorageConfig,
}
fn load_config() -> Result<ServerConfig> {
// TODO get config path as a cmd line arg
let raw_config = Figment::new()
.merge(Toml::file("config.toml"))
.merge(Toml::file("/etc/lavina/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()?;
tracing::info!("Booting up");
tracing::info!("Loaded config: {config:?}");
let ServerConfig {
telemetry: telemetry_config,
irc: irc_config,
xmpp: xmpp_config,
storage: storage_config,
} = config;
let mut metrics = MetricsRegistry::new();
let storage = Storage::open(storage_config).await?;
let rooms = RoomRegistry::new(&mut metrics, storage.clone())?;
let mut players = PlayerRegistry::empty(rooms.clone(), &mut metrics)?;
let telemetry_terminator =
util::telemetry::launch(telemetry_config, metrics.clone(), rooms.clone()).await?;
let irc = projections::irc::launch(irc_config, players.clone(), rooms.clone(), metrics.clone(), storage.clone()).await?;
let xmpp = projections::xmpp::launch(xmpp_config, players.clone(), rooms.clone(), metrics.clone()).await?;
tracing::info!("Started");
sleep.await;
tracing::info!("Begin shutdown");
xmpp.terminate().await?;
irc.terminate().await?;
telemetry_terminator.terminate().await?;
players.shutdown_all().await?;
drop(players);
drop(rooms);
storage.close().await?;
tracing::info!("Shutdown complete");
Ok(())
}
#[cfg(windows)]
fn ctrl_c() -> Result<impl Future<Output = ()>> {
use tokio::signal::windows::*;
let chan = ctrl_c()?;
async fn recv(mut chan: CtrlC) {
let _ = chan.recv().await;
}
Ok(recv(chan))
}
#[cfg(unix)]
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(())
}