Use thiserror.

This commit is contained in:
LukeMathWalker 2021-05-10 09:57:49 +01:00
parent f0aee87a00
commit c6e88e8f8e
3 changed files with 15 additions and 63 deletions

1
Cargo.lock generated
View file

@ -2685,6 +2685,7 @@ dependencies = [
"serde_json",
"sha2",
"sqlx",
"thiserror",
"tokio",
"tracing",
"tracing-actix-web",

View file

@ -28,6 +28,7 @@ tracing-futures = "0.2.4"
tracing-subscriber = { version = "0.2.12", features = ["registry", "env-filter"] }
tracing-bunyan-formatter = "0.2.2"
tracing-log = "0.1.1"
thiserror = "1.0.24"
serde-aux = "1.0.1"
unicode-segmentation = "1.7.1"
validator = "0.12.0"

View file

@ -26,56 +26,20 @@ impl TryInto<NewSubscriber> for FormData {
}
}
#[derive(thiserror::Error)]
pub enum SubscribeError {
#[error("{0}")]
ValidationError(String),
PoolError(sqlx::Error),
InsertSubscriberError(sqlx::Error),
StoreTokenError(StoreTokenError),
TransactionCommitError(sqlx::Error),
SendEmailError(reqwest::Error),
}
impl From<reqwest::Error> for SubscribeError {
fn from(e: reqwest::Error) -> Self {
Self::SendEmailError(e)
}
}
impl From<StoreTokenError> for SubscribeError {
fn from(e: StoreTokenError) -> Self {
Self::StoreTokenError(e)
}
}
impl From<String> for SubscribeError {
fn from(e: String) -> Self {
Self::ValidationError(e)
}
}
impl std::fmt::Display for SubscribeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SubscribeError::ValidationError(e) => write!(f, "{}", e),
SubscribeError::PoolError(_) => {
write!(f, "Failed to acquire a Postgres connection from the pool")
}
SubscribeError::InsertSubscriberError(_) => {
write!(f, "Failed to insert new subscriber in the database.")
}
SubscribeError::StoreTokenError(_) => write!(
f,
"Failed to store the confirmation token for a new subscriber."
),
SubscribeError::TransactionCommitError(_) => {
write!(
f,
"Failed to commit SQL transaction to store a new subscriber."
)
}
SubscribeError::SendEmailError(_) => write!(f, "Failed to send a confirmation email."),
}
}
#[error("Failed to acquire a Postgres connection from the pool")]
PoolError(#[source] sqlx::Error),
#[error("Failed to insert new subscriber in the database.")]
InsertSubscriberError(#[source] sqlx::Error),
#[error("Failed to store the confirmation token for a new subscriber.")]
StoreTokenError(#[from] StoreTokenError),
#[error("Failed to commit SQL transaction to store a new subscriber.")]
TransactionCommitError(#[source] sqlx::Error),
#[error("Failed to send a confirmation email.")]
SendEmailError(#[from] reqwest::Error),
}
impl std::fmt::Debug for SubscribeError {
@ -84,20 +48,6 @@ impl std::fmt::Debug for SubscribeError {
}
}
impl std::error::Error for SubscribeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
// &str does not implement `Error` - we consider it the root cause
SubscribeError::ValidationError(_) => None,
SubscribeError::PoolError(e) => Some(e),
SubscribeError::InsertSubscriberError(e) => Some(e),
SubscribeError::StoreTokenError(e) => Some(e),
SubscribeError::TransactionCommitError(e) => Some(e),
SubscribeError::SendEmailError(e) => Some(e),
}
}
}
impl ResponseError for SubscribeError {
fn status_code(&self) -> StatusCode {
match self {
@ -125,7 +75,7 @@ pub async fn subscribe(
email_client: web::Data<EmailClient>,
base_url: web::Data<ApplicationBaseUrl>,
) -> Result<HttpResponse, SubscribeError> {
let new_subscriber = form.0.try_into()?;
let new_subscriber = form.0.try_into().map_err(SubscribeError::ValidationError)?;
let mut transaction = pool.begin().await.map_err(SubscribeError::PoolError)?;
let subscriber_id = insert_subscriber(&mut transaction, &new_subscriber)
.await