refactor(server): lay groundwork for unix socket configuration
parent
7abce21aee
commit
dca4d2d1ec
|
@ -1,3 +1,6 @@
|
||||||
data_dir = "./data"
|
data_dir = "./data"
|
||||||
domain = "127.0.0.1"
|
domain = "127.0.0.1"
|
||||||
port = 8080
|
port = 8080
|
||||||
|
|
||||||
|
[net]
|
||||||
|
type = "tcp"
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod serve;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand, ValueEnum};
|
||||||
use figment::{
|
use figment::{
|
||||||
providers::{Env, Format, Serialized, Toml},
|
providers::{Env, Format, Serialized, Toml},
|
||||||
Figment,
|
Figment,
|
||||||
|
@ -24,7 +24,7 @@ pub struct Cli {
|
||||||
pub cmd: Command,
|
pub cmd: Command,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Args, Clone)]
|
#[derive(Serialize, Args, Clone, Debug)]
|
||||||
pub struct ClapConfig {
|
pub struct ClapConfig {
|
||||||
#[arg(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
|
@ -35,21 +35,37 @@ pub struct ClapConfig {
|
||||||
)]
|
)]
|
||||||
config_file: Option<PathBuf>,
|
config_file: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[command(flatten)]
|
||||||
|
net: NetConfig,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[arg(long = "data", value_name = "DATA_DIR", global = true)]
|
#[arg(long = "data", value_name = "DATA_DIR", global = true)]
|
||||||
data_dir: Option<PathBuf>,
|
data_dir: Option<PathBuf>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[arg(short, long, value_name = "DOMAIN", global = true)]
|
#[arg(short, long = "log", value_name = "LOG_LEVEL", global = true)]
|
||||||
|
log_level: Option<LogLevel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ValueEnum, Serialize, Clone, Debug)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum NetConfigType {
|
||||||
|
Tcp,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Clone, Args, Debug)]
|
||||||
|
pub struct NetConfig {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[arg(long = "net", value_name = "NET", global = true)]
|
||||||
|
r#type: Option<NetConfigType>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
#[arg(long, value_name = "DOMAIN", global = true)]
|
||||||
domain: Option<String>,
|
domain: Option<String>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[arg(short, long, value_name = "PORT", global = true)]
|
#[arg(long, value_name = "PORT", global = true)]
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
#[arg(short, long = "log", value_name = "LOG_LEVEL", global = true)]
|
|
||||||
log_level: Option<LogLevel>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
|
@ -65,17 +81,18 @@ pub enum Command {
|
||||||
|
|
||||||
impl Cli {
|
impl Cli {
|
||||||
pub fn run(&self) -> u8 {
|
pub fn run(&self) -> u8 {
|
||||||
let mut figment = Figment::new();
|
let mut figment =
|
||||||
|
Figment::new().merge(Serialized::defaults(crate::config::Config::default()));
|
||||||
|
|
||||||
if let Some(config_path) = &self.config.config_file {
|
if let Some(config_path) = &self.config.config_file {
|
||||||
figment = figment.merge(Toml::file(config_path));
|
figment = figment.merge(Toml::file(config_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
let config: crate::config::Config = match figment
|
let config = figment
|
||||||
.merge(Env::prefixed("OTTER_"))
|
.merge(Env::prefixed("OTTER_"))
|
||||||
.merge(Serialized::defaults(self.config.clone()))
|
.merge(Serialized::defaults(self.config.clone()));
|
||||||
.extract()
|
|
||||||
{
|
let config = match config.extract::<crate::config::Config>() {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
use crate::server;
|
use crate::{config::NetConfig, server};
|
||||||
|
|
||||||
pub fn serve(config: &crate::config::Config) -> u8 {
|
pub fn serve(config: &crate::config::Config) -> u8 {
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
|
@ -27,13 +27,12 @@ pub fn serve(config: &crate::config::Config) -> u8 {
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let address = format!("{}:{}", config.domain, config.port);
|
// Spawn the session cleanup background task
|
||||||
tracing::info!("Starting server on {address}");
|
|
||||||
|
|
||||||
let session_removal_duration = Duration::from_secs(config.session_cleanup_interval);
|
let session_removal_duration = Duration::from_secs(config.session_cleanup_interval);
|
||||||
|
|
||||||
rt.block_on(async {
|
tracing::info!("Starting session cleanup background task");
|
||||||
tokio::task::spawn(async move {
|
|
||||||
|
rt.spawn(async move {
|
||||||
let mut interval = tokio::time::interval(session_removal_duration);
|
let mut interval = tokio::time::interval(session_removal_duration);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -52,11 +51,21 @@ pub fn serve(config: &crate::config::Config) -> u8 {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
tracing::info!("Initializing server");
|
||||||
|
|
||||||
|
match &config.net {
|
||||||
|
NetConfig::Tcp { domain, port } => {
|
||||||
|
let address = format!("{}:{}", domain, port);
|
||||||
|
tracing::info!("Listening on TCP address {address}");
|
||||||
|
|
||||||
|
rt.block_on(async {
|
||||||
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
||||||
axum::serve(listener, app.into_make_service())
|
axum::serve(listener, app.into_make_service())
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
||||||
use clap::ValueEnum;
|
use clap::ValueEnum;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone, ValueEnum, Copy)]
|
#[derive(Deserialize, Serialize, Clone, ValueEnum, Copy, Debug)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum LogLevel {
|
pub enum LogLevel {
|
||||||
Debug,
|
Debug,
|
||||||
|
@ -23,37 +23,32 @@ impl From<LogLevel> for tracing::Level {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum NetConfig {
|
||||||
|
Tcp { domain: String, port: u16 },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
#[serde(default = "default_data_dir")]
|
pub net: NetConfig,
|
||||||
pub data_dir: PathBuf,
|
pub data_dir: PathBuf,
|
||||||
#[serde(default = "default_domain")]
|
|
||||||
pub domain: String,
|
|
||||||
#[serde(default = "default_port")]
|
|
||||||
pub port: u16,
|
|
||||||
#[serde(default = "default_session_cleanup_interval")]
|
|
||||||
pub session_cleanup_interval: u64,
|
pub session_cleanup_interval: u64,
|
||||||
#[serde(default = "default_log_level")]
|
|
||||||
pub log_level: LogLevel,
|
pub log_level: LogLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_data_dir() -> PathBuf {
|
impl Default for Config {
|
||||||
PathBuf::from("./data")
|
fn default() -> Self {
|
||||||
}
|
Self {
|
||||||
|
net: NetConfig::Tcp {
|
||||||
fn default_domain() -> String {
|
domain: "127.0.0.1".to_string(),
|
||||||
"127.0.0.1".to_string()
|
port: 8080,
|
||||||
}
|
},
|
||||||
|
data_dir: "./data".into(),
|
||||||
fn default_port() -> u16 {
|
// Once per day
|
||||||
8080
|
session_cleanup_interval: 60 * 60 * 24,
|
||||||
}
|
log_level: LogLevel::Warn,
|
||||||
|
}
|
||||||
fn default_session_cleanup_interval() -> u64 {
|
}
|
||||||
// Default is once a day
|
|
||||||
60 * 60 * 24
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_log_level() -> LogLevel {
|
|
||||||
LogLevel::Warn
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue