diff --git a/Cargo.lock b/Cargo.lock index 3d13bed..f1d2243 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,6 +50,156 @@ dependencies = [ "libc", ] +[[package]] +name = "arc-swap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +dependencies = [ + "concurrent-queue", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +dependencies = [ + "async-lock 3.3.0", + "async-task", + "concurrent-queue", + "fastrand 2.0.1", + "futures-lite 2.2.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.2.0", + "async-executor", + "async-io 2.3.2", + "async-lock 3.3.0", + "blocking", + "futures-lite 2.2.0", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.2.0", + "parking", + "polling 3.5.0", + "rustix 0.38.31", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", + "pin-project-lite", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" + [[package]] name = "async-trait" version = "0.1.77" @@ -61,6 +211,12 @@ dependencies = [ "syn 2.0.50", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.1.0" @@ -164,6 +320,22 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +dependencies = [ + "async-channel 2.2.0", + "async-lock 3.3.0", + "async-task", + "fastrand 2.0.1", + "futures-io", + "futures-lite 2.2.0", + "piper", + "tracing", +] + [[package]] name = "bumpalo" version = "3.15.3" @@ -260,6 +432,15 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -285,6 +466,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + [[package]] name = "crypto-common" version = "0.1.6" @@ -365,6 +561,16 @@ dependencies = [ "syn 2.0.50", ] +[[package]] +name = "deadqueue" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a2561fd313df162315935989dceb8c99db4ee1933358270a57a3cfb8c957f3" +dependencies = [ + "crossbeam-queue", + "tokio", +] + [[package]] name = "deranged" version = "0.3.11" @@ -386,10 +592,10 @@ dependencies = [ ] [[package]] -name = "dotenv" -version = "0.15.0" +name = "dotenvy" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "email-encoding" @@ -432,6 +638,63 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.2.0", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.0.1" @@ -468,6 +731,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -475,6 +753,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -483,12 +762,62 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +dependencies = [ + "fastrand 2.0.1", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + [[package]] name = "futures-sink" version = "0.3.30" @@ -507,8 +836,10 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -544,6 +875,18 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "h2" version = "0.3.24" @@ -856,6 +1199,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -877,6 +1231,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -894,7 +1257,7 @@ dependencies = [ "chumsky", "email-encoding", "email_address", - "fastrand", + "fastrand 2.0.1", "futures-io", "futures-util", "hostname", @@ -919,6 +1282,12 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -940,6 +1309,9 @@ name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +dependencies = [ + "value-bag", +] [[package]] name = "match_cfg" @@ -966,12 +1338,15 @@ dependencies = [ "axum", "cached", "chrono", - "dotenv", + "deadqueue", + "dotenvy", + "futures", "headers", "http 1.0.0", "lettre", "log", - "redis", + "redis 0.24.0", + "redis-work-queue", "reqwest", "serde", "serde_json", @@ -1125,6 +1500,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1186,18 +1567,65 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite", + "rustix 0.38.31", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[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.78" @@ -1231,6 +1659,61 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79ec282e887b434b68c18fe5c121d38e72a5cf35119b59e54ec5b992ea9c8eb0" +[[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 = "redis" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f49cdc0bb3f412bf8e7d1bd90fe1d9eb10bc5c399ba90973c14662a27b3f8ba" +dependencies = [ + "arc-swap", + "async-std", + "async-trait", + "bytes", + "combine", + "futures", + "futures-util", + "itoa", + "percent-encoding", + "pin-project-lite", + "ryu", + "sha1_smol", + "socket2 0.4.10", + "tokio", + "tokio-retry", + "tokio-util", + "url", +] + [[package]] name = "redis" version = "0.24.0" @@ -1252,6 +1735,19 @@ dependencies = [ "url", ] +[[package]] +name = "redis-work-queue" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf912baed64806b519b0b1e2e6879f02727319f6917f150d0440abc6a2ca1042" +dependencies = [ + "futures", + "redis 0.23.3", + "serde", + "serde_json", + "uuid", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1322,6 +1818,20 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.31" @@ -1331,7 +1841,7 @@ dependencies = [ "bitflags 2.4.2", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.13", "windows-sys 0.52.0", ] @@ -1666,8 +2176,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", - "fastrand", - "rustix", + "fastrand 2.0.1", + "rustix 0.38.31", "windows-sys 0.52.0", ] @@ -1777,6 +2287,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-retry" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" +dependencies = [ + "pin-project", + "rand", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.25.0" @@ -1921,6 +2442,28 @@ name = "uuid" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +dependencies = [ + "getrandom", + "rand", + "uuid-macro-internal", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abb14ae1a50dad63eaa768a458ef43d298cd1bd44951677bd10b732a9ba2a2d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + +[[package]] +name = "value-bag" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b" [[package]] name = "vcpkg" @@ -1934,6 +2477,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + [[package]] name = "want" version = "0.3.1" diff --git a/Cargo.toml b/Cargo.toml index afd41d7..f541215 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,11 @@ http = "1.0.0" reqwest = "0.11.24" serde_json = "1.0.114" cached = "0.49.2" -dotenv = "0.15.0" log = "0.4.20" lettre = { version = "0.11.4", default-features = false, features = ["smtp-transport", "tokio1-rustls-tls", "hostname", "builder"] } redis = { version = "0.24.0", features = ["aio", "tokio-comp"] } tower-http = { version = "0.5.2", features = ["cors"] } +dotenvy = "0.15.7" +futures = "0.3.30" +deadqueue = "0.2.4" +redis-work-queue = "0.1.6" diff --git a/src/config/config_auth.rs b/src/config/config_auth.rs index cfb8666..be889bd 100644 --- a/src/config/config_auth.rs +++ b/src/config/config_auth.rs @@ -8,7 +8,7 @@ pub struct ConfigAuth { #[cached] pub fn get_config_auth() -> ConfigAuth { - dotenv::dotenv().ok(); + dotenvy::dotenv().ok(); let url = env::var("AUTH_URL").expect("AUTH_URL must be set"); diff --git a/src/config/config_email.rs b/src/config/config_email.rs index d5c87d9..4f86135 100644 --- a/src/config/config_email.rs +++ b/src/config/config_email.rs @@ -1,7 +1,7 @@ use cached::proc_macro::cached; use std::env; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct ConfigEmail { pub smtp_server: String, pub smtp_port: u16, @@ -13,7 +13,7 @@ pub struct ConfigEmail { #[cached] pub fn get_config_email() -> ConfigEmail { - dotenv::dotenv().ok(); + dotenvy::dotenv().ok(); let server = env::var("SMTP_SERVER").expect("SMTP_SERVER must be set"); let port = env::var("SMTP_PORT").expect("SMTP_PORT must be set"); diff --git a/src/config/config_limits.rs b/src/config/config_limits.rs index b2f7014..5d3c8c9 100644 --- a/src/config/config_limits.rs +++ b/src/config/config_limits.rs @@ -9,7 +9,7 @@ pub struct ConfigLimits { #[cached] pub fn get_config_limits() -> ConfigLimits { - dotenv::dotenv().ok(); + dotenvy::dotenv().ok(); let max_requests = env::var("MAX_REQUESTS") .unwrap_or("10".to_string()) diff --git a/src/config/config_redis.rs b/src/config/config_redis.rs index 2c921fb..8224e0f 100644 --- a/src/config/config_redis.rs +++ b/src/config/config_redis.rs @@ -3,6 +3,7 @@ use std::env; #[derive(Clone)] pub struct ConfigRedis { + pub redis_db: u8, pub redis_url: String, pub redis_port: u16, pub redis_password: Option, @@ -10,13 +11,15 @@ pub struct ConfigRedis { #[cached] pub fn get_config_redis() -> ConfigRedis { - dotenv::dotenv().ok(); + dotenvy::dotenv().ok(); + let db = env::var("REDIS_DB").unwrap_or("0".to_string()); let url = env::var("REDIS_URL").unwrap_or("localhost".to_string()); let port = env::var("REDIS_PORT").unwrap_or("6379".to_string()); let password = env::var("REDIS_PASSWORD").ok(); ConfigRedis { + redis_db: db.parse::().unwrap(), redis_url: url, redis_port: port.parse::().unwrap(), redis_password: password, diff --git a/src/config/config_server.rs b/src/config/config_server.rs index 9adda45..7def155 100644 --- a/src/config/config_server.rs +++ b/src/config/config_server.rs @@ -1,4 +1,5 @@ use cached::proc_macro::cached; +use std::env; #[derive(Clone)] pub struct ConfigServer { @@ -9,18 +10,18 @@ pub struct ConfigServer { #[cached] pub fn get_config_server() -> ConfigServer { - dotenv::dotenv().ok(); + dotenvy::dotenv().ok(); - let host = option_env!("HOST").unwrap_or("localhost").to_string(); + let host = env::var("HOST").unwrap_or("localhost".to_string()); - let port = option_env!("PORT") - .unwrap_or("8500") + let port = env::var("PORT") + .unwrap_or("8500".to_string()) .parse::() .unwrap(); - let allowed_origins = match option_env!("ALLOWED_ORIGINS") { - Some(origins) => Some(origins.split(",").map(|s| s.to_string()).collect()), - None => None, + let allowed_origins = match env::var("ALLOWED_ORIGINS") { + Ok(origins) => Some(origins.split(',').map(|s| s.to_string()).collect()), + Err(_) => None, }; ConfigServer { diff --git a/src/handler/message.rs b/src/handler/message.rs index 0467309..e145823 100644 --- a/src/handler/message.rs +++ b/src/handler/message.rs @@ -8,10 +8,9 @@ pub async fn send_message( Extension(auth_service): Extension, Extension(email_service): Extension, Extension(author): Extension, - Json(payload): Json, + Json(mut payload): Json, ) -> impl IntoResponse { - let mut package = payload.clone(); - package.author = Some(author.clone()).clone(); + payload.author = Some(author.clone()).clone(); if auth_service.has_user_reached_limit(&author).await { return ( @@ -23,26 +22,14 @@ pub async fn send_message( ); } - match email_service.send_email_smtp(package).await { - Ok(_) => {} - Err(e) => { - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(GenericResponse { - status: StatusCode::INTERNAL_SERVER_ERROR.to_string(), - message: e.to_string(), - }), - ) - } - }; + email_service.send_email(payload).await; + auth_service.increase_user_request_count(&author).await; - auth_service.increase_user_request(&author).await; - - return ( + ( StatusCode::OK, Json(GenericResponse { status: StatusCode::OK.to_string(), message: "Message sent".to_string(), }), - ); + ) } diff --git a/src/main.rs b/src/main.rs index e545876..994fe1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,5 +20,6 @@ async fn main() { tokio::net::TcpListener::bind(format!("{}:{}", server_config.host, server_config.port)) .await .unwrap(); + axum::serve(listener, app).await.unwrap(); } diff --git a/src/model/send_message.rs b/src/model/send_message.rs index ff2a214..2b71bea 100644 --- a/src/model/send_message.rs +++ b/src/model/send_message.rs @@ -1,5 +1,5 @@ -use chrono::naive::serde::ts_seconds::deserialize as from_ts; -use chrono::NaiveDateTime; +use chrono::serde::ts_seconds::deserialize as from_ts; +use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; @@ -20,5 +20,5 @@ pub struct SendMessage { pub message: String, #[serde(deserialize_with = "from_ts")] - pub timestamp: NaiveDateTime, + pub timestamp: DateTime, } diff --git a/src/service/auth_service.rs b/src/service/auth_service.rs index 5efedc1..edf7b4b 100644 --- a/src/service/auth_service.rs +++ b/src/service/auth_service.rs @@ -58,7 +58,7 @@ impl AuthService { return user_requests >= self.max_requests; } - pub async fn increase_user_request(&self, user: &MessageAuthor) -> bool { + pub async fn increase_user_request_count(&self, user: &MessageAuthor) -> bool { let mut con = self.redis.get_async_connection().await.unwrap(); let current_request_key = format!( "user-message:{}:requests:{}", diff --git a/src/service/email_service.rs b/src/service/email_service.rs index e2eafa8..bda266f 100644 --- a/src/service/email_service.rs +++ b/src/service/email_service.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; use crate::config::config_email::ConfigEmail; use crate::model::send_message::SendMessage; use lettre::message::Mailbox; @@ -6,16 +7,22 @@ use lettre::{ Message, Tokio1Executor, }; + +type MessageQueue = deadqueue::unlimited::Queue; + + #[derive(Clone)] pub struct EmailService { name: String, email: String, mailer: AsyncSmtpTransport, + + message_queue: Arc } impl EmailService { pub fn new(config_email: ConfigEmail) -> Self { - EmailService { + let email_service = EmailService { name: config_email.smtp_name.clone(), email: config_email.smtp_email.clone(), mailer: AsyncSmtpTransport::::starttls_relay(&config_email.smtp_server) @@ -26,10 +33,48 @@ impl EmailService { )) .port(config_email.smtp_port) .build(), + message_queue: Arc::new(MessageQueue::new()) + }; + email_service.bind_executer(); + + email_service + } + + pub async fn send_email ( + &self, + m: SendMessage + ) { + self.message_queue.push(m); + } + + fn bind_executer(&self) { + let local_self = self.clone(); + let message_queue = self.message_queue.clone(); + tokio::spawn(async move { + loop { + let message = message_queue.pop().await; + local_self.create_send_message_task(message).await; + } + }); + } + + async fn create_send_message_task(&self, m: SendMessage) { + let message = self.message_queue.pop().await; + match self.send_message_smtp(message.clone()).await { + Ok(_) => { + println!( + "Email sent successfully from {} to {}", + message.author.unwrap().email, + self.email + ); + } + Err(e) => { + println!("Error sending email: {}", e); + } } } - pub async fn send_email_smtp(&self, m: SendMessage) -> Result<(), Box> { + async fn send_message_smtp(&self, m: SendMessage) -> Result<(), Box> { let sender = m.author.clone().unwrap(); let sender_mailbox = Mailbox::new(Some(sender.name), sender.email.parse::
().unwrap()); diff --git a/src/utils/router_builder.rs b/src/utils/router_builder.rs index 8699171..9afccef 100644 --- a/src/utils/router_builder.rs +++ b/src/utils/router_builder.rs @@ -1,6 +1,6 @@ use axum::Router; use http::Method; -use tower_http::cors::{AllowOrigin, CorsLayer}; +use tower_http::cors::{AllowHeaders, AllowOrigin, CorsLayer}; pub struct RouterBuilder { router: Router, @@ -18,12 +18,19 @@ impl RouterBuilder { return self; } - pub fn add_cors(&mut self, allowed_origins: Option>) -> &mut Self { + pub fn add_cors(&mut self, origins: Option>) -> &mut Self { + let allowed_origins = origins.map_or(AllowOrigin::any(), |origins| { + AllowOrigin::list(origins.iter().map(|s| s.parse().unwrap())) + }); + let allowed_headers = [ + "content-type".parse().unwrap(), + "authorization".parse().unwrap(), + ]; + let cors = CorsLayer::new() .allow_methods([Method::GET, Method::POST, Method::OPTIONS]) - .allow_origin(allowed_origins.map_or(AllowOrigin::any(), |origins| { - AllowOrigin::list(origins.iter().map(|s| s.parse().unwrap())) - })); + .allow_headers(allowed_headers) + .allow_origin(allowed_origins); self.router = self.router.clone().layer(cors); return self;