diff --git a/Cargo.lock b/Cargo.lock index aaca994..f9261c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,17 @@ # It is not intended for manual editing. version = 3 +[[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 = "android-tzdata" version = "0.1.1" @@ -43,7 +54,7 @@ dependencies = [ "async-trait", "axum-core", "axum-macros", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "http", @@ -117,6 +128,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84" + [[package]] name = "bumpalo" version = "3.13.0" @@ -240,6 +257,18 @@ dependencies = [ "libc", ] +[[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" @@ -337,6 +366,17 @@ dependencies = [ "byteorder", ] +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + [[package]] name = "h2" version = "0.3.19" @@ -362,6 +402,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 = "heck" version = "0.4.1" @@ -500,7 +558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] @@ -556,6 +614,16 @@ version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -617,6 +685,8 @@ dependencies = [ "chrono", "lazy_static", "openssl", + "r2d2", + "r2d2_sqlite", "reqwest", "serde", "serde-aux", @@ -704,7 +774,7 @@ version = "0.10.54" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -850,6 +920,12 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.59" @@ -868,13 +944,65 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot 0.12.1", + "scheduled-thread-pool", +] + +[[package]] +name = "r2d2_sqlite" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f31323d6161385f385046738df520e0e8694fa74852d35891fc0be08348ddc" +dependencies = [ + "r2d2", + "rusqlite", + "uuid", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -883,7 +1011,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -953,13 +1081,27 @@ dependencies = [ "winreg", ] +[[package]] +name = "rusqlite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" +dependencies = [ + "bitflags 2.3.1", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rustix" version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -988,6 +1130,15 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +dependencies = [ + "parking_lot 0.12.1", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -1000,7 +1151,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1281,7 +1432,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d1d42a9b3f3ec46ba828e8d376aec14592ea199f70a06a548587ecd1c4ab658" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bytes", "futures-core", "futures-util", @@ -1407,6 +1558,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +dependencies = [ + "getrandom", + "rand", +] + [[package]] name = "valuable" version = "0.1.0" @@ -1419,6 +1580,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 9536454..b2670b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,5 @@ chrono = { version = "0.4", features = ["serde"] } lazy_static = "1.4" serde-aux = "4" bincode = "1.3" +r2d2_sqlite = "0.22" +r2d2 = "0.8" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index cb3a246..c13c852 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use axum::{ routing::get, Json, Router, }; +use r2d2_sqlite::{rusqlite::params, SqliteConnectionManager}; use std::{env, net::SocketAddr}; use tokio::task::JoinSet; use types::{World, Zone}; @@ -24,20 +25,32 @@ async fn main() { // .with_max_level(Level::DEBUG) .init(); - let db = sled::open("/tmp/metagame").expect("open"); + // let db = sqlite::Connection::open_with_full_mutex(":memory:").unwrap(); + // db.execute("CREATE TABLE worlds (id INTEGER NOT NULL PRIMARY KEY, data BLOB);") + // .unwrap(); + + let sqlite_manager = SqliteConnectionManager::memory(); + let pool = r2d2::Pool::new(sqlite_manager).unwrap(); + pool.get() + .unwrap() + .execute( + "CREATE TABLE worlds (id INTEGER NOT NULL PRIMARY KEY, data BLOB);", + params![], + ) + .unwrap(); let app = Router::new() .layer(tower_http::trace::TraceLayer::new_for_http()) .route("/:world", get(get_one_world)) .route("/all", get(get_all_worlds)) .route("/", get(root)) - .with_state(db.clone()); + .with_state(pool.clone()); tokio::spawn(async move { loop { let mut set = JoinSet::new(); for world in vec![1, 10, 13, 17, 19, 40, 1000, 2000] { - set.spawn(get_world(db.clone(), world, true)); + set.spawn(get_world(pool.clone(), world, true)); } while let Some(_) = set.join_next().await {} @@ -64,11 +77,16 @@ async fn root() -> Html<&'static str> { Html(include_str!("./html/index.html")) } -pub async fn get_one_world(State(db): State, Path(world): Path) -> Json { +pub async fn get_one_world( + State(db): State>, + Path(world): Path, +) -> Json { Json(get_world(db, world, false).await) } -pub async fn get_all_worlds(State(db): State) -> Json> { +pub async fn get_all_worlds( + State(db): State>, +) -> Json> { let mut set = JoinSet::new(); let mut worlds = vec![World::default(); 8]; @@ -85,7 +103,11 @@ pub async fn get_all_worlds(State(db): State) -> Json> { Json(worlds) } -pub async fn get_world(db: sled::Db, world: i32, skip_cache: bool) -> World { +pub async fn get_world( + db: r2d2::Pool, + world: i32, + skip_cache: bool, +) -> World { if !skip_cache { match world_from_cache(db.clone(), world) { Ok(response) => return response, @@ -114,19 +136,21 @@ pub async fn get_world(db: sled::Db, world: i32, skip_cache: bool) -> World { cached_at: chrono::Utc::now(), }; - world_to_cache(db, world, &response); + world_to_cache(db.clone(), world, &response); response } -fn world_from_cache(db: sled::Db, world: i32) -> Result { - let key = format!("world:{}", world); - let value = match db.get(key) { - Ok(Some(value)) => value, - _ => return Err(()), - }; +fn world_from_cache(db: r2d2::Pool, world: i32) -> Result { + let db = db.get().unwrap(); + let mut query = db.prepare("SELECT data FROM worlds WHERE id = ?").unwrap(); + let value: Result, _> = query.query_row(params![world], |r| r.get(0)); - match bincode::deserialize::(&value) { + if value.is_err() { + return Err(()); + } + + match bincode::deserialize::(value.unwrap().as_slice()) { Ok(response) => { if response.cached_at + chrono::Duration::minutes(5) < chrono::Utc::now() { return Err(()); @@ -137,8 +161,9 @@ fn world_from_cache(db: sled::Db, world: i32) -> Result { } } -fn world_to_cache(db: sled::Db, world: i32, response: &World) { - let key = format!("world:{}", world); +fn world_to_cache(db: r2d2::Pool, world: i32, response: &World) { let value = bincode::serialize(response).unwrap(); - db.insert(key, value).unwrap(); + let db = db.get().unwrap(); + let mut query = db.prepare("INSERT INTO worlds (id, data) VALUES (?, ?) ON CONFLICT DO UPDATE SET data=excluded.data").unwrap(); + query.execute(params![world, value]).unwrap(); }