From 81daf525b86db129ea8c6b78a8d150620ec65900 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Thu, 25 Aug 2022 20:47:25 -0400 Subject: [PATCH] Add a rocksdb session store implementation --- Cargo.lock | 386 +++++++++++++++++++++++++++++++++- kitchen/Cargo.toml | 3 + kitchen/src/web/mod.rs | 126 +++++++++++ kitchen/src/web/session.rs | 94 +++++++++ web/src/router_integration.rs | 2 +- web/src/service.rs | 2 +- 6 files changed, 601 insertions(+), 12 deletions(-) create mode 100644 kitchen/src/web/mod.rs create mode 100644 kitchen/src/web/session.rs diff --git a/Cargo.lock b/Cargo.lock index b8e7c6d..4d88f1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "async-channel" version = "1.6.1" @@ -117,6 +135,27 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-session" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da4ce523b4e2ebaaf330746761df23a465b951a83d84bbce4233dabedae630" +dependencies = [ + "anyhow", + "async-lock", + "async-trait", + "base64", + "bincode", + "blake3", + "chrono", + "hmac", + "log", + "rand", + "serde", + "serde_json", + "sha2", +] + [[package]] name = "async-std" version = "1.12.0" @@ -228,12 +267,61 @@ dependencies = [ "mime", ] +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.60.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake3" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if 0.1.10", + "constant_time_eq", + "crypto-mac 0.8.0", + "digest", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -281,6 +369,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cache-padded" version = "1.2.0" @@ -292,6 +391,24 @@ name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" @@ -308,10 +425,49 @@ dependencies = [ "libc", "num-integer", "num-traits", + "serde", "time", "winapi", ] +[[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clang-sys" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "3.2.16" @@ -352,10 +508,16 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "cpufeatures" version = "0.2.2" @@ -371,10 +533,30 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "csv" version = "1.1.6" @@ -523,11 +705,17 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "gloo-net" version = "0.1.0" @@ -571,6 +759,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.12.3" @@ -586,6 +780,16 @@ dependencies = [ "libc", ] +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest", +] + [[package]] name = "http" version = "0.2.8" @@ -665,7 +869,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -680,6 +884,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.58" @@ -693,14 +906,17 @@ dependencies = [ name = "kitchen" version = "0.2.10" dependencies = [ + "async-session", "async-std", "async-trait", "axum", + "ciborium", "clap", "csv", "mime_guess", "recipe-store", "recipes", + "rocksdb", "rust-embed", "tower-http", "tracing", @@ -739,6 +955,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "lexical" version = "6.1.1" @@ -818,13 +1040,49 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "libloading" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + +[[package]] +name = "librocksdb-sys" +version = "0.8.0+7.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611804e4666a25136fcc5f8cf425ab4d26c7f74ea245ffe92ea23b85b6420b5d" +dependencies = [ + "bindgen", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "zstd-sys", +] + +[[package]] +name = "libz-sys" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "value-bag", ] @@ -862,6 +1120,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "mio" version = "0.8.4" @@ -874,6 +1138,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -956,6 +1230,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -994,19 +1274,31 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + [[package]] name = "polling" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "log", "wepoll-ffi", "winapi", ] +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + [[package]] name = "proc-macro2" version = "1.0.40" @@ -1025,6 +1317,36 @@ dependencies = [ "proc-macro2", ] +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + [[package]] name = "recipe-store" version = "0.2.10" @@ -1080,6 +1402,16 @@ dependencies = [ "gloo-net", ] +[[package]] +name = "rocksdb" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9562ea1d70c0cc63a34a22d977753b50cca91cc6b6527750463bd5dd8697bc" +dependencies = [ + "libc", + "librocksdb-sys", +] + [[package]] name = "rust-embed" version = "6.4.0" @@ -1114,6 +1446,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "ryu" version = "1.0.10" @@ -1179,7 +1517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer", - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", "opaque-debug", @@ -1194,6 +1532,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + [[package]] name = "slab" version = "0.4.7" @@ -1231,6 +1575,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "sycamore" version = "0.7.1" @@ -1418,7 +1768,7 @@ version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -1525,6 +1875,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" @@ -1576,7 +1932,7 @@ version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "serde", "serde_json", "wasm-bindgen-macro", @@ -1603,7 +1959,7 @@ version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -1730,3 +2086,13 @@ name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "zstd-sys" +version = "2.0.1+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +dependencies = [ + "cc", + "libc", +] diff --git a/kitchen/Cargo.toml b/kitchen/Cargo.toml index 50aec18..2234ef8 100644 --- a/kitchen/Cargo.toml +++ b/kitchen/Cargo.toml @@ -17,6 +17,9 @@ rust-embed="6.4.0" mime_guess = "2.0.4" async-trait = "0.1.57" tower-http = { version = "0.3.0", features = ["trace"] } +async-session = "3.0.0" +ciborium = "0.2.0" +rocksdb = "0.19.0" [dependencies.clap] version = "3.2.16" diff --git a/kitchen/src/web/mod.rs b/kitchen/src/web/mod.rs new file mode 100644 index 0000000..94f2d85 --- /dev/null +++ b/kitchen/src/web/mod.rs @@ -0,0 +1,126 @@ +// Copyright 2022 Jeremy Wall +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use std::net::SocketAddr; +use std::path::PathBuf; +use std::sync::Arc; + +use axum::{ + body::{boxed, Full}, + extract::{Extension, Path}, + http::{header, StatusCode}, + response::{IntoResponse, Redirect, Response}, + routing::{get, Router}, +}; +use mime_guess; +use recipe_store::{self, RecipeEntry, RecipeStore}; +use rust_embed::RustEmbed; +use tower_http::trace::TraceLayer; +use tracing::{debug, info, instrument}; + +mod session; + +#[derive(RustEmbed)] +#[folder = "../web/dist"] +struct UiAssets; + +pub struct StaticFile(pub T); + +impl IntoResponse for StaticFile +where + T: Into, +{ + fn into_response(self) -> Response { + let path = self.0.into(); + + match UiAssets::get(path.as_str()) { + Some(content) => { + let body = boxed(Full::from(content.data)); + let mime = mime_guess::from_path(path).first_or_octet_stream(); + Response::builder() + .header(header::CONTENT_TYPE, mime.as_ref()) + .body(body) + .unwrap() + } + None => Response::builder() + .status(StatusCode::NOT_FOUND) + .body(boxed(Full::from("404"))) + .unwrap(), + } + } +} + +#[instrument] +async fn ui_static_assets(Path(path): Path) -> impl IntoResponse { + info!("Serving ui path"); + + let mut path = path.trim_start_matches("/"); + path = if path == "" { "index.html" } else { path }; + debug!(path = path, "Serving transformed path"); + StaticFile(path.to_owned()) +} + +#[instrument] +async fn api_recipes(Extension(store): Extension>) -> Response { + let result: Result>, String> = match store + .get_recipes() + .await + .map_err(|e| format!("Error: {:?}", e)) + { + Ok(Some(recipes)) => Ok(axum::Json::from(recipes)), + Ok(None) => Ok(axum::Json::from(Vec::::new())), + Err(e) => Err(e), + }; + result.into_response() +} + +#[instrument] +async fn api_categories( + Extension(store): Extension>, +) -> Response { + let recipe_result = store + .get_categories() + .await + .map_err(|e| format!("Error: {:?}", e)); + let result: Result, String> = match recipe_result { + Ok(Some(categories)) => Ok(axum::Json::from(categories)), + Ok(None) => Ok(axum::Json::from(String::new())), + Err(e) => Err(e), + }; + result.into_response() +} + +#[instrument(fields(recipe_dir=?recipe_dir_path,listen=?listen_socket), skip_all)] +pub async fn ui_main(recipe_dir_path: PathBuf, listen_socket: SocketAddr) { + let store = Arc::new(recipe_store::AsyncFileStore::new(recipe_dir_path.clone())); + //let dir_path = (&dir_path).clone(); + let router = Router::new() + .route("/", get(|| async { Redirect::temporary("/ui/plan") })) + .route("/ui/*path", get(ui_static_assets)) + // recipes api path route + .route("/api/v1/recipes", get(api_recipes)) + // categories api path route + .route("/api/v1/categories", get(api_categories)) + // NOTE(jwall): Note that the layers are applied to the preceding routes not + // the following routes. + .layer(TraceLayer::new_for_http()) + .layer(Extension(store)); + info!( + http = format!("http://{}", listen_socket), + "Starting server" + ); + axum::Server::bind(&listen_socket) + .serve(router.into_make_service()) + .await + .expect("Failed to start service"); +} diff --git a/kitchen/src/web/session.rs b/kitchen/src/web/session.rs new file mode 100644 index 0000000..58a4209 --- /dev/null +++ b/kitchen/src/web/session.rs @@ -0,0 +1,94 @@ +// Copyright 2022 Jeremy Wall (Jeremy@marzhilsltudios.com) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use async_std::sync::Arc; +use std::path::Path; + +use async_session::{async_trait, Session, SessionStore}; +use ciborium; +use rocksdb::{ + BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, +}; + +const SESSION_CF: &'static str = "kitchen_session"; + +#[derive(Clone, Debug)] +pub struct RocksdbInnerStore { + db: Arc>, +} + +impl RocksdbInnerStore { + pub fn new>(name: P) -> Result { + let cf_opts = Options::default(); + let cf = ColumnFamilyDescriptor::new(SESSION_CF, cf_opts); + let mut opts = Options::default(); + opts.create_missing_column_families(true); + opts.create_if_missing(true); + Ok(Self { + db: Arc::new(DBWithThreadMode::open_cf_descriptors( + &opts, + name, + vec![cf], + )?), + }) + } + + fn get_column_family_handle(&self) -> Option> { + self.db.cf_handle(SESSION_CF) + } + + fn make_id_key(cookie_value: &str) -> async_session::Result { + Ok(Session::id_from_cookie_value(cookie_value)?) + } +} + +#[async_trait] +impl SessionStore for RocksdbInnerStore { + async fn load_session(&self, cookie_value: String) -> async_session::Result> { + let id = Self::make_id_key(&cookie_value)?; + let cf_handle = self + .get_column_family_handle() + .expect(&format!("column family {} is missing", SESSION_CF)); + if let Some(payload) = self.db.get_cf(&cf_handle, id.as_bytes())? { + let session: Session = ciborium::de::from_reader(payload.as_slice())?; + return Ok(Some(session)); + } + Ok(None) + } + + async fn store_session(&self, session: Session) -> async_session::Result> { + let id = session.id(); + let mut payload: Vec = Vec::new(); + let cf_handle = self + .get_column_family_handle() + .expect(&format!("column family {} is missing", SESSION_CF)); + ciborium::ser::into_writer(&session, &mut payload)?; + self.db + .put_cf(&cf_handle, id.as_bytes(), payload.as_slice())?; + Ok(session.into_cookie_value()) + } + + async fn destroy_session(&self, session: Session) -> async_session::Result { + let id = session.id(); + let cf_handle = self + .get_column_family_handle() + .expect(&format!("column family {} is missing", SESSION_CF)); + self.db.delete_cf(&cf_handle, id.as_bytes())?; + Ok(()) + } + + async fn clear_store(&self) -> async_session::Result { + self.db.drop_cf(SESSION_CF)?; + Ok(()) + } +} diff --git a/web/src/router_integration.rs b/web/src/router_integration.rs index 540c6aa..984b5e2 100644 --- a/web/src/router_integration.rs +++ b/web/src/router_integration.rs @@ -193,7 +193,7 @@ impl DeriveRoute for AppRoutes { let (_origin, path, _hash) = input; let route = match path.as_str() { "" | "/" | "/ui/" => AppRoutes::default(), - "/ui/plan" | "/" => AppRoutes::Plan, + "/ui/plan" => AppRoutes::Plan, "/ui/cook" => AppRoutes::Cook, "/ui/inventory" => AppRoutes::Inventory, h => { diff --git a/web/src/service.rs b/web/src/service.rs index 1054a3b..1351b18 100644 --- a/web/src/service.rs +++ b/web/src/service.rs @@ -243,7 +243,7 @@ where .collect() } - pub fn set_recipes(&mut self, mut recipes: BTreeMap) { + pub fn set_recipes(&mut self, recipes: BTreeMap) { self.recipes.set( recipes .iter()