diff --git a/src/domain/create_pokemon.rs b/src/domain/create_pokemon.rs index 79a2406..e3466f2 100644 --- a/src/domain/create_pokemon.rs +++ b/src/domain/create_pokemon.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; use crate::domain::entity::{PokemonName, PokemonNumber, PokemonTypes}; use crate::repo::pokemon::{Insert, Repository}; @@ -13,7 +14,7 @@ enum Response { Conflict, } -fn execute(repo: &mut dyn Repository, req: Request) -> Response { +fn execute(repo: Arc, req: Request) -> Response { println!("execute"); match ( 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){ Insert::Ok(num) => Response::Ok(u16::from(num)), Insert::Conflict => Response::Conflict, + Insert::Error => Response::BadRequest, }, _ => Response::BadRequest, } @@ -35,14 +37,14 @@ mod tests { #[test] fn it_should_return_the_pokemon_number_otherwise() { - let mut repo = InMemoryRepository::new(); + let mut repo = Arc::new(InMemoryRepository::new()); let number = 25; let req = Request { number: number, name: "Pikachu".to_string(), types: vec!["Electric".to_string(), ], }; - let res = execute(&mut repo, req); + let res = execute(repo, req); match res { Response::Ok(num) => assert_eq!(num, number), _ => unreachable!(), @@ -51,14 +53,14 @@ mod tests { #[test] 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 req = Request { number: number, name: "".to_string(), types: vec!["Electric".to_string(), ], }; - let res = execute(&mut repo, req); + let res = execute(repo, req); match res { Response::Ok(num) => assert_eq!(num, number), Response::BadRequest => {}, @@ -71,14 +73,14 @@ mod tests { let number = PokemonNumber::try_from(25).unwrap(); let name = PokemonName::try_from("Pikachu".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); let req = Request { number: 25, name: "Charmander".to_string(), types: vec!["File".to_string()], }; - let res = execute(&mut repo, req); + let res = execute(repo, req); match res { Response::Conflict => {}, _ => unreachable!(), diff --git a/src/repo/pokemon.rs b/src/repo/pokemon.rs index c9e80ad..50b5c99 100644 --- a/src/repo/pokemon.rs +++ b/src/repo/pokemon.rs @@ -1,16 +1,19 @@ +use std::sync::Mutex; use crate::domain::entity::{Pokemon, PokemonName, PokemonNumber, PokemonTypes}; 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)] pub struct InMemoryRepository { - pokemons: Vec + error: bool, + pokemons: Mutex> } impl InMemoryRepository { pub fn new() -> Self { - let pokemons: Vec = vec![]; + let pokemons: Mutex> = Mutex::new(vec![]); Self { + error: false, pokemons } } @@ -19,16 +22,26 @@ impl InMemoryRepository { pub enum Insert { Ok(PokemonNumber), Conflict, + Error, } 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); - if self.pokemons.iter().any(|pokemon| pokemon.number == number) { + if lock.iter().any(|pokemon| pokemon.number == number) { return Insert::Conflict; } 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); Insert::Ok(number) }