Skip to content

Commit

Permalink
remove redundant to_string calls, use ? for option
Browse files Browse the repository at this point in the history
  • Loading branch information
rdcm committed Oct 17, 2023
1 parent 5269b47 commit 7a722e3
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 119 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions app/src/endpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub async fn get_user(
path: Path<String>,
) -> HttpResponse {
let query = GetUserQuery {
id: path.to_string(),
id: path.into_inner(),
};

let option = handler.handle(query).await;
Expand All @@ -30,7 +30,7 @@ pub async fn get_user(
Some(user) => HttpResponse::Ok().json(UserResponse {
name: user.name,
age: user.age,
id: path.to_string(),
id: user.id,
}),
None => HttpResponse::BadRequest().json(ErrorResponse { code: 101 }),
}
Expand All @@ -49,10 +49,12 @@ pub async fn get_user(
#[post("/user")]
pub async fn create_user(
handler: Data<dyn ICommandHandler<CreateUserCommand, Option<String>>>,
request: Json<CreateUserRequest>,
json: Json<CreateUserRequest>,
) -> HttpResponse {
let request = json.into_inner();

let command = CreateUserCommand {
name: request.name.to_string(),
name: request.name,
age: request.age,
};

Expand Down
5 changes: 3 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ services:
environment:
- API_HOST=0.0.0.0
- API_PORT=8080
- RUST_BACKTRACE=1
- DB_CONNECTION_STRING=mongodb://mongo:27017/test
- DB_NAME=docker
- DB_URI=mongodb://mongo:27017
- RUST_BACKTRACE=1
1 change: 1 addition & 0 deletions domain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ edition = "2021"
async-trait = { version = "0.1.73", features = [] }
serde = "1.0.188"
serde_derive = "1.0.188"
bson = "2.7.0"

10 changes: 10 additions & 0 deletions domain/src/queries.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use async_trait::async_trait;
use bson::serde_helpers::{
deserialize_hex_string_from_object_id, serialize_hex_string_as_object_id,
};
use serde_derive::{Deserialize, Serialize};

#[async_trait]
Expand All @@ -12,6 +15,13 @@ pub struct GetUserQuery {

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct User {
#[serde(
rename = "_id",
deserialize_with = "deserialize_hex_string_from_object_id",
serialize_with = "serialize_hex_string_as_object_id",
skip_serializing_if = "String::is_empty"
)]
pub id: String,
pub name: String,
pub age: u8,
}
3 changes: 2 additions & 1 deletion domain_impl/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ pub struct CreateUserCommandHandler {
impl ICommandHandler<CreateUserCommand, Option<String>> for CreateUserCommandHandler {
async fn handle(&self, cmd: CreateUserCommand) -> Option<String> {
let user = User {
name: cmd.name.to_string(),
id: String::new(),
name: cmd.name,
age: cmd.age,
};

Expand Down
79 changes: 79 additions & 0 deletions host/src/composition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use actix_web::dev::Server;
use actix_web::web::Data;
use actix_web::{App, HttpServer};
use mongodb::options::{ClientOptions, ServerApi, ServerApiVersion};
use mongodb::{Client, Collection};
use std::net::SocketAddr;
use std::sync::Arc;
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;

use crate::conf::AppConf;
use app::endpoints::{create_user, get_user};
use app::models::*;
use domain::commands::{CreateUserCommand, ICommandHandler};
use domain::queries::{GetUserQuery, IQueryHandler, User};
use domain_impl::handlers::{CreateUserCommandHandler, GetUserQueryHandler};
use infra::repositories::UserRepository;

#[derive(OpenApi)]
#[openapi(
paths(app::endpoints::create_user, app::endpoints::get_user),
components(
schemas(CreateUserRequest, CreatedUserIdResponse, ErrorResponse),
schemas(UserResponse, ErrorResponse)
)
)]
struct ApiDoc;
pub struct Composition {
pub server: Server,
pub addrs: Vec<SocketAddr>,
}

impl Composition {
pub async fn new(conf: &AppConf) -> Result<Composition, std::io::Error> {
let user_repository_arc = Arc::new(create_user_repository(conf).await);
let command_handler: Arc<dyn ICommandHandler<CreateUserCommand, Option<String>>> =
Arc::new(CreateUserCommandHandler {
repo: user_repository_arc.clone(),
});
let query_handler: Arc<dyn IQueryHandler<GetUserQuery, Option<User>>> =
Arc::new(GetUserQueryHandler {
repo: user_repository_arc.clone(),
});

let openapi = ApiDoc::openapi();

let addr = conf.get_api_address();
let http_server = HttpServer::new(move || {
App::new()
.service(
SwaggerUi::new("/swagger-ui/{_:.*}")
.url("/api-docs/openapi.json", openapi.clone()),
)
.service(create_user)
.service(get_user)
.app_data(Data::from(command_handler.clone()))
.app_data(Data::from(query_handler.clone()))
})
.bind(&addr)
.unwrap_or_else(|_| panic!("Failed to bind to the host: {}", &addr));

let addrs = http_server.addrs();
let server = http_server.run();

Ok(Self { server, addrs })
}
}

async fn create_user_repository(conf: &AppConf) -> UserRepository {
let mut client_options = ClientOptions::parse(&conf.db_uri).await.unwrap();

let server_api = ServerApi::builder().version(ServerApiVersion::V1).build();
client_options.server_api = Some(server_api);

let client = Client::with_options(client_options).unwrap();

let collection: Collection<User> = client.database(&conf.db_name).collection("users");
UserRepository::new(collection)
}
30 changes: 20 additions & 10 deletions host/src/conf.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
pub struct AppConf {
pub api_host: String,
pub api_port: i32,
pub connection_string: String,
pub db_uri: String,
pub db_name: String,
}

pub fn read_app_conf() -> AppConf {
AppConf {
api_host: std::env::var("API_HOST").unwrap_or_else(|_| "0.0.0.0".into()),
api_port: std::env::var("API_PORT")
.unwrap_or_else(|_| "8080".into())
.parse::<i32>()
.expect("wrong api port"),
connection_string: std::env::var("DB_CONNECTION_STRING")
.unwrap_or_else(|_| "mongodb://0.0.0.0:27017/test".into()),
impl AppConf {
pub fn new() -> AppConf {
Self {
db_name: std::env::var("DB_NAME").unwrap_or_else(|_| "test".into()),
api_host: std::env::var("API_HOST").unwrap_or_else(|_| "0.0.0.0".into()),
api_port: std::env::var("API_PORT")
.unwrap_or_else(|_| "8080".into())
.parse::<i32>()
.expect("wrong api port"),
db_uri: std::env::var("DB_URI")
.unwrap_or_else(|_| "mongodb://0.0.0.0:27017/test".into()),
}
}
}

Expand All @@ -21,3 +25,9 @@ impl AppConf {
format!("{}:{}", self.api_host, self.api_port)
}
}

impl Default for AppConf {
fn default() -> Self {
Self::new()
}
}
77 changes: 0 additions & 77 deletions host/src/factory.rs

This file was deleted.

4 changes: 2 additions & 2 deletions host/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[path = "composition.rs"]
pub mod composition;
#[path = "conf.rs"]
pub mod conf;
#[path = "factory.rs"]
pub mod factory;
8 changes: 4 additions & 4 deletions host/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use host::conf::read_app_conf;
use host::factory::create_server;
use host::composition::Composition;
use host::conf::AppConf;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "debug");
env_logger::init();

let conf = read_app_conf();
create_server(&conf).await.unwrap().server.await
let conf = AppConf::new();
Composition::new(&conf).await?.server.await
}
31 changes: 15 additions & 16 deletions infra/src/repositories.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use async_trait::async_trait;
use mongodb::{bson, bson::doc, Collection};
use mongodb::bson::oid::ObjectId;
use mongodb::{bson::doc, Collection};

use domain::queries::User;
use domain_impl::ports::IUserRepository;
Expand All @@ -18,26 +19,24 @@ impl UserRepository {
#[async_trait]
impl IUserRepository for UserRepository {
async fn create(&self, user: User) -> Option<String> {
let result = self.collection.insert_one(user, None).await;
let user_id = self
.collection
.insert_one(user, None)
.await
.ok()?
.inserted_id
.as_object_id()?
.to_string();

return match result {
Ok(insertion_result) => Some(
insertion_result
.inserted_id
.as_object_id()
.unwrap()
.to_string(),
),
Err(_) => None,
};
Some(user_id)
}

async fn get(&self, id: String) -> Option<User> {
let user_id = bson::oid::ObjectId::parse_str(&id).ok()?;
return self
.collection
let user_id = ObjectId::parse_str(&id).ok()?;

self.collection
.find_one(doc! { "_id": user_id }, None)
.await
.ok()?;
.ok()?
}
}
7 changes: 4 additions & 3 deletions integrtion-tests/tests/sut.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use actix_web::rt;
use app::models::{CreateUserRequest, CreatedUserIdResponse, UserResponse};
use host::composition::Composition;
use host::conf::AppConf;
use host::factory::create_server;
use reqwest::StatusCode;

#[derive(Clone)]
Expand All @@ -14,10 +14,11 @@ impl Sut {
let conf = AppConf {
api_host: "127.0.0.1".to_string(),
api_port: 0,
connection_string: "mongodb://127.0.0.1/test".to_string(),
db_uri: "mongodb://127.0.0.1/test".to_string(),
db_name: "test".to_string(),
};

let info = create_server(&conf).await.unwrap();
let info = Composition::new(&conf).await.unwrap();
let base_url = format!("http://{}:{}", info.addrs[0].ip(), info.addrs[0].port());

rt::spawn(info.server);
Expand Down

0 comments on commit 7a722e3

Please sign in to comment.