From cf08196a52db9b3ec9e69a33106e76d53660232e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 00:59:11 +0000 Subject: [PATCH 1/8] build(deps): bump testcontainers-modules from 0.3.6 to 0.3.7 Bumps [testcontainers-modules](https://github.com/testcontainers/testcontainers-rs-modules-community) from 0.3.6 to 0.3.7. - [Release notes](https://github.com/testcontainers/testcontainers-rs-modules-community/releases) - [Changelog](https://github.com/testcontainers/testcontainers-rs-modules-community/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-rs-modules-community/compare/v0.3.6...v0.3.7) --- updated-dependencies: - dependency-name: testcontainers-modules dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/adapter/Cargo.toml | 2 +- src/public/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 029fdb2..94ece91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2079,9 +2079,9 @@ dependencies = [ [[package]] name = "testcontainers-modules" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "204d1c7516bfdc8a01bb85d3e30145e5bbeb2351812e5e8aa6971769109b45b5" +checksum = "8debb5e215d9e89ea93255fffff00bf037ea44075d7a2669a21a8a988d6b52fd" dependencies = [ "testcontainers", ] diff --git a/src/adapter/Cargo.toml b/src/adapter/Cargo.toml index 73171b8..dc46297 100644 --- a/src/adapter/Cargo.toml +++ b/src/adapter/Cargo.toml @@ -37,7 +37,7 @@ version = "1.0" features = ["derive"] [dependencies.testcontainers-modules] -version = "0.3.4" +version = "0.3.7" features = ["postgres"] [dependencies.tokio] diff --git a/src/public/Cargo.toml b/src/public/Cargo.toml index 97f5ab4..161768a 100644 --- a/src/public/Cargo.toml +++ b/src/public/Cargo.toml @@ -100,7 +100,7 @@ version = "1.0" features = ["derive"] [dependencies.testcontainers-modules] -version = "0.3.5" +version = "0.3.7" features = ["postgres"] [dependencies.tokio] From 4d4d49a0fe153cbd7c35e61b8808a158789085d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 00:58:56 +0000 Subject: [PATCH 2/8] build(deps): bump warp from 0.3.6 to 0.3.7 Bumps [warp](https://github.com/seanmonstar/warp) from 0.3.6 to 0.3.7. - [Release notes](https://github.com/seanmonstar/warp/releases) - [Changelog](https://github.com/seanmonstar/warp/blob/master/CHANGELOG.md) - [Commits](https://github.com/seanmonstar/warp/compare/v0.3.6...v0.3.7) --- updated-dependencies: - dependency-name: warp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 58 +++++++++++++++++++++---------------------- src/public/Cargo.toml | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94ece91..907859b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,7 +160,7 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http", + "http 0.2.12", "http-body", "hyper", "itoa", @@ -186,7 +186,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", + "http 0.2.12", "http-body", "mime", "rustversion", @@ -870,7 +870,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.2.6", "slab", "tokio", @@ -905,7 +905,7 @@ dependencies = [ "base64", "bytes", "headers-core", - "http", + "http 0.2.12", "httpdate", "mime", "sha1", @@ -917,7 +917,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" dependencies = [ - "http", + "http 0.2.12", ] [[package]] @@ -973,6 +973,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -980,7 +991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", "pin-project-lite", ] @@ -1007,7 +1018,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", + "http 0.2.12", "http-body", "httparse", "httpdate", @@ -1236,7 +1247,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 0.2.12", "httparse", "log", "memchr", @@ -1372,7 +1383,7 @@ checksum = "1a016b8d9495c639af2145ac22387dcb88e44118e45320d9238fbf4e7889abcb" dependencies = [ "async-trait", "futures-core", - "http", + "http 0.2.12", "opentelemetry", "opentelemetry-proto", "opentelemetry-semantic-conventions", @@ -1824,15 +1835,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64", -] - [[package]] name = "rustversion" version = "1.0.14" @@ -2224,9 +2226,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", "log", @@ -2319,7 +2321,7 @@ dependencies = [ "base64", "bytes", "h2", - "http", + "http 0.2.12", "http-body", "hyper", "hyper-timeout", @@ -2496,14 +2498,14 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ "byteorder", "bytes", "data-encoding", - "http", + "http 1.1.0", "httparse", "log", "rand", @@ -2631,15 +2633,15 @@ dependencies = [ [[package]] name = "warp" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e92e22e03ff1230c03a1a8ee37d2f89cd489e2e541b7550d6afad96faed169" +checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" dependencies = [ "bytes", "futures-channel", "futures-util", "headers", - "http", + "http 0.2.12", "hyper", "log", "mime", @@ -2647,13 +2649,11 @@ dependencies = [ "multer", "percent-encoding", "pin-project", - "rustls-pemfile", "scoped-tls", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-stream", "tokio-tungstenite", "tokio-util", "tower-service", diff --git a/src/public/Cargo.toml b/src/public/Cargo.toml index 161768a..bc2d086 100644 --- a/src/public/Cargo.toml +++ b/src/public/Cargo.toml @@ -75,7 +75,7 @@ version = "1.0" version = "0.1" [dependencies.warp] -version = "0.3.6" +version = "0.3.7" [dependencies.clap] version = "4.4.7" From c506a048400be360a49e1c4d80c62d1e4a2917c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 00:58:43 +0000 Subject: [PATCH 3/8] build(deps): bump prost from 0.12.3 to 0.12.4 Bumps [prost](https://github.com/tokio-rs/prost) from 0.12.3 to 0.12.4. - [Release notes](https://github.com/tokio-rs/prost/releases) - [Commits](https://github.com/tokio-rs/prost/compare/v0.12.3...v0.12.4) --- updated-dependencies: - dependency-name: prost dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- src/common/Cargo.toml | 2 +- src/gpt_answer_server/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 907859b..ef38dfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1629,9 +1629,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" dependencies = [ "bytes", "prost-derive", @@ -1661,9 +1661,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" dependencies = [ "anyhow", "itertools", diff --git a/src/common/Cargo.toml b/src/common/Cargo.toml index 4e8982e..e6957fa 100644 --- a/src/common/Cargo.toml +++ b/src/common/Cargo.toml @@ -52,7 +52,7 @@ features = ["env-filter"] version = "0.11.0" [dependencies.prost] -version = "0.12.3" +version = "0.12.4" [build-dependencies.tonic-build] version = "0.11.0" diff --git a/src/gpt_answer_server/Cargo.toml b/src/gpt_answer_server/Cargo.toml index f4f8e6a..6ad94b1 100644 --- a/src/gpt_answer_server/Cargo.toml +++ b/src/gpt_answer_server/Cargo.toml @@ -22,7 +22,7 @@ path = "../common" version = "0.11.0" [dependencies.prost] -version = "0.12.3" +version = "0.12.4" [dependencies.serde] version = "1.0" From 883152bf59e91fe6f24942035265462aa7d081d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 00:27:44 +0000 Subject: [PATCH 4/8] build(deps): bump async-trait from 0.1.79 to 0.1.80 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.79 to 0.1.80. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.79...0.1.80) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/adapter/Cargo.toml | 2 +- src/core/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef38dfd..f425ac4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", diff --git a/src/adapter/Cargo.toml b/src/adapter/Cargo.toml index dc46297..e37c201 100644 --- a/src/adapter/Cargo.toml +++ b/src/adapter/Cargo.toml @@ -22,7 +22,7 @@ path = "../common" version = "2.1.0" [dependencies.async-trait] -version = "0.1.77" +version = "0.1.80" [dependencies.deadpool-diesel] version = "0.6.0" diff --git a/src/core/Cargo.toml b/src/core/Cargo.toml index 61da5a9..6b225fb 100644 --- a/src/core/Cargo.toml +++ b/src/core/Cargo.toml @@ -13,7 +13,7 @@ autotests = true autobenches = true [dependencies.async-trait] -version = "0.1.77" +version = "0.1.80" [dependencies.serde] version = "1.0" From fca0c2df86bc1eeca615007c76b1b3c1ad433387 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 00:48:20 +0000 Subject: [PATCH 5/8] build(deps): bump anyhow from 1.0.81 to 1.0.82 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.81 to 1.0.82. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.81...1.0.82) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- src/adapter/Cargo.toml | 2 +- src/core/Cargo.toml | 2 +- src/public/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f425ac4..9c9637d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-stream" diff --git a/src/adapter/Cargo.toml b/src/adapter/Cargo.toml index e37c201..b97620a 100644 --- a/src/adapter/Cargo.toml +++ b/src/adapter/Cargo.toml @@ -45,7 +45,7 @@ version = "1.36.0" features = ["full"] [dependencies.anyhow] -version = "1.0.80" +version = "1.0.82" [dependencies.tonic] version = "0.11.0" diff --git a/src/core/Cargo.toml b/src/core/Cargo.toml index 6b225fb..04b6d46 100644 --- a/src/core/Cargo.toml +++ b/src/core/Cargo.toml @@ -23,4 +23,4 @@ features = ["derive"] version = "1.0.57" [dependencies.anyhow] -version = "1.0.80" +version = "1.0.82" diff --git a/src/public/Cargo.toml b/src/public/Cargo.toml index bc2d086..0b07a62 100644 --- a/src/public/Cargo.toml +++ b/src/public/Cargo.toml @@ -111,7 +111,7 @@ features = ["full"] version = "1.0.57" [dependencies.anyhow] -version = "1.0.80" +version = "1.0.82" [lib] path = "src/lib.rs" From b57e8624574de8af43f2e2615319b6883f9d6018 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 00:44:20 +0000 Subject: [PATCH 6/8] build(deps): bump serde from 1.0.197 to 1.0.198 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.197 to 1.0.198. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.197...v1.0.198) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c9637d..a149b5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1861,18 +1861,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", From 4e7d27fe4f5022b4376e32d7496ef2623842e9be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 00:44:10 +0000 Subject: [PATCH 7/8] build(deps): bump serde_json from 1.0.115 to 1.0.116 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.115 to 1.0.116. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.115...v1.0.116) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a149b5a..54fdc54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1881,9 +1881,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", From af498b1d3518b49a2b1d7a4c63e9568fbd0a1a67 Mon Sep 17 00:00:00 2001 From: thuan2172001 Date: Sat, 6 Apr 2024 11:17:36 +0700 Subject: [PATCH 8/8] feat: cache port --- Cargo.lock | 19 +++ src/adapter/Cargo.toml | 3 + .../src/repositories/in_memory/cache.rs | 109 ++++++++++++++++++ src/adapter/src/repositories/in_memory/mod.rs | 1 + src/adapter/src/repositories/mod.rs | 1 + src/adapter/src/repositories/redis/cache.rs | 104 +++++++++++++++++ src/adapter/src/repositories/redis/mod.rs | 1 + src/core/src/ports/cache.rs | 49 ++++++++ src/core/src/ports/mod.rs | 1 + src/gpt_answer_server/Cargo.toml | 3 + .../src/controllers/gpt_answer.rs | 27 +++-- src/gpt_answer_server/src/main.rs | 10 +- src/gpt_answer_server/src/options.rs | 9 ++ 13 files changed, 328 insertions(+), 9 deletions(-) create mode 100644 src/adapter/src/repositories/in_memory/cache.rs create mode 100644 src/adapter/src/repositories/redis/cache.rs create mode 100644 src/adapter/src/repositories/redis/mod.rs create mode 100644 src/core/src/ports/cache.rs diff --git a/Cargo.lock b/Cargo.lock index 54fdc54..c79f31d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,7 @@ dependencies = [ "deadpool-diesel", "diesel", "diesel_migrations", + "redis-async", "rust_core", "serde", "testcontainers-modules", @@ -845,6 +846,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" name = "gpt_answer_server" version = "0.0.1" dependencies = [ + "adapter", "clap", "common", "opentelemetry", @@ -1731,6 +1733,23 @@ dependencies = [ "syn 2.0.57", ] +[[package]] +name = "redis-async" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48732d38d64794df698e1f6410d1650088ee9bf7cea405fbb0adb24189217a8f" +dependencies = [ + "bytes", + "futures-channel", + "futures-sink", + "futures-util", + "log", + "pin-project", + "socket2", + "tokio", + "tokio-util", +] + [[package]] name = "redox_syscall" version = "0.4.1" diff --git a/src/adapter/Cargo.toml b/src/adapter/Cargo.toml index b97620a..a492a2a 100644 --- a/src/adapter/Cargo.toml +++ b/src/adapter/Cargo.toml @@ -49,3 +49,6 @@ version = "1.0.82" [dependencies.tonic] version = "0.11.0" + +[dependencies.redis-async] +version = "0.17.1" diff --git a/src/adapter/src/repositories/in_memory/cache.rs b/src/adapter/src/repositories/in_memory/cache.rs new file mode 100644 index 0000000..0aca64b --- /dev/null +++ b/src/adapter/src/repositories/in_memory/cache.rs @@ -0,0 +1,109 @@ +use std::{ + collections::HashMap, + sync::Arc, + time::{Duration, SystemTime}, +}; + +use async_trait::async_trait; +use tokio::sync::RwLock; + +use rust_core::common::errors::CoreError; +use rust_core::ports::cache::CachePort; + +/// Represents an in-memory cache implementation. +pub struct InMemoryCache { + cache: Arc)>>>, +} + +impl InMemoryCache { + /// Creates a new empty in-memory cache. + pub fn new() -> Self { + Self { + cache: Arc::new(RwLock::new(HashMap::new())), + } + } + + /// Removes expired entries from the cache asynchronously. + /// + /// This method is used to remove any expired cache entries based on their expiration time. + /// + /// # Returns + /// + /// Returns `Ok(())` if the cleanup is successful, otherwise returns a `CoreError`. + async fn cleanup_expired_entries(&self) -> Result<(), CoreError> { + let mut cache = self.cache.write().await; + let now = SystemTime::now(); + cache.retain(|_, (_, expiry_time, _)| *expiry_time > now); + Ok(()) + } +} + +#[async_trait] +impl CachePort for InMemoryCache { + /// Retrieves a value from the cache based on the provided key. + /// + /// # Arguments + /// + /// * `key`: A string representing the key to retrieve from the cache. + /// + /// # Returns + /// + /// Returns a `Result` containing `Some(value)` if the key is found and not expired, + /// or `None` if the key is not found or expired. Returns a `CoreError` on failure. + async fn get(&self, key: &str) -> Result, CoreError> { + let cache = self.cache.read().await; + Ok(cache + .get(key) + .filter(|(_, expiry_time, _)| *expiry_time > SystemTime::now()) + .map(|(value, _, _)| value.clone())) + } + + /// Sets a key-value pair in the cache with an optional expiration duration. + /// + /// # Arguments + /// + /// * `key`: A string representing the key to set in the cache. + /// * `value`: A string representing the value to associate with the key. + /// * `expiration`: An optional `Duration` specifying the expiration time for the key-value pair. + /// + /// # Returns + /// + /// Returns `Ok(())` if the set operation is successful, otherwise returns a `CoreError`. + async fn set( + &mut self, + key: String, + value: String, + expiration: Option, + ) -> Result { + self.cleanup_expired_entries().await?; + let expiry_time = expiration.map(|exp| SystemTime::now() + exp); + let mut cache = self.cache.write().await; + cache.insert( + key, + ( + value, + expiry_time.unwrap_or_else(|| SystemTime::UNIX_EPOCH), + expiration, + ), + ); + Ok(true) + } + + /// Removes a key-value pair from the cache based on the provided key. + /// + /// # Arguments + /// + /// * `key`: A string representing the key to remove from the cache. + /// + /// # Returns + /// + /// Returns `Ok(())` if the key is found and removed, otherwise returns a `CoreError`. + async fn remove(&mut self, key: &str) -> Result { + let mut cache = self.cache.write().await; + if cache.remove(key).is_some() { + Ok(true) + } else { + Err(CoreError::NotFound) + } + } +} diff --git a/src/adapter/src/repositories/in_memory/mod.rs b/src/adapter/src/repositories/in_memory/mod.rs index b44264d..5f6965d 100644 --- a/src/adapter/src/repositories/in_memory/mod.rs +++ b/src/adapter/src/repositories/in_memory/mod.rs @@ -1 +1,2 @@ +pub mod cache; pub mod question; diff --git a/src/adapter/src/repositories/mod.rs b/src/adapter/src/repositories/mod.rs index 5da5a18..f946f94 100644 --- a/src/adapter/src/repositories/mod.rs +++ b/src/adapter/src/repositories/mod.rs @@ -1,4 +1,5 @@ pub mod grpc; pub mod in_memory; pub mod postgres; +pub mod redis; pub mod repository_test; diff --git a/src/adapter/src/repositories/redis/cache.rs b/src/adapter/src/repositories/redis/cache.rs new file mode 100644 index 0000000..2f77bfe --- /dev/null +++ b/src/adapter/src/repositories/redis/cache.rs @@ -0,0 +1,104 @@ +use async_trait::async_trait; +use redis_async::{client, resp::RespValue, resp_array}; + +use rust_core::{common::errors::CoreError, ports::cache::CachePort}; + +use std::time::Duration; + +/// Represents a Redis cache implementation. +pub struct RedisCache { + client: client::PairedConnection, +} + +impl RedisCache { + /// Creates a new Redis cache instance. + /// + /// # Arguments + /// + /// * `redis_host`: Hostname or IP address of the Redis server. + /// * `redis_port`: Port number of the Redis server. + /// + /// # Returns + /// + /// Returns a `Result` containing the initialized `RedisCache` instance. + pub async fn new(redis_host: &str, redis_port: u16) -> Result { + let client = client::paired_connect(redis_host, redis_port) + .await + .map_err(|err| CoreError::InternalError(err.into()))?; + Ok(Self { client }) + } +} + +#[async_trait] +impl CachePort for RedisCache { + /// Retrieves a value from the Redis cache. + /// + /// # Arguments + /// + /// * `key`: The key of the value to retrieve. + /// + /// # Returns + /// + /// Returns a `Result` containing the value associated with the key if found, or `None`. + async fn get(&self, key: &str) -> Result, CoreError> { + let result: Result = self.client.send(resp_array!["GET", key]).await; + match result { + Ok(RespValue::BulkString(data)) => Ok(Some(String::from_utf8_lossy(&data).to_string())), + _ => Ok(None), + } + } + + /// Sets a key-value pair in the Redis cache with an optional expiration time. + /// + /// # Arguments + /// + /// * `key`: The key to set. + /// * `value`: The value to associate with the key. + /// * `expiration`: Optional expiration duration for the key-value pair. + /// + /// # Returns + /// + /// Returns a `Result` indicating success (`true`) or failure (`false`). + async fn set( + &mut self, + key: String, + value: String, + expiration: Option, + ) -> Result { + let mut args = vec!["SET", &key, &value]; + + let exp_secs = if let Some(exp) = expiration { + args.push("EX"); + Some(exp.as_secs().to_string()) + } else { + None + }; + + if let Some(ref secs) = exp_secs { + args.push(secs); + } + + let result: Result = self.client.send(resp_array![].append(args)).await; + match result { + Ok(RespValue::SimpleString(s)) if s == "OK" => Ok(true), + _ => Ok(false), + } + } + + /// Removes a key-value pair from the Redis cache. + /// + /// # Arguments + /// + /// * `key`: The key to remove. + /// + /// # Returns + /// + /// Returns a `Result` indicating success (`true`) or failure (`false`). + async fn remove(&mut self, key: &str) -> Result { + let result: Result = self.client.send(resp_array!["DEL", key]).await; + match result { + Ok(RespValue::Integer(1)) => Ok(true), + _ => Ok(false), + } + } +} diff --git a/src/adapter/src/repositories/redis/mod.rs b/src/adapter/src/repositories/redis/mod.rs new file mode 100644 index 0000000..a5c08fd --- /dev/null +++ b/src/adapter/src/repositories/redis/mod.rs @@ -0,0 +1 @@ +pub mod cache; diff --git a/src/core/src/ports/cache.rs b/src/core/src/ports/cache.rs new file mode 100644 index 0000000..a2a21c4 --- /dev/null +++ b/src/core/src/ports/cache.rs @@ -0,0 +1,49 @@ +use async_trait::async_trait; + +use std::time::Duration; + +use crate::common::errors::CoreError; + +/// Represents a cache port for storing key-value pairs. +#[async_trait] +pub trait CachePort { + /// Retrieves a value from the cache based on the given key. + /// + /// # Arguments + /// + /// * `key`: The key to look up in the cache. + /// + /// # Returns + /// + /// Returns an optional value associated with the key, or `None` if the key is not present in the cache. + async fn get(&self, key: &str) -> Result, CoreError>; + + /// Sets a key-value pair in the cache with an optional expiration duration. + /// + /// # Arguments + /// + /// * `key`: The key to set in the cache. + /// * `value`: The value to associate with the key. + /// * `expiration`: Optional expiration duration for the key-value pair. + /// + /// # Returns + /// + /// Returns `true` if the key-value pair is successfully set in the cache, `false` otherwise. + async fn set( + &mut self, + key: String, + value: String, + expiration: Option, + ) -> Result; + + /// Removes a key-value pair from the cache based on the given key. + /// + /// # Arguments + /// + /// * `key`: The key to remove from the cache. + /// + /// # Returns + /// + /// Returns `true` if the key-value pair is successfully removed from the cache, `false` otherwise. + async fn remove(&mut self, key: &str) -> Result; +} diff --git a/src/core/src/ports/mod.rs b/src/core/src/ports/mod.rs index d2e9d02..14ce930 100644 --- a/src/core/src/ports/mod.rs +++ b/src/core/src/ports/mod.rs @@ -1,2 +1,3 @@ +pub mod cache; pub mod gpt_answer; pub mod question; diff --git a/src/gpt_answer_server/Cargo.toml b/src/gpt_answer_server/Cargo.toml index 6ad94b1..d34192a 100644 --- a/src/gpt_answer_server/Cargo.toml +++ b/src/gpt_answer_server/Cargo.toml @@ -18,6 +18,9 @@ path = "../core" [dependencies.common] path = "../common" +[dependencies.adapter] +path = "../adapter" + [dependencies.tonic] version = "0.11.0" diff --git a/src/gpt_answer_server/src/controllers/gpt_answer.rs b/src/gpt_answer_server/src/controllers/gpt_answer.rs index 2263d69..0c26401 100644 --- a/src/gpt_answer_server/src/controllers/gpt_answer.rs +++ b/src/gpt_answer_server/src/controllers/gpt_answer.rs @@ -1,22 +1,24 @@ +use std::sync::Arc; + use tonic::{Request, Response, Status}; use common::grpc::gpt_answer::gpt_answer::{ gpt_answer_service_server::GptAnswerService, GetAnswerPayload, GetAnswerResponse, }; +use rust_core::ports::cache::CachePort; /// Implementation of the gRPC service for generating answers to questions. /// /// This struct represents the gRPC server implementation for answering questions. It implements /// the `GptAnswerService` trait generated by Tonic, which defines the RPC methods for answering /// questions. -#[derive(Debug, Default)] pub struct GptAnswerServiceImpl { - pub dummy_prop: String, + pub cache: Arc, } impl GptAnswerServiceImpl { - pub fn new(dummy_prop: String) -> Self { - Self { dummy_prop } + pub fn new(cache: Arc) -> Self { + Self { cache } } } @@ -44,12 +46,21 @@ impl GptAnswerService for GptAnswerServiceImpl { // Extract the payload containing the question from the request let payload = request.into_inner(); - // TODO: Implement your logic to generate an answer based on the question. - // Placeholder logic: Generate an answer string - let answer = format!("Answer to: {}, {}", payload.question, self.dummy_prop); + let mut answer = + self.cache.get(&payload.question).await.map_err(|err| { + Status::internal(format!("Failed to get answer from cache: {}", err)) + })?; + + if answer.is_none() { + // TODO: Implement your logic to generate an answer based on the question. + // Placeholder logic: Generate an answer string + answer = Some(format!("Answer to: {}", payload.question)); + } // Construct a response containing the generated answer - let response = GetAnswerResponse { answer }; + let response = GetAnswerResponse { + answer: answer.unwrap(), + }; // Return the response Ok(Response::new(response)) diff --git a/src/gpt_answer_server/src/main.rs b/src/gpt_answer_server/src/main.rs index 7f6034b..da6cde7 100644 --- a/src/gpt_answer_server/src/main.rs +++ b/src/gpt_answer_server/src/main.rs @@ -1,7 +1,10 @@ +use std::sync::Arc; + use clap::{Parser, Subcommand}; use opentelemetry::global; use tonic::transport::Server; +use adapter::repositories::redis::cache::RedisCache; use common::grpc::gpt_answer::gpt_answer::gpt_answer_service_server::GptAnswerServiceServer; use common::loggers::telemetry::init_telemetry; use common::options::parse_options; @@ -12,7 +15,12 @@ pub async fn serve(options: Options) { let address = options.server_endpoint.parse().unwrap(); println!("Starting GPT Answer server at {}", options.server_endpoint); - let gpt_answer_service = GptAnswerServiceImpl::new("dummy_prop".to_string()); + let cache = RedisCache::new(&options.redis.host, options.redis.port) + .await + .unwrap(); + + let gpt_answer_service = GptAnswerServiceImpl::new(Arc::new(cache)); + Server::builder() .add_service(GptAnswerServiceServer::new(gpt_answer_service)) .serve(address) diff --git a/src/gpt_answer_server/src/options.rs b/src/gpt_answer_server/src/options.rs index f32eb2b..ceb9c17 100644 --- a/src/gpt_answer_server/src/options.rs +++ b/src/gpt_answer_server/src/options.rs @@ -15,7 +15,16 @@ pub struct Options { pub exporter_endpoint: String, /// The name of the service. pub service_name: String, + /// Configuration for redis. + pub redis: RedisConfig, /// Configuration for logging, including log level. #[serde(default = "default_log")] pub log: Log, } + +/// Represents redis configuration. +#[derive(Debug, Deserialize, Clone)] +pub struct RedisConfig { + pub host: String, + pub port: u16, +}