alex_db_server/
lib.rs

1use clap::Parser;
2use std::{error::Error, net::SocketAddr};
3use tokio::{
4    task,
5    time::{sleep, Duration},
6};
7use tracing::{error, info};
8use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
9
10type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
11
12mod access;
13mod api;
14mod app;
15mod config;
16mod error;
17
18#[derive(Parser, Debug)]
19#[command(author, version, about, long_about = None)]
20pub struct Args {
21    /// Data directory
22    #[arg(short, long)]
23    pub data_dir: Option<String>,
24
25    /// Enable API Key endpoint protection
26    #[arg(short, long)]
27    pub enable_security_api_keys: Option<bool>,
28
29    /// Port
30    #[arg(short, long)]
31    pub port: Option<u16>,
32
33    /// Database save triggered after write operations threshold
34    #[arg(long)]
35    pub save_triggered_by_threshold: Option<u16>,
36
37    /// Database save triggered after time in ms
38    #[arg(long)]
39    pub save_triggered_after_ms: Option<i64>,
40
41    /// Sleep time between database gc in ms
42    #[arg(long)]
43    pub sleep_time_between_gc_ms: Option<u64>,
44
45    /// Sleep time between database saves in ms
46    #[arg(long)]
47    pub sleep_time_between_saves_ms: Option<u64>,
48}
49
50pub async fn run() -> Result<()> {
51    tracing_subscriber::registry()
52        .with(
53            tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
54                "alex_db_server=error,runtime=error,tokio=error,tower_http=error".into()
55            }),
56        )
57        .with(tracing_subscriber::fmt::layer())
58        .init();
59
60    let args = Args::parse();
61    let config = config::load(args)?;
62
63    let app = app::get_app(config.clone()).await?;
64
65    let db_for_deleting = app.db.clone();
66    task::spawn(async move {
67        loop {
68            let res = db_for_deleting.gc();
69
70            if let Err(e) = res {
71                error!("Error: {:?}", e);
72            }
73
74            sleep(Duration::from_millis(
75                config.db_config.sleep_time_between_gc_ms,
76            ))
77            .await;
78        }
79    });
80
81    let db_for_saving = app.db;
82    task::spawn(async move {
83        loop {
84            let res = db_for_saving.save();
85
86            if let Err(e) = res {
87                error!("Error: {:?}", e);
88            }
89
90            sleep(Duration::from_millis(
91                config.db_config.sleep_time_between_saves_ms,
92            ))
93            .await;
94        }
95    });
96
97    let addr = SocketAddr::from(([0, 0, 0, 0], config.port));
98    info!("listening on {}", addr);
99    axum::Server::bind(&addr)
100        .serve(app.router.into_make_service())
101        .await
102        .unwrap();
103
104    Ok(())
105}