diff --git a/services/backup/Cargo.lock b/services/backup/Cargo.lock --- a/services/backup/Cargo.lock +++ b/services/backup/Cargo.lock @@ -756,6 +756,7 @@ "chrono", "clap", "comm-services-lib", + "derive_more", "once_cell", "rand", "reqwest", diff --git a/services/backup/Cargo.toml b/services/backup/Cargo.toml --- a/services/backup/Cargo.toml +++ b/services/backup/Cargo.toml @@ -14,7 +14,10 @@ aws-types = "0.55" chrono = "0.4" clap = { version = "4.0", features = ["derive", "env"] } -comm-services-lib = { path = "../comm-services-lib", features = ["http", "blob-client"] } +comm-services-lib = { path = "../comm-services-lib", features = [ + "http", + "blob-client", +] } once_cell = "1.17" rand = "0.8.5" tokio = { version = "1.24", features = ["rt-multi-thread", "macros"] } @@ -26,6 +29,7 @@ actix-web = "4.3" tracing-actix-web = "0.7.3" reqwest = "0.11.18" +derive_more = "0.99" [build-dependencies] tonic-build = "0.8" diff --git a/services/backup/src/error.rs b/services/backup/src/error.rs new file mode 100644 --- /dev/null +++ b/services/backup/src/error.rs @@ -0,0 +1,64 @@ +use actix_web::{ + error::{ + ErrorBadRequest, ErrorConflict, ErrorInternalServerError, + ErrorServiceUnavailable, HttpError, + }, + HttpResponse, ResponseError, +}; +use comm_services_lib::blob::client::BlobServiceError; +use reqwest::StatusCode; +use tracing::{error, trace, warn}; + +#[derive( + Debug, derive_more::Display, derive_more::From, derive_more::Error, +)] +pub enum BackupError { + BlobError(BlobServiceError), +} + +impl From<&BackupError> for actix_web::Error { + fn from(value: &BackupError) -> Self { + trace!("Handling backup service error: {value}"); + match value { + BackupError::BlobError( + err @ (BlobServiceError::ClientError(_) + | BlobServiceError::UnexpectedHttpStatus(_) + | BlobServiceError::ServerError + | BlobServiceError::UnexpectedError), + ) => { + warn!("Transient blob error occurred: {err}"); + ErrorServiceUnavailable("please retry") + } + BackupError::BlobError(BlobServiceError::AlreadyExists) => { + ErrorConflict("blob already exists") + } + BackupError::BlobError(BlobServiceError::InvalidArguments) => { + ErrorBadRequest("bad request") + } + BackupError::BlobError( + err @ (BlobServiceError::URLError(_) | BlobServiceError::NotFound), + ) => { + error!("Unexpected blob error: {err}"); + ErrorInternalServerError("server error") + } + } + } +} + +impl From for HttpError { + fn from(value: BackupError) -> Self { + value.into() + } +} + +impl ResponseError for BackupError { + fn error_response(&self) -> HttpResponse { + actix_web::Error::from(self).error_response() + } + + fn status_code(&self) -> StatusCode { + actix_web::Error::from(self) + .as_response_error() + .status_code() + } +} diff --git a/services/backup/src/main.rs b/services/backup/src/main.rs --- a/services/backup/src/main.rs +++ b/services/backup/src/main.rs @@ -6,6 +6,7 @@ pub mod config; pub mod constants; pub mod database; +pub mod error; pub mod http; pub mod utils;