Added better error handling for API+Database

+ GeoffreyDatabaseError implements Into<GeoffreyApiError>
+ The database Option and Result were combined into just Result to reduce complexity
main
Joey Hines 2021-10-17 12:21:01 -06:00
parent 692cbfebd8
commit c2bc16f3d8
No known key found for this signature in database
GPG Key ID: 80F567B5C968F91B
5 changed files with 30 additions and 17 deletions

View File

@ -42,7 +42,7 @@ impl Command for AddLocation {
.insert(location) .insert(location)
.map_err(|err| GeoffreyAPIError::DatabaseError(err.to_string())) .map_err(|err| GeoffreyAPIError::DatabaseError(err.to_string()))
} else { } else {
Err(GeoffreyAPIError::PlayerNotFound) Err(GeoffreyAPIError::PlayerNotRegistered)
} }
} }
} }

View File

@ -2,13 +2,11 @@ use crate::Result;
use geoffrey_db::database::Database; use geoffrey_db::database::Database;
use geoffrey_models::models::parameters::CommandRequest; use geoffrey_models::models::parameters::CommandRequest;
use geoffrey_models::models::player::Player; use geoffrey_models::models::player::Player;
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
pub fn get_player_from_req<T>(db: &Database, req: &CommandRequest<T>) -> Result<Option<Player>> { pub fn get_player_from_req<T>(db: &Database, req: &CommandRequest<T>) -> Result<Option<Player>> {
if let Some(user_id) = &req.user { if let Some(user_id) = &req.user {
Ok(db Ok(db
.filter(|_, player: &Player| player.has_user_id(user_id)) .filter(|_, player: &Player| player.has_user_id(user_id)).map_err(|e| e.into())?
.map_err(|err| GeoffreyAPIError::DatabaseError(err.to_string()))?
.next()) .next())
} else { } else {
Ok(None) Ok(None)

View File

@ -48,7 +48,7 @@ impl Database {
Ok(model) Ok(model)
} }
pub fn get<T>(&self, id: u64) -> Result<Option<T>> pub fn get<T>(&self, id: u64) -> Result<T>
where where
T: GeoffreyDatabaseModel, T: GeoffreyDatabaseModel,
{ {
@ -56,9 +56,9 @@ impl Database {
let id_bytes = id.to_be_bytes(); let id_bytes = id.to_be_bytes();
if let Some(bytes) = tree.get(id_bytes)? { if let Some(bytes) = tree.get(id_bytes)? {
Ok(Some(T::try_from_bytes(&bytes)?)) Ok(T::try_from_bytes(&bytes)?)
} else { } else {
Ok(None) Err(GeoffreyDBError::NotFound)
} }
} }
@ -125,7 +125,7 @@ mod tests {
#[test] #[test]
fn test_insert() { fn test_insert() {
let player = Player::new("CoolZero123", UserID::DiscordUUID(0u64)); let player = Player::new("CoolZero123", UserID::DiscordUUID {discord_uuid: 0u64});
let p2 = DB.insert::<Player>(player.clone()).unwrap(); let p2 = DB.insert::<Player>(player.clone()).unwrap();
@ -137,8 +137,8 @@ mod tests {
#[test] #[test]
fn test_unique_insert() { fn test_unique_insert() {
let player1 = Player::new("CoolZero123", UserID::DiscordUUID(0u64)); let player1 = Player::new("CoolZero123", UserID::DiscordUUID {discord_uuid: 0u64});
let player2 = Player::new("CoolZero123", UserID::DiscordUUID(0u64)); let player2 = Player::new("CoolZero123", UserID::DiscordUUID {discord_uuid: 0u64});
DB.insert::<Player>(player1.clone()).unwrap(); DB.insert::<Player>(player1.clone()).unwrap();
assert_eq!(DB.insert::<Player>(player2.clone()).is_err(), true); assert_eq!(DB.insert::<Player>(player2.clone()).is_err(), true);
@ -148,20 +148,19 @@ mod tests {
#[test] #[test]
fn test_get() { fn test_get() {
let player = Player::new("CoolZero123", UserID::DiscordUUID(0u64)); let player = Player::new("CoolZero123", UserID::DiscordUUID {discord_uuid: 0u64});
let p2 = DB.insert::<Player>(player.clone()).unwrap(); let p2 = DB.insert::<Player>(player.clone()).unwrap();
let p3 = DB.get::<Player>(p2.id().unwrap()).unwrap(); let p3 = DB.get::<Player>(p2.id().unwrap()).unwrap();
assert!(p3.is_some()); assert_eq!(p3.name, player.name);
assert_eq!(p3.unwrap().name, player.name);
cleanup(); cleanup();
} }
#[test] #[test]
fn test_filter() { fn test_filter() {
let player = Player::new("CoolZero123", UserID::DiscordUUID(0u64)); let player = Player::new("CoolZero123", UserID::DiscordUUID {discord_uuid: 0u64});
let player = DB.insert::<Player>(player.clone()).unwrap(); let player = DB.insert::<Player>(player.clone()).unwrap();
let loc = Location::new( let loc = Location::new(
"Test Shop", "Test Shop",
@ -191,7 +190,7 @@ mod tests {
let insert_count = 1000; let insert_count = 1000;
let timer = Instant::now(); let timer = Instant::now();
for i in 0..insert_count { for i in 0..insert_count {
let player = Player::new("test", UserID::DiscordUUID(i)); let player = Player::new("test", UserID::DiscordUUID {discord_uuid: i});
DB.insert::<Player>(player).unwrap(); DB.insert::<Player>(player).unwrap();
} }

View File

@ -1,3 +1,5 @@
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
pub type Result<T> = std::result::Result<T, GeoffreyDBError>; pub type Result<T> = std::result::Result<T, GeoffreyDBError>;
#[derive(Debug)] #[derive(Debug)]
@ -5,6 +7,7 @@ pub enum GeoffreyDBError {
SledError(sled::Error), SledError(sled::Error),
SerdeJsonError(serde_json::Error), SerdeJsonError(serde_json::Error),
NotUnique, NotUnique,
NotFound,
} }
impl std::error::Error for GeoffreyDBError {} impl std::error::Error for GeoffreyDBError {}
@ -15,6 +18,7 @@ impl std::fmt::Display for GeoffreyDBError {
GeoffreyDBError::SledError(e) => write!(f, "Sled Error: {}", e), GeoffreyDBError::SledError(e) => write!(f, "Sled Error: {}", e),
GeoffreyDBError::SerdeJsonError(e) => write!(f, "Serde JSON Error: {}", e), GeoffreyDBError::SerdeJsonError(e) => write!(f, "Serde JSON Error: {}", e),
GeoffreyDBError::NotUnique => write!(f, "Entry is not unique."), GeoffreyDBError::NotUnique => write!(f, "Entry is not unique."),
GeoffreyDBError::NotFound => write!(f, "Entry was not found."),
} }
} }
} }
@ -30,3 +34,14 @@ impl From<serde_json::Error> for GeoffreyDBError {
GeoffreyDBError::SerdeJsonError(e) GeoffreyDBError::SerdeJsonError(e)
} }
} }
impl Into<GeoffreyAPIError> for GeoffreyDBError {
fn into(self) -> GeoffreyAPIError {
match self {
GeoffreyDBError::SledError(_) => GeoffreyAPIError::DatabaseError(self.to_string()),
GeoffreyDBError::SerdeJsonError(_) => GeoffreyAPIError::DatabaseError(self.to_string()),
GeoffreyDBError::NotUnique => GeoffreyAPIError::EntryNotUnique,
GeoffreyDBError::NotFound => GeoffreyAPIError::EntryNotFound
}
}
}

View File

@ -2,8 +2,9 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum GeoffreyAPIError { pub enum GeoffreyAPIError {
PlayerNotFound, PlayerNotRegistered,
LocationNotFound, EntryNotFound,
PermissionInsufficient, PermissionInsufficient,
EntryNotUnique,
DatabaseError(String), DatabaseError(String),
} }