From fb3aab7cb640bc1b6117071fdf738025b6cceb5a Mon Sep 17 00:00:00 2001 From: thuan2172001 Date: Thu, 28 Mar 2024 23:01:06 +0700 Subject: [PATCH] fix: structure --- Cargo.lock | 19 ++----- Cargo.toml | 2 +- src/adapter/Cargo.toml | 8 +-- src/adapter/src/repositories/grpc/config.rs | 15 ------ src/adapter/src/repositories/grpc/mod.rs | 1 - .../repositories/grpc/models/gpt_answer.rs | 18 ++++--- .../repositories/postgres/models/question.rs | 9 ++-- .../src/repositories/postgres/question_db.rs | 18 +++---- src/common/Cargo.toml | 11 ++++ src/{grpc => common}/build.rs | 0 src/{grpc => common}/proto/gpt_answer.proto | 0 .../src/grpc}/gpt_answer.rs | 0 .../src/interfaces => common/src/grpc}/mod.rs | 0 src/common/src/lib.rs | 1 + src/core/Cargo.toml | 2 +- src/core/src/common/errors.rs | 9 +++- .../Cargo.toml | 7 +-- .../build.rs | 0 .../config/00-default.toml | 4 +- .../src/controllers/gpt_answer.rs | 23 ++++++++ .../src/controllers/mod.rs | 0 .../src/lib.rs | 0 .../src/main.rs | 23 ++++++-- .../src/options.rs | 21 ++------ src/grpc/Cargo.toml | 38 -------------- src/grpc/src/lib.rs | 1 - src/grpc_server/src/controllers/gpt_answer.rs | 52 ------------------- src/public/Cargo.toml | 3 -- src/public/config/00-default.toml | 5 +- src/public/src/controllers/question.rs | 40 +++++++------- src/public/src/errors.rs | 3 +- src/public/src/main.rs | 13 +++-- src/public/src/options.rs | 20 +++---- src/public/src/router.rs | 11 ++-- src/public/tests/questions_router_test.rs | 11 ++-- 35 files changed, 151 insertions(+), 237 deletions(-) delete mode 100644 src/adapter/src/repositories/grpc/config.rs rename src/{grpc => common}/build.rs (100%) rename src/{grpc => common}/proto/gpt_answer.proto (100%) rename src/{grpc/src/interfaces => common/src/grpc}/gpt_answer.rs (100%) rename src/{grpc/src/interfaces => common/src/grpc}/mod.rs (100%) rename src/{grpc_server => gpt_answer_service}/Cargo.toml (90%) rename src/{grpc_server => gpt_answer_service}/build.rs (100%) rename src/{grpc_server => gpt_answer_service}/config/00-default.toml (60%) create mode 100644 src/gpt_answer_service/src/controllers/gpt_answer.rs rename src/{grpc_server => gpt_answer_service}/src/controllers/mod.rs (100%) rename src/{grpc_server => gpt_answer_service}/src/lib.rs (100%) rename src/{grpc_server => gpt_answer_service}/src/main.rs (64%) rename src/{grpc_server => gpt_answer_service}/src/options.rs (59%) delete mode 100644 src/grpc/Cargo.toml delete mode 100644 src/grpc/src/lib.rs delete mode 100644 src/grpc_server/src/controllers/gpt_answer.rs diff --git a/Cargo.lock b/Cargo.lock index 41b2555..94d7717 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,10 +8,10 @@ version = "0.0.1" dependencies = [ "anyhow", "async-trait", + "common", "deadpool-diesel", "diesel", "diesel_migrations", - "grpc_interface", "rust_core", "serde", "testcontainers-modules", @@ -330,7 +330,6 @@ dependencies = [ "deadpool-diesel", "diesel", "diesel_migrations", - "grpc_interface", "openssl", "opentelemetry", "rand", @@ -361,7 +360,10 @@ dependencies = [ "opentelemetry-otlp", "opentelemetry-semantic-conventions", "opentelemetry_sdk", + "prost", "serde", + "tonic", + "tonic-build", "tracing", "tracing-bunyan-formatter", "tracing-opentelemetry", @@ -821,22 +823,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] -name = "grpc_interface" -version = "0.0.1" -dependencies = [ - "glob", - "prost", - "tonic", - "tonic-build", -] - -[[package]] -name = "grpc_server" +name = "gpt_answer_service" version = "0.0.1" dependencies = [ "clap", "common", - "grpc_interface", "opentelemetry", "prost", "readonly", diff --git a/Cargo.toml b/Cargo.toml index 25646c6..0064c08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = ["src/public", "src/grpc_server"] +members = ["src/public", "src/gpt_answer_service"] resolver = "2" diff --git a/src/adapter/Cargo.toml b/src/adapter/Cargo.toml index d04f690..0db1706 100644 --- a/src/adapter/Cargo.toml +++ b/src/adapter/Cargo.toml @@ -29,6 +29,9 @@ features = ["postgres", "postgres_backend", "uuid"] [dependencies.rust_core] path = "../core" +[dependencies.common] +path = "../common" + [dependencies.serde] version = "1.0" features = ["derive"] @@ -45,7 +48,4 @@ features = ["full"] version = "1.0.80" [dependencies.tonic] -version = "0.11.0" - -[dependencies.grpc_interface] -path = "../grpc" +version = "0.11.0" \ No newline at end of file diff --git a/src/adapter/src/repositories/grpc/config.rs b/src/adapter/src/repositories/grpc/config.rs deleted file mode 100644 index c078b18..0000000 --- a/src/adapter/src/repositories/grpc/config.rs +++ /dev/null @@ -1,15 +0,0 @@ -use serde::Deserialize; - -/// Represents servers configuration options. -#[derive(Deserialize, Debug)] -pub struct GrpcServers { - /// Configuration for using in-memory database. - pub gpt_answer_service: Option, -} - -/// Represents service server configuration. -#[derive(Debug, Deserialize, Clone)] -pub struct ServiceServer { - /// URL for the server. - pub url: String, -} diff --git a/src/adapter/src/repositories/grpc/mod.rs b/src/adapter/src/repositories/grpc/mod.rs index b6a44ac..c446ac8 100644 --- a/src/adapter/src/repositories/grpc/mod.rs +++ b/src/adapter/src/repositories/grpc/mod.rs @@ -1,2 +1 @@ -pub mod config; pub mod models; diff --git a/src/adapter/src/repositories/grpc/models/gpt_answer.rs b/src/adapter/src/repositories/grpc/models/gpt_answer.rs index 4e42922..467cdc7 100644 --- a/src/adapter/src/repositories/grpc/models/gpt_answer.rs +++ b/src/adapter/src/repositories/grpc/models/gpt_answer.rs @@ -1,9 +1,9 @@ -use rust_core::common::errors::CoreError; use tonic::transport::Channel; -use grpc_interface::interfaces::gpt_answer::gpt_answer::{ +use common::grpc::gpt_answer::gpt_answer::{ gpt_answer_service_client::GptAnswerServiceClient, GetAnswerPayload, }; +use rust_core::common::errors::CoreError; pub struct GptAnswerGrpcClient { client: GptAnswerServiceClient, @@ -15,11 +15,13 @@ impl GptAnswerGrpcClient { Self { client } } - pub async fn get_instance(uri: &'static str) -> Result { - let channel = Channel::from_static(uri).connect().await.map_err(|err| { - eprintln!("Error connecting to GPT: {:?}", err); - CoreError::InternalError - })?; + pub async fn connect(uri: &'static str) -> Result { + let channel: Channel = match Channel::from_static(uri).connect().await { + Ok(channel) => channel, + Err(err) => { + return Err(CoreError::InternalError(err.into())); + } + }; let client = Self::new(channel); Ok(client) @@ -32,7 +34,7 @@ impl GptAnswerGrpcClient { let response = self.client.get_answer(request).await.map_err(|err| { eprintln!("Error getting answer from GPT: {:?}", err); - CoreError::InternalError + CoreError::InternalError(err.into()) })?; Ok(response.into_inner().answer) diff --git a/src/adapter/src/repositories/postgres/models/question.rs b/src/adapter/src/repositories/postgres/models/question.rs index 93e804c..ad2aa18 100644 --- a/src/adapter/src/repositories/postgres/models/question.rs +++ b/src/adapter/src/repositories/postgres/models/question.rs @@ -1,12 +1,11 @@ -use std::{ - io::{Error, ErrorKind}, - time::SystemTime, -}; +use std::io::{Error, ErrorKind}; +use std::time::SystemTime; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; -use rust_core::entities::question::{QuestionEntity, QuestionId}; use serde::Serialize; +use rust_core::entities::question::{QuestionEntity, QuestionId}; + #[derive(Debug, Queryable, Serialize, Selectable, Insertable, AsChangeset, Identifiable)] #[diesel(table_name = super::super::schema::questions)] #[cfg_attr(feature = "postgres", derive(diesel::pg::Pg))] diff --git a/src/adapter/src/repositories/postgres/question_db.rs b/src/adapter/src/repositories/postgres/question_db.rs index 9b3b40d..9627a7a 100644 --- a/src/adapter/src/repositories/postgres/question_db.rs +++ b/src/adapter/src/repositories/postgres/question_db.rs @@ -37,14 +37,14 @@ impl QuestionPort for QuestionDBRepository { .await .unwrap() .interact(move |conn| { - let question = - QuestionModel::try_from(question).map_err(|_| CoreError::InternalError)?; + let question = QuestionModel::try_from(question) + .map_err(|err| CoreError::InternalError(err.into()))?; let response = insert_into(questions) .values(&question) .get_result::(conn) .map_err(|err| match err { diesel::result::Error::NotFound => CoreError::NotFound, - _ => CoreError::InternalError, + _ => CoreError::InternalError(err.into()), }) .unwrap(); Ok(response.into()) @@ -59,14 +59,14 @@ impl QuestionPort for QuestionDBRepository { .await .unwrap() .interact(move |conn| { - let question = - QuestionModel::try_from(question).map_err(|_| CoreError::InternalError)?; + let question = QuestionModel::try_from(question) + .map_err(|err| CoreError::InternalError(err.into()))?; let response = update(questions.filter(id.eq(question.id))) .set(&question) .get_result::(conn) .map_err(|err| match err { diesel::result::Error::NotFound => CoreError::NotFound, - _ => CoreError::InternalError, + _ => CoreError::InternalError(err.into()), })? .into(); @@ -87,7 +87,7 @@ impl QuestionPort for QuestionDBRepository { .execute(conn) .map_err(|err| match err { diesel::result::Error::NotFound => CoreError::NotFound, - _ => CoreError::InternalError, + _ => CoreError::InternalError(err.into()), })?; Ok(()) @@ -109,7 +109,7 @@ impl QuestionPort for QuestionDBRepository { .first(conn) .map_err(|err| match err { diesel::result::Error::NotFound => CoreError::NotFound, - _ => CoreError::InternalError, + _ => CoreError::InternalError(err.into()), })? .into(); @@ -133,7 +133,7 @@ impl QuestionPort for QuestionDBRepository { .load(conn) .map_err(|err| match err { diesel::result::Error::NotFound => CoreError::NotFound, - _ => CoreError::InternalError, + _ => CoreError::InternalError(err.into()), })?; Ok(question_list diff --git a/src/common/Cargo.toml b/src/common/Cargo.toml index c727049..4bdee6d 100644 --- a/src/common/Cargo.toml +++ b/src/common/Cargo.toml @@ -39,3 +39,14 @@ features = ["derive"] [dependencies.tracing-subscriber] version = "0.3.18" features = ["env-filter"] + + +[dependencies.tonic] +version = "0.11.0" + +[dependencies.prost] +version = "0.12.3" + +[build-dependencies] +tonic-build = "0.11.0" +glob = "0.3.1" diff --git a/src/grpc/build.rs b/src/common/build.rs similarity index 100% rename from src/grpc/build.rs rename to src/common/build.rs diff --git a/src/grpc/proto/gpt_answer.proto b/src/common/proto/gpt_answer.proto similarity index 100% rename from src/grpc/proto/gpt_answer.proto rename to src/common/proto/gpt_answer.proto diff --git a/src/grpc/src/interfaces/gpt_answer.rs b/src/common/src/grpc/gpt_answer.rs similarity index 100% rename from src/grpc/src/interfaces/gpt_answer.rs rename to src/common/src/grpc/gpt_answer.rs diff --git a/src/grpc/src/interfaces/mod.rs b/src/common/src/grpc/mod.rs similarity index 100% rename from src/grpc/src/interfaces/mod.rs rename to src/common/src/grpc/mod.rs diff --git a/src/common/src/lib.rs b/src/common/src/lib.rs index c9499bd..4598395 100644 --- a/src/common/src/lib.rs +++ b/src/common/src/lib.rs @@ -1,2 +1,3 @@ +pub mod grpc; pub mod loggers; pub mod options; diff --git a/src/core/Cargo.toml b/src/core/Cargo.toml index 189d377..5dbd443 100644 --- a/src/core/Cargo.toml +++ b/src/core/Cargo.toml @@ -23,4 +23,4 @@ features = ["derive"] version = "1.0.57" [dependencies] -anyhow = "1.0.80" \ No newline at end of file +anyhow = "1.0.80" diff --git a/src/core/src/common/errors.rs b/src/core/src/common/errors.rs index 0f2d689..c2d1168 100644 --- a/src/core/src/common/errors.rs +++ b/src/core/src/common/errors.rs @@ -1,3 +1,5 @@ +use anyhow::Error; + #[derive(thiserror::Error, Debug)] pub enum CoreError { #[error("parse error {0}")] @@ -8,10 +10,13 @@ pub enum CoreError { #[error("missing parameters")] MissingParameters, + #[error("not found")] NotFound, - #[error("transparent")] - InternalError, + + #[error("internal error {0}")] + InternalError(#[from] Error), + #[error("unknown data store error")] Unknown, } diff --git a/src/grpc_server/Cargo.toml b/src/gpt_answer_service/Cargo.toml similarity index 90% rename from src/grpc_server/Cargo.toml rename to src/gpt_answer_service/Cargo.toml index d6a048b..76ab3ea 100644 --- a/src/grpc_server/Cargo.toml +++ b/src/gpt_answer_service/Cargo.toml @@ -4,7 +4,7 @@ test = [] example = [] [package] -name = "grpc_server" +name = "gpt_answer_service" edition = "2021" version = "0.0.1" autobins = true @@ -44,16 +44,13 @@ tracing = "0.1" [dependencies.common] path = "../common" -[dependencies.grpc_interface] -path = "../grpc" - [build-dependencies] tonic-build = "0.11.0" [lib] path = "src/lib.rs" -name = "grpc_server" +name = "gpt_answer_service" test = true doctest = true bench = true diff --git a/src/grpc_server/build.rs b/src/gpt_answer_service/build.rs similarity index 100% rename from src/grpc_server/build.rs rename to src/gpt_answer_service/build.rs diff --git a/src/grpc_server/config/00-default.toml b/src/gpt_answer_service/config/00-default.toml similarity index 60% rename from src/grpc_server/config/00-default.toml rename to src/gpt_answer_service/config/00-default.toml index 1f4048f..baf3a2b 100644 --- a/src/grpc_server/config/00-default.toml +++ b/src/gpt_answer_service/config/00-default.toml @@ -1,5 +1,3 @@ service_name = "rust-grpc-server" exporter_endpoint = "http://localhost:7281" - -[servers.gpt_answer_service] -url = "0.0.0.0:50051" \ No newline at end of file +server_endpoint = "0.0.0.0:50051" \ No newline at end of file diff --git a/src/gpt_answer_service/src/controllers/gpt_answer.rs b/src/gpt_answer_service/src/controllers/gpt_answer.rs new file mode 100644 index 0000000..d7e2237 --- /dev/null +++ b/src/gpt_answer_service/src/controllers/gpt_answer.rs @@ -0,0 +1,23 @@ +use tonic::{Request, Response, Status}; + +use common::grpc::gpt_answer::gpt_answer::{ + gpt_answer_service_server::GptAnswerService, GetAnswerPayload, GetAnswerResponse, +}; + +#[derive(Debug, Default)] +pub struct GptAnswerServer; + +#[tonic::async_trait] +impl GptAnswerService for GptAnswerServer { + async fn get_answer( + &self, + request: Request, + ) -> Result, Status> { + let payload = request.into_inner(); + // TODO: Implement your logic to generate an answer based on the question. + let answer = format!("Answer to: {}", payload.question); + + let response = GetAnswerResponse { answer }; + Ok(Response::new(response)) + } +} diff --git a/src/grpc_server/src/controllers/mod.rs b/src/gpt_answer_service/src/controllers/mod.rs similarity index 100% rename from src/grpc_server/src/controllers/mod.rs rename to src/gpt_answer_service/src/controllers/mod.rs diff --git a/src/grpc_server/src/lib.rs b/src/gpt_answer_service/src/lib.rs similarity index 100% rename from src/grpc_server/src/lib.rs rename to src/gpt_answer_service/src/lib.rs diff --git a/src/grpc_server/src/main.rs b/src/gpt_answer_service/src/main.rs similarity index 64% rename from src/grpc_server/src/main.rs rename to src/gpt_answer_service/src/main.rs index 201752b..23a6acb 100644 --- a/src/grpc_server/src/main.rs +++ b/src/gpt_answer_service/src/main.rs @@ -1,11 +1,26 @@ use clap::{Parser, Subcommand}; -use grpc_server::{controllers, options}; use opentelemetry::global; +use tonic::transport::Server; +use common::grpc::gpt_answer::gpt_answer::gpt_answer_service_server::GptAnswerServiceServer; use common::loggers::telemetry::init_telemetry; use common::options::parse_options; -use controllers::gpt_answer::init_gpt_answer_server; -use options::Options; +use gpt_answer_service::controllers::gpt_answer::GptAnswerServer; +use gpt_answer_service::options::Options; + +pub async fn init_grpc_server(options: Options) { + let server_endpoint = options.server_endpoint.clone(); + let gpt_answer_server = GptAnswerServer::default(); + let address = server_endpoint.parse().unwrap(); + + Server::builder() + .add_service(GptAnswerServiceServer::new(gpt_answer_server)) + .serve(address) + .await + .unwrap(); + + println!("GPT Answer server started at {}", server_endpoint); +} #[tokio::main] async fn main() { @@ -34,7 +49,7 @@ async fn main() { options.log.level.as_str(), ); - let gpt_answer_server = tokio::spawn(init_gpt_answer_server(options)); + let gpt_answer_server = tokio::spawn(init_grpc_server(options)); tokio::try_join!(gpt_answer_server).expect("Failed to run servers"); diff --git a/src/grpc_server/src/options.rs b/src/gpt_answer_service/src/options.rs similarity index 59% rename from src/grpc_server/src/options.rs rename to src/gpt_answer_service/src/options.rs index f660c2c..6cc2358 100644 --- a/src/grpc_server/src/options.rs +++ b/src/gpt_answer_service/src/options.rs @@ -1,6 +1,7 @@ -use common::options::{default_log, Log}; use serde::Deserialize; +use common::options::{default_log, Log}; + /// Configuration options for the application. /// /// This struct represents the configuration options for the application, including server settings, @@ -8,8 +9,8 @@ use serde::Deserialize; #[readonly::make] #[derive(Deserialize, Debug)] pub struct Options { - /// Configuration for the servers. - pub servers: GrpcServers, + /// Configuration for the grpc server endpoint. + pub server_endpoint: String, /// The endpoint for the exporter. pub exporter_endpoint: String, /// The name of the service. @@ -18,17 +19,3 @@ pub struct Options { #[serde(default = "default_log")] pub log: Log, } - -/// Represents servers configuration options. -#[derive(Deserialize, Debug)] -pub struct GrpcServers { - /// Configuration for using in-memory database. - pub gpt_answer_service: Option, -} - -/// Represents service server configuration. -#[derive(Debug, Deserialize, Clone)] -pub struct ServiceServer { - /// URL for the server. - pub url: String, -} diff --git a/src/grpc/Cargo.toml b/src/grpc/Cargo.toml deleted file mode 100644 index 652ee3f..0000000 --- a/src/grpc/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -bin = [] -bench = [] -test = [] -example = [] - -[package] -name = "grpc_interface" -edition = "2021" -version = "0.0.1" -autobins = true -autoexamples = true -autotests = true -autobenches = true - -[dependencies.tonic] -version = "0.11.0" - -[dependencies.prost] -version = "0.12.3" - -[build-dependencies] -tonic-build = "0.11.0" -glob = "0.3.1" - - -[lib] -path = "src/lib.rs" -name = "grpc_interface" -test = true -doctest = true -bench = true -doc = true -plugin = false -proc-macro = false -harness = true -edition = "2021" -required-features = [] -crate-type = ["rlib"] diff --git a/src/grpc/src/lib.rs b/src/grpc/src/lib.rs deleted file mode 100644 index 43b15ec..0000000 --- a/src/grpc/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod interfaces; diff --git a/src/grpc_server/src/controllers/gpt_answer.rs b/src/grpc_server/src/controllers/gpt_answer.rs deleted file mode 100644 index 7aae3d4..0000000 --- a/src/grpc_server/src/controllers/gpt_answer.rs +++ /dev/null @@ -1,52 +0,0 @@ -use grpc_interface::interfaces::gpt_answer::gpt_answer::gpt_answer_service_server::{ - GptAnswerService, GptAnswerServiceServer, -}; -use grpc_interface::interfaces::gpt_answer::gpt_answer::{GetAnswerPayload, GetAnswerResponse}; -use rust_core::common::errors::CoreError; -use tonic::{transport::Server, Request, Response, Status}; - -use crate::options::Options; - -#[derive(Debug, Default)] -pub struct GptAnswerServer; - -#[tonic::async_trait] -impl GptAnswerService for GptAnswerServer { - async fn get_answer( - &self, - request: Request, - ) -> Result, Status> { - let payload = request.into_inner(); - // TODO: Implement your logic to generate an answer based on the question. - let answer = format!("Answer to: {}", payload.question); - - let response = GetAnswerResponse { answer }; - Ok(Response::new(response)) - } -} - -pub async fn init_gpt_answer_server(options: Options) { - let gpt_answer_config = options.servers.gpt_answer_service.clone().unwrap(); - let result = gpt_answer_config.url.parse().map_err(|err| { - eprintln!("Error: {:?}", err); - CoreError::InternalError - }); - - if result.is_ok() { - let addr = result.unwrap(); - - println!("GPT Answer server config at {}", addr); - - let gpt_answer_server = GptAnswerServer::default(); - - Server::builder() - .add_service(GptAnswerServiceServer::new(gpt_answer_server)) - .serve(addr) - .await - .unwrap(); - - println!("GPT Answer server started at {}", addr); - } else { - eprintln!("GPT Answer server failed to start"); - } -} diff --git a/src/public/Cargo.toml b/src/public/Cargo.toml index 74b8a55..c2cc804 100644 --- a/src/public/Cargo.toml +++ b/src/public/Cargo.toml @@ -103,9 +103,6 @@ version = "1.0.57" [dependencies.anyhow] version = "1.0.80" -[dependencies.grpc_interface] -path = "../grpc" - [lib] path = "src/lib.rs" name = "cli" diff --git a/src/public/config/00-default.toml b/src/public/config/00-default.toml index 029a598..650e010 100644 --- a/src/public/config/00-default.toml +++ b/src/public/config/00-default.toml @@ -6,4 +6,7 @@ exporter_endpoint = "http://localhost:7281" [server] url = "0.0.0.0" -port = 8000 \ No newline at end of file +port = 8000 + +[grpc_client] +gpt_answer_url = "0.0.0.0:50051" diff --git a/src/public/src/controllers/question.rs b/src/public/src/controllers/question.rs index 6bb8797..c82eda2 100644 --- a/src/public/src/controllers/question.rs +++ b/src/public/src/controllers/question.rs @@ -2,18 +2,18 @@ use std::collections::HashMap; use std::str::FromStr; use std::sync::Arc; -use adapter::repositories::grpc::models::gpt_answer::GptAnswerGrpcClient; use tracing::instrument; use warp::http::StatusCode; use warp::reject::Rejection; use warp::Reply; +use adapter::repositories::grpc::models::gpt_answer::GptAnswerGrpcClient; use rust_core::entities::question::{QuestionEntity, QuestionId}; use rust_core::entities::question_filter::QuestionFilter; use rust_core::ports::question::QuestionPort; use crate::errors::WarpError; -use crate::options::GrpcClients; +use crate::options::GrpcClient; /// Handler for retrieving questions based on query parameters. /// @@ -23,7 +23,7 @@ use crate::options::GrpcClients; #[instrument(level = "info", skip(question_port))] pub async fn get_questions( question_port: Arc, - server_config: Arc, + server_config: Arc, query: HashMap, ) -> Result { let question_filter = QuestionFilter::from_query(&query).map_err(WarpError::from)?; @@ -44,7 +44,7 @@ pub async fn get_questions( #[instrument(level = "info", skip(question_port))] pub async fn get_question( question_port: Arc, - server_config: Arc, + server_config: Arc, id: String, ) -> Result { let question_id = QuestionId::from_str(id.as_str()).map_err(WarpError::from)?; @@ -65,7 +65,7 @@ pub async fn get_question( #[instrument(level = "info", skip(question_port))] pub async fn add_question( question_port: Arc, - server_config: Arc, + server_config: Arc, question: QuestionEntity, ) -> Result { question_port.add(question).await.map_err(WarpError::from)?; @@ -81,7 +81,7 @@ pub async fn add_question( #[instrument(level = "info", skip(question_port))] pub async fn delete_question( question_port: Arc, - server_config: Arc, + server_config: Arc, id: String, ) -> Result { let question_id = QuestionId::from_str(id.as_str()).map_err(WarpError::from)?; @@ -103,12 +103,11 @@ pub async fn delete_question( #[instrument(level = "info", skip(question_port))] pub async fn update_question( question_port: Arc, - server_config: Arc, + server_config: Arc, id: String, mut question: QuestionEntity, ) -> Result { - let question_id = QuestionId::from_str(id.as_str()).map_err(WarpError::from)?; - question.id = question_id; + question.id = QuestionId::from_str(id.as_str()).map_err(WarpError::from)?; question_port .update(question) @@ -127,18 +126,19 @@ pub async fn update_question( /// # Arguments /// /// * `question_port`: A trait object implementing `QuestionPort` for interacting with questions. -/// * `gpt_client`: An instance of `GrpcClient` used for communication with the gRPC server. +/// * `server_config`: An Arc reference to `GrpcClients` struct containing configuration +/// for gRPC clients. /// * `id`: The ID of the question to fetch the answer for. /// /// # Returns /// -/// Returns a `Result` containing the HTTP response. If successful, responds with a String -/// representation of the answer and a status code of 200 OK. If there's an error during -/// question retrieval, gRPC communication, or response construction, it returns a Warp Rejection. +/// Returns a `Result` containing the HTTP response. If successful, responds with a `String` +/// representation of the answer and a status code of `200 OK`. If there's an error during +/// question retrieval, gRPC communication, or response construction, it returns a Warp `Rejection`. #[instrument(level = "info", skip(question_port))] -pub async fn get_question_answer_controller( +pub async fn get_question_answer( question_port: Arc, - server_config: Arc, + server_config: Arc, id: String, ) -> Result { let question = question_port @@ -147,13 +147,17 @@ pub async fn get_question_answer_controller( .map_err(WarpError::from)?; // Clone the gpt_client string to have a static lifetime - let gpt_client = server_config.gpt_answer_service.clone().unwrap().url; + let url = server_config.gpt_answer_url.clone(); // Use the cloned gpt_client string - let client = GptAnswerGrpcClient::get_instance(gpt_client.leak()).await; + let mut client = GptAnswerGrpcClient::connect(url.leak()) + .await + .map_err(|err| { + tracing::error!("Error connecting to gRPC server: {:?}", err); + WarpError::from(err) + })?; let answer = client - .unwrap() .get_answer(&question.content) .await .map_err(WarpError::from)?; diff --git a/src/public/src/errors.rs b/src/public/src/errors.rs index 555164c..e92437f 100644 --- a/src/public/src/errors.rs +++ b/src/public/src/errors.rs @@ -1,4 +1,5 @@ use std::io; + use thiserror::Error; use warp::body::BodyDeserializeError; use warp::cors::CorsForbidden; @@ -34,7 +35,7 @@ pub async fn return_error(r: Rejection) -> Result { "MissingParameters".to_string(), StatusCode::BAD_REQUEST, )), - CoreError::InternalError => Ok(warp::reply::with_status( + CoreError::InternalError(_) => Ok(warp::reply::with_status( "InternalError".to_string(), StatusCode::INTERNAL_SERVER_ERROR, )), diff --git a/src/public/src/main.rs b/src/public/src/main.rs index a5c0302..e26783a 100644 --- a/src/public/src/main.rs +++ b/src/public/src/main.rs @@ -1,13 +1,12 @@ +use std::net::{Ipv4Addr, SocketAddrV4}; +use std::str::FromStr; +use std::sync::Arc; + #[cfg_attr(debug_assertions, allow(dead_code, unused_imports))] use openssl; #[rustfmt::skip] #[cfg_attr(debug_assertions, allow(dead_code, unused_imports))] use diesel; - -use std::net::{Ipv4Addr, SocketAddrV4}; -use std::str::FromStr; -use std::sync::Arc; - use clap::{Parser, Subcommand}; use deadpool_diesel::postgres::Pool; use deadpool_diesel::{Manager, Runtime}; @@ -93,8 +92,8 @@ pub async fn run_warp_server(options: Options) { Arc::new(QuestionInMemoryRepository::new()) }; - let grpc_clients = options.grpc_clients.clone(); - let router = Router::new(question_port, Arc::new(grpc_clients)); + let grpc_client = options.grpc_client.clone(); + let router = Router::new(question_port, Arc::new(grpc_client)); let address = SocketAddrV4::new( Ipv4Addr::from_str(options.server.url.as_str()).unwrap(), diff --git a/src/public/src/options.rs b/src/public/src/options.rs index ad1c30a..2f0a331 100644 --- a/src/public/src/options.rs +++ b/src/public/src/options.rs @@ -12,9 +12,9 @@ use common::options::{default_log, Log}; pub struct Options { /// Configuration for the server. pub server: Server, - /// Specifies the backend database will be used. - pub grpc_clients: GrpcClients, - /// Specifies the backend database will be used. + /// Specifies the gRPC client configuration for communicating with the backend services. + pub grpc_client: GrpcClient, + /// Specifies the configuration of grpc clients will be connected. pub db: Database, /// The endpoint for the exporter. pub exporter_endpoint: String, @@ -47,15 +47,9 @@ pub struct Server { pub url: String, } -/// Represents server configuration. -#[derive(Debug, Deserialize, Clone)] -pub struct GrpcClients { - pub gpt_answer_service: Option, -} - -/// Represents service server configuration. +/// Represents grpc client configuration. #[derive(Debug, Deserialize, Clone)] -pub struct ServiceServer { - /// URL for the server. - pub url: String, +pub struct GrpcClient { + /// URL for the GPT Answer gRPC client. + pub gpt_answer_url: String, } diff --git a/src/public/src/router.rs b/src/public/src/router.rs index 98c33a6..1cf91da 100644 --- a/src/public/src/router.rs +++ b/src/public/src/router.rs @@ -1,28 +1,27 @@ use std::sync::Arc; - use warp::http::Method; use warp::{Filter, Rejection, Reply}; use rust_core::ports::question::QuestionPort; use crate::controllers::question::{ - add_question, delete_question, get_question, get_question_answer_controller, get_questions, + add_question, delete_question, get_question, get_question_answer, get_questions, update_question, }; use crate::errors::return_error; -use crate::options::GrpcClients; +use crate::options::GrpcClient; /// Router for handling HTTP requests related to questions. pub struct Router { question_port: Arc, - server_config: Arc, + server_config: Arc, } impl Router { /// Creates a new Router instance with the specified QuestionPort. pub fn new( question_port: Arc, - server_config: Arc, + server_config: Arc, ) -> Self { Router { question_port: question_port.clone(), @@ -85,7 +84,7 @@ impl Router { .and(server_config.clone()) .and(warp::path::param::()) .and(warp::path("answer")) - .and_then(get_question_answer_controller); + .and_then(get_question_answer); get_questions .with(cors) diff --git a/src/public/tests/questions_router_test.rs b/src/public/tests/questions_router_test.rs index 0672db1..1900147 100644 --- a/src/public/tests/questions_router_test.rs +++ b/src/public/tests/questions_router_test.rs @@ -15,10 +15,7 @@ mod tests { in_memory::question::QuestionInMemoryRepository, postgres::question_db::{QuestionDBRepository, MIGRATIONS}, }; - use cli::{ - options::{GrpcClients, ServiceServer}, - router::Router, - }; + use cli::{options::GrpcClient, router::Router}; use rust_core::{ entities::question::{QuestionEntity, QuestionId}, ports::question::QuestionPort, @@ -33,10 +30,8 @@ mod tests { where T: QuestionPort + Send + Sync + 'static, { - let server_config: GrpcClients = GrpcClients { - gpt_answer_service: Some(ServiceServer { - url: "http://localhost:50051".to_string(), - }), + let server_config: GrpcClient = GrpcClient { + gpt_answer_url: "http://localhost:50051".to_string(), }; let router = Router::new(question_port, Arc::new(server_config));