Arc<dyn repo>

This commit is contained in:
Jeremy Yin 2023-07-01 18:10:46 +08:00
parent fcc54cc0c9
commit 78ec96f9ae
2 changed files with 28 additions and 13 deletions

View File

@ -1,3 +1,4 @@
use std::sync::Arc;
use crate::domain::entity::{PokemonName, PokemonNumber, PokemonTypes}; use crate::domain::entity::{PokemonName, PokemonNumber, PokemonTypes};
use crate::repo::pokemon::{Insert, Repository}; use crate::repo::pokemon::{Insert, Repository};
@ -13,7 +14,7 @@ enum Response {
Conflict, Conflict,
} }
fn execute(repo: &mut dyn Repository, req: Request) -> Response { fn execute(repo: Arc<dyn Repository>, req: Request) -> Response {
println!("execute"); println!("execute");
match ( match (
PokemonNumber::try_from(req.number), PokemonNumber::try_from(req.number),
@ -23,6 +24,7 @@ fn execute(repo: &mut dyn Repository, req: Request) -> Response {
(Ok(number), Ok(name), Ok(types)) => match repo.insert(number, name, types){ (Ok(number), Ok(name), Ok(types)) => match repo.insert(number, name, types){
Insert::Ok(num) => Response::Ok(u16::from(num)), Insert::Ok(num) => Response::Ok(u16::from(num)),
Insert::Conflict => Response::Conflict, Insert::Conflict => Response::Conflict,
Insert::Error => Response::BadRequest,
}, },
_ => Response::BadRequest, _ => Response::BadRequest,
} }
@ -35,14 +37,14 @@ mod tests {
#[test] #[test]
fn it_should_return_the_pokemon_number_otherwise() { fn it_should_return_the_pokemon_number_otherwise() {
let mut repo = InMemoryRepository::new(); let mut repo = Arc::new(InMemoryRepository::new());
let number = 25; let number = 25;
let req = Request { let req = Request {
number: number, number: number,
name: "Pikachu".to_string(), name: "Pikachu".to_string(),
types: vec!["Electric".to_string(), ], types: vec!["Electric".to_string(), ],
}; };
let res = execute(&mut repo, req); let res = execute(repo, req);
match res { match res {
Response::Ok(num) => assert_eq!(num, number), Response::Ok(num) => assert_eq!(num, number),
_ => unreachable!(), _ => unreachable!(),
@ -51,14 +53,14 @@ mod tests {
#[test] #[test]
fn it_should_return_a_bad_request_error_when_request_is_invalid() { fn it_should_return_a_bad_request_error_when_request_is_invalid() {
let mut repo = InMemoryRepository::new(); let mut repo = Arc::new(InMemoryRepository::new());
let number = 25; let number = 25;
let req = Request { let req = Request {
number: number, number: number,
name: "".to_string(), name: "".to_string(),
types: vec!["Electric".to_string(), ], types: vec!["Electric".to_string(), ],
}; };
let res = execute(&mut repo, req); let res = execute(repo, req);
match res { match res {
Response::Ok(num) => assert_eq!(num, number), Response::Ok(num) => assert_eq!(num, number),
Response::BadRequest => {}, Response::BadRequest => {},
@ -71,14 +73,14 @@ mod tests {
let number = PokemonNumber::try_from(25).unwrap(); let number = PokemonNumber::try_from(25).unwrap();
let name = PokemonName::try_from("Pikachu".to_string()).unwrap(); let name = PokemonName::try_from("Pikachu".to_string()).unwrap();
let types = PokemonTypes::try_from(vec!["Electric".to_string(),]).unwrap(); let types = PokemonTypes::try_from(vec!["Electric".to_string(),]).unwrap();
let mut repo = InMemoryRepository::new(); let mut repo = Arc::new(InMemoryRepository::new());
repo.insert(number, name, types); repo.insert(number, name, types);
let req = Request { let req = Request {
number: 25, number: 25,
name: "Charmander".to_string(), name: "Charmander".to_string(),
types: vec!["File".to_string()], types: vec!["File".to_string()],
}; };
let res = execute(&mut repo, req); let res = execute(repo, req);
match res { match res {
Response::Conflict => {}, Response::Conflict => {},
_ => unreachable!(), _ => unreachable!(),

View File

@ -1,16 +1,19 @@
use std::sync::Mutex;
use crate::domain::entity::{Pokemon, PokemonName, PokemonNumber, PokemonTypes}; use crate::domain::entity::{Pokemon, PokemonName, PokemonNumber, PokemonTypes};
pub trait Repository: Send + Sync { pub trait Repository: Send + Sync {
fn insert(&mut self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Insert; fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Insert;
} }
#[derive(Debug)] #[derive(Debug)]
pub struct InMemoryRepository { pub struct InMemoryRepository {
pokemons: Vec<Pokemon> error: bool,
pokemons: Mutex<Vec<Pokemon>>
} }
impl InMemoryRepository { impl InMemoryRepository {
pub fn new() -> Self { pub fn new() -> Self {
let pokemons: Vec<Pokemon> = vec![]; let pokemons: Mutex<Vec<Pokemon>> = Mutex::new(vec![]);
Self { Self {
error: false,
pokemons pokemons
} }
} }
@ -19,16 +22,26 @@ impl InMemoryRepository {
pub enum Insert { pub enum Insert {
Ok(PokemonNumber), Ok(PokemonNumber),
Conflict, Conflict,
Error,
} }
impl Repository for InMemoryRepository { impl Repository for InMemoryRepository {
fn insert(&mut self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Insert { fn insert(&self, number: PokemonNumber, name: PokemonName, types: PokemonTypes) -> Insert {
if self.error {
return Insert::Error;
}
let mut lock = match self.pokemons.lock() {
Ok(lock) => lock,
_ => return Insert::Error,
};
println!("{number:?} {:?}", self.pokemons); println!("{number:?} {:?}", self.pokemons);
if self.pokemons.iter().any(|pokemon| pokemon.number == number) { if lock.iter().any(|pokemon| pokemon.number == number) {
return Insert::Conflict; return Insert::Conflict;
} }
let number_clone = number.clone(); let number_clone = number.clone();
self.pokemons.push(Pokemon::new(number_clone, name, types)); lock.push(Pokemon::new(number_clone, name, types));
println!("{number:?} {:?}", self.pokemons); println!("{number:?} {:?}", self.pokemons);
Insert::Ok(number) Insert::Ok(number)
} }