diff --git a/Cargo.lock b/Cargo.lock index 783e8db..048f0f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -404,6 +404,12 @@ version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +[[package]] +name = "bytecount" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" + [[package]] name = "bytemuck" version = "1.15.0" @@ -416,6 +422,37 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] + [[package]] name = "cbc" version = "0.1.2" @@ -540,6 +577,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -699,6 +745,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "version_check", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1440,6 +1495,30 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "moka" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1911e88d5831f748a4097a43862d129e3c6fca831eecac9b8db6d01d93c9de2" +dependencies = [ + "async-lock 2.8.0", + "async-trait", + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "futures-util", + "once_cell", + "parking_lot", + "quanta", + "rustc_version", + "skeptic", + "smallvec", + "tagptr", + "thiserror", + "triomphe", + "uuid", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -1465,6 +1544,7 @@ dependencies = [ "anyhow", "fast_qr", "log", + "moka", "opentelemetry", "pegasus-common", "pretty_env_logger", @@ -1969,6 +2049,32 @@ version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.4.2", + "memchr", + "unicase", +] + +[[package]] +name = "quanta" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca0b7bac0b97248c40bb77288fc52029cf1459c0461ea1b05ee32ccf011de2c" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quote" version = "1.0.35" @@ -2008,6 +2114,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "raw-cpuid" +version = "11.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" +dependencies = [ + "bitflags 2.4.2", +] + [[package]] name = "rc-box" version = "1.2.0" @@ -2343,6 +2458,15 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.23" @@ -2396,6 +2520,9 @@ name = "semver" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +dependencies = [ + "serde", +] [[package]] name = "serde" @@ -2515,6 +2642,21 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "skeptic" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" +dependencies = [ + "bytecount", + "cargo_metadata", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", +] + [[package]] name = "slab" version = "0.4.9" @@ -2648,6 +2790,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "take_mut" version = "0.2.2" @@ -2988,6 +3136,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "triomphe" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" + [[package]] name = "try-lock" version = "0.2.5" @@ -3159,6 +3313,16 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" diff --git a/rust-components/network-functions-handler/Cargo.toml b/rust-components/network-functions-handler/Cargo.toml index 763c62c..a5a368b 100644 --- a/rust-components/network-functions-handler/Cargo.toml +++ b/rust-components/network-functions-handler/Cargo.toml @@ -20,3 +20,4 @@ teloxide = { workspace = true, features = ["macros"] } serde = { workspace = true, features = ["derive"] } anyhow = "1.0" fast_qr = { version = "0.12", features = ["image"] } +moka = { version = "0.12", features = ["future"] } diff --git a/rust-components/network-functions-handler/src/handlers.rs b/rust-components/network-functions-handler/src/handlers.rs index 9d69235..a702144 100644 --- a/rust-components/network-functions-handler/src/handlers.rs +++ b/rust-components/network-functions-handler/src/handlers.rs @@ -1,4 +1,5 @@ use fast_qr::convert::Builder; +use moka::future::Cache; use teloxide::prelude::*; use teloxide::types::InputFile; use teloxide::utils::command::BotCommands; @@ -19,13 +20,33 @@ macro_rules! send_error_message { }; } -pub(crate) async fn qrcode_handler(bot: &Bot, message: &Message, text: &str) -> anyhow::Result<()> { +pub(crate) async fn qrcode_handler( + bot: Bot, + message: Message, + text: String, + cache: Cache>, +) -> anyhow::Result<()> { if text.is_empty() { send_error_message!(bot, message, "Text is empty"); return Err(anyhow::anyhow!("Text is empty")); } - let qr_code = match fast_qr::QRBuilder::new(text).build() { + // Check if QRCode already exists in cache + if let Some(data) = cache.get(&format!("qrcode:{}", &text).to_string()).await { + log::debug!("QRCode cache hit"); + + bot.send_photo( + message.chat.id, + InputFile::memory(data.to_vec()).file_name("qrcode.png"), + ) + .reply_to_message_id(message.id) + .send() + .await?; + + return Ok(()); + } + + let qr_code = match fast_qr::QRBuilder::new(text.clone()).build() { Ok(d) => d, Err(err) => { send_error_message!(bot, message, format!("Failed to generate QRCode: {}", err)); @@ -41,11 +62,15 @@ pub(crate) async fn qrcode_handler(bot: &Bot, message: &Message, text: &str) -> bot.send_photo( message.chat.id, - InputFile::memory(image).file_name("qrcode.png"), + InputFile::memory(image.clone()).file_name("qrcode.png"), ) .reply_to_message_id(message.id) .send() .await?; + cache + .insert(format!("qrcode:{}", text).to_string(), image.to_vec()) + .await; + Ok(()) } diff --git a/rust-components/network-functions-handler/src/run.rs b/rust-components/network-functions-handler/src/run.rs index 1316666..4ee8f2a 100644 --- a/rust-components/network-functions-handler/src/run.rs +++ b/rust-components/network-functions-handler/src/run.rs @@ -1,3 +1,4 @@ +use moka::future::Cache; use teloxide::prelude::*; use pegasus_common::bot::channel::MqUpdateListener; @@ -8,19 +9,13 @@ pub(crate) async fn run(bot: Bot, listener: MqUpdateListener) { let handler = dptree::entry().branch( Update::filter_message() .filter_command::() - .endpoint(|bot: Bot, cmd: Command, msg: Message| async move { - match cmd { - Command::QRCode(text) => qrcode_handler(&bot, &msg, text.as_str()) - .await - .map_err(|e| { - log::error!("Error handling qrcode command: {}", e); - e - }), - } - }), + .branch(dptree::case![Command::QRCode(string)].endpoint(qrcode_handler)), ); + let cache: Cache> = Cache::new(1000); + Dispatcher::builder(bot, handler) + .dependencies(dptree::deps![cache]) .build() .dispatch_with_listener( listener,