Skip to content

Commit

Permalink
refactor: Simplify error types
Browse files Browse the repository at this point in the history
  • Loading branch information
caleb-leinz committed Sep 6, 2024
1 parent d0e26b6 commit 2f8b228
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 101 deletions.
6 changes: 2 additions & 4 deletions examples/fetch_accounts.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use freedom_api::prelude::*;
use freedom_config::Config;
use futures::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::from_env()?;
let client = Client::from_config(config);
let client = Client::from_env()?;
let accounts = client
.get_accounts()
.filter_map(|result| async move { result.ok() })
.map(|container| container.into_inner())
.collect::<Vec<_>>()
.await;

println!("{:?}", accounts);
println!("{:#?}", accounts);

Ok(())
}
18 changes: 7 additions & 11 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ use freedom_models::{
utils::Embedded,
};
use reqwest::{Response, StatusCode};
use serde::{de::DeserializeOwned, Serialize};
use serde::de::DeserializeOwned;
use serde_json::Value;
use time::{format_description::well_known::Iso8601, OffsetDateTime};
use url::Url;

use futures_core::Stream;

use crate::{error::Error, prelude::RuntimeError};
use crate::error::Error;

pub(crate) mod post;

Expand Down Expand Up @@ -1185,11 +1185,9 @@ pub trait FreedomApi: Send + Sync {

value
.get("token")
.ok_or(RuntimeError::Response(String::from("Missing token field")))?
.ok_or(Error::Response(String::from("Missing token field")))?
.as_str()
.ok_or(RuntimeError::Response(String::from(
"Invalid type for token",
)))
.ok_or(Error::Response(String::from("Invalid type for token")))
.map(|s| s.to_owned())
.map_err(From::from)
}
Expand All @@ -1210,11 +1208,9 @@ pub trait FreedomApi: Send + Sync {

value
.get("token")
.ok_or(RuntimeError::Response(String::from("Missing token field")))?
.ok_or(Error::Response(String::from("Missing token field")))?
.as_str()
.ok_or(RuntimeError::Response(String::from(
"Invalid type for token",
)))
.ok_or(Error::Response(String::from("Invalid type for token")))
.map(|s| s.to_owned())
.map_err(From::from)
}
Expand All @@ -1231,7 +1227,7 @@ pub trait FreedomApi: Send + Sync {

fn error_on_non_success(status: &StatusCode) -> Result<(), Error> {
if !status.is_success() {
return Err(Error::Runtime(RuntimeError::Response(status.to_string())));
return Err(Error::Response(status.to_string()));
}

Ok(())
Expand Down
4 changes: 1 addition & 3 deletions src/caching_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ impl FreedomApi for CachingClient {

#[tracing::instrument]
async fn get(&self, url: Url) -> Result<(Bytes, StatusCode), Error> {
use crate::error::RuntimeError;

// This is a rather cheap clone. Something like 50 bytes. This is necessary since we will
// be passing this to the tokio executor which has lifetime requirements of `'static`
let client = &self.inner;
Expand All @@ -59,7 +57,7 @@ impl FreedomApi for CachingClient {
let (body, status) = client.get(url).await?;

if !status.is_success() {
return Err(Error::Runtime(RuntimeError::Response(status.to_string())));
return Err(Error::Response(status.to_string()));
}

Ok((body, status))
Expand Down
81 changes: 10 additions & 71 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,63 +1,8 @@
use serde::{Deserialize, Serialize};
use serde::Serialize;

/// The combined error type for the client builder and for API errors
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq, Serialize)]
pub enum Error {
#[error("Builder error: {0}")]
Builder(BuilderError),

#[error("Runtime error: {0}")]
Runtime(RuntimeError),
}

impl Error {
/// Shorthand for creating a runtime pagination error
pub(crate) fn pag_item(s: String) -> Self {
From::from(RuntimeError::PaginationItemDeserialization(s))
}
}

#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq, Deserialize, Serialize)]
pub enum BuilderError {
#[error("Failed to build client from environment variables, {0} is missing.")]
MissingEnv(String),

#[error("Failed to build client from the provided environment file, could not find {0}")]
InvalidEnvPath(String),

#[error("Failed to build client, no username was provided")]
MissingUsername,

#[error("Failed to build client, no password was provided")]
MissingPassword,

#[error("Failed to build request, need task type")]
TaskType,

#[error("Failed to build request, need account ID")]
AccountId,

#[error("Failed to build request, need minimum duration")]
Duration,

#[error("Failed to build request, need target date")]
TargetDate,

#[error("Failed to build request, configuration ID")]
ConfigurationId,

#[error("Failed to build request, need site ID")]
SiteId,

#[error("Failed to build request, need satellite ID")]
SatelliteId,

#[error("Failed to build client, underlying client failed to build with: {0}")]
ClientBuild(String),
}

#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq, Deserialize, Serialize)]
pub enum RuntimeError {
#[error("Failed to get valid response from server: {0}")]
Response(String),

Expand Down Expand Up @@ -88,45 +33,39 @@ pub enum RuntimeError {
InvalidId,
}

impl From<RuntimeError> for Error {
fn from(value: RuntimeError) -> Self {
Error::Runtime(value)
}
}

impl From<BuilderError> for Error {
fn from(value: BuilderError) -> Self {
Error::Builder(value)
impl Error {
/// Shorthand for creating a runtime pagination error
pub(crate) fn pag_item(s: String) -> Self {
Self::PaginationItemDeserialization(s)
}
}

impl From<reqwest::Error> for Error {
fn from(value: reqwest::Error) -> Self {
println!("{:?}", value);
Error::Runtime(RuntimeError::Response(value.to_string()))
Error::Response(value.to_string())
}
}

impl From<serde_json::Error> for Error {
fn from(value: serde_json::Error) -> Self {
Error::Runtime(RuntimeError::Deserialization(value.to_string()))
Error::Deserialization(value.to_string())
}
}

impl From<time::error::Error> for Error {
fn from(value: time::error::Error) -> Self {
Error::Runtime(RuntimeError::TimeFormatError(value.to_string()))
Error::TimeFormatError(value.to_string())
}
}

impl From<time::error::Format> for Error {
fn from(value: time::error::Format) -> Self {
Error::Runtime(RuntimeError::TimeFormatError(value.to_string()))
Error::TimeFormatError(value.to_string())
}
}

impl From<url::ParseError> for Error {
fn from(value: url::ParseError) -> Self {
Self::Runtime(RuntimeError::InvalidUri(value.to_string()))
Self::InvalidUri(value.to_string())
}
}
12 changes: 4 additions & 8 deletions src/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,15 @@ pub use {
fn get_id(reference: &'static str, links: &HashMap<String, url::Url>) -> Result<i32, crate::Error> {
let url = links
.get(reference)
.ok_or(crate::error::RuntimeError::MissingUri(reference))?;
.ok_or(crate::error::Error::MissingUri(reference))?;

let id_str = url
.path_segments()
.ok_or(crate::error::RuntimeError::InvalidUri(
"Missing Path".into(),
))?
.ok_or(crate::error::Error::InvalidUri("Missing Path".into()))?
.last()
.unwrap();

id_str
.parse()
.map_err(|_| From::from(crate::error::RuntimeError::InvalidId))
id_str.parse().map_err(|_| crate::error::Error::InvalidId)
}

async fn get_item<T, C>(
Expand All @@ -59,7 +55,7 @@ where
{
let uri = links
.get(reference)
.ok_or(crate::error::RuntimeError::MissingUri(reference))?
.ok_or(crate::error::Error::MissingUri(reference))?
.clone();

client.get_json_map(uri).await
Expand Down
5 changes: 1 addition & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ pub mod prelude {
#[cfg(feature = "caching")]
pub use crate::caching_client::CachingClient;
pub use crate::extensions::*;
pub use crate::{
client::Client,
error::{BuilderError, Error, RuntimeError},
};
pub use crate::{client::Client, error::Error};
pub use freedom_models::{
account::*, satellite::*, satellite_configuration::*, site::*, task::*, user::*,
};
Expand Down

0 comments on commit 2f8b228

Please sign in to comment.