diff --git a/.envrc b/.envrc index ffccafd..5066f56 100644 --- a/.envrc +++ b/.envrc @@ -1,4 +1,5 @@ watch_file flake.nix flake.lock dotenv_if_exists +export ANALYTICS_DB="db/analytics.db" export GEOLITE2_COUNTRY_DB="db/ip_country_sample.mmdb" use flake diff --git a/Cargo.lock b/Cargo.lock index b626896..1c25a32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.0.1" @@ -643,6 +654,18 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" version = "1.9.0" @@ -893,6 +916,24 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa" +dependencies = [ + "hashbrown 0.13.2", +] + [[package]] name = "hazy" version = "0.1.1" @@ -1094,7 +1135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -1201,6 +1242,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "libsqlite3-sys" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f835d03d717946d28b1d1ed632eb6f0e24a299388ee623d0c23118d3e8a7fa" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.3.7" @@ -1209,11 +1260,12 @@ checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" [[package]] name = "locat" -version = "0.3.1" +version = "0.4.0" source = "registry+ssh://git@git.shipyard.rs/menteeth/crate-index.git" -checksum = "5710a18ee2dbe5aff9a408bc48e25a9c53116b2e3a0a334b23388437806c0884" +checksum = "8be9ea47c9293870c87ce3820d1abfcea3de226168f2ab01e395ab1995394a83" dependencies = [ "maxminddb", + "rusqlite", "thiserror", ] @@ -1835,6 +1887,20 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" +[[package]] +name = "rusqlite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/Cargo.toml b/Cargo.toml index 9d8f4c8..191284b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ artem = { version = "=1.1.5", default-features = false } axum = "0.6" color-eyre = "0.6" image = "0.24" -locat = { version = "0.3.1", registry = "menteeth" } +locat = { version = "0.4.0", registry = "menteeth" } opentelemetry = { version = "0.18", features = ["rt-tokio"] } opentelemetry-honeycomb = { git = "https://github.com/fasterthanlime/opentelemetry-honeycomb-rs", branch = "simplified", version = "0.1.0" } pretty-hex = "0.3" diff --git a/flake.nix b/flake.nix index 888531f..fcea8e0 100644 --- a/flake.nix +++ b/flake.nix @@ -39,6 +39,7 @@ buildInputs = [ openssl pkg-config + sqlite ] ++ (if inShell then [ # In 'nix develop', provide some developer tools. rust-analyzer diff --git a/src/main.rs b/src/main.rs index e3713eb..9caeb3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,12 +48,20 @@ async fn main() { let cdb_env_var = "GEOLITE2_COUNTRY_DB"; let cdb_path = std::env::var(cdb_env_var) .unwrap_or_else(|_| panic!("${cdb_env_var} must be set")); + + let adb_env_var = "ANALYTICS_DB"; + let adb_path = std::env::var(adb_env_var) + .unwrap_or_else(|_| panic!("${adb_env_var} must be set")); + let state = ServerState { client: Default::default(), - locat: Arc::new(Locat::new(&cdb_path, "todo.db").unwrap()), + locat: Arc::new(Locat::new(&cdb_path, &adb_path).unwrap()), }; - let app = Router::new().route("/", get(root_get)).with_state(state); + let app = Router::new() + .route("/", get(root_get)) + .route("/analytics", get(analytics_get)) + .with_state(state); let quit_signal = async { _ = tokio::signal::ctrl_c().await; @@ -192,3 +200,13 @@ async fn download_file(client: &reqwest::Client, url: &str) -> color_eyre::Resul .await?; Ok(bytes.to_vec()) } + +async fn analytics_get(State(state): State) -> Response { + let analytics = state.locat.get_analytics().await.unwrap(); + let mut response = String::new(); + use std::fmt::Write; + for (country, count) in analytics { + _ = writeln!(&mut response, "{country}: {count}"); + } + response.into_response() +}