Skip to content

Commit

Permalink
Handling Errors in a proper trait, and passing it up the stack
Browse files Browse the repository at this point in the history
  • Loading branch information
oestradiol committed Feb 25, 2024
1 parent 823f3d7 commit 5e20ce4
Show file tree
Hide file tree
Showing 31 changed files with 406 additions and 257 deletions.
8 changes: 4 additions & 4 deletions src/business/repositories/deployments/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ pub async fn delete(name: String) -> Result<(), VoyagerError> {
}

impl VoyagerError {
pub fn delete_mongo(e: Error, name: &str) -> Self {
fn delete_mongo(e: Error, name: &str) -> Self {
let message = format!("Failed to delete deployment named '{name}'! Error:{e}");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::INTERNAL_SERVER_ERROR,
source: Some(e),
}
}

pub fn delete(name: &str) -> Self {
fn delete(name: &str) -> Self {
let message = format!("Failed to find deployment named '{name}'!");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::NOT_FOUND,
source: None,
Expand Down
8 changes: 4 additions & 4 deletions src/business/repositories/deployments/find_by_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ pub async fn find_by_host(host: String) -> Result<Deployment, VoyagerError> {
}

impl VoyagerError {
pub fn find_mongo_host(e: Error, host: &str) -> Self {
fn find_mongo_host(e: Error, host: &str) -> Self {
let message = format!("Failed to find deployment by host '{host}'! Error:{e}");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::INTERNAL_SERVER_ERROR,
source: Some(e),
}
}

pub fn find_null_host(host: &str) -> Self {
fn find_null_host(host: &str) -> Self {
let message = format!("Failed to find deployment by host '{host}'!");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::NOT_FOUND,
source: None,
Expand Down
8 changes: 4 additions & 4 deletions src/business/repositories/deployments/find_by_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ pub async fn find_by_id(id: String) -> Result<Deployment, VoyagerError> {
}

impl VoyagerError {
pub fn find_mongo_id(e: Error, id: &str) -> Self {
fn find_mongo_id(e: Error, id: &str) -> Self {
let message = format!("Failed to find deployment by id '{id}'! Error:{e}");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::INTERNAL_SERVER_ERROR,
source: Some(e),
}
}

pub fn find_null_id(id: &str) -> Self {
fn find_null_id(id: &str) -> Self {
let message = format!("Failed to find deployment by id '{id}'!");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::NOT_FOUND,
source: None,
Expand Down
8 changes: 4 additions & 4 deletions src/business/repositories/deployments/find_by_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ pub async fn find_by_name(name: String) -> Result<Deployment, VoyagerError> {
}

impl VoyagerError {
pub fn find_mongo_name(e: Error, name: &str) -> Self {
fn find_mongo_name(e: Error, name: &str) -> Self {
let message = format!("Failed to find deployment named '{name}'! Error:{e}");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::INTERNAL_SERVER_ERROR,
source: Some(e),
}
}

pub fn find_null_name(name: &str) -> Self {
fn find_null_name(name: &str) -> Self {
let message = format!("Failed to find deployment named '{name}'!");

event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::NOT_FOUND,
source: None,
Expand Down
4 changes: 2 additions & 2 deletions src/business/repositories/deployments/retrieve_all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ pub async fn retrieve_all(
}

impl VoyagerError {
pub fn retrieve_all(e: Error) -> Self {
fn retrieve_all(e: Error) -> Self {
let message = format!("Failed to retrieve deployments! Error: {e}");
event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::INTERNAL_SERVER_ERROR,
source: Some(e),
Expand Down
4 changes: 2 additions & 2 deletions src/business/repositories/deployments/save.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ pub async fn save(deployment: Deployment) -> Result<Bson, VoyagerError> {
}

impl VoyagerError {
pub fn save(e: Error) -> Self {
fn save(e: Error) -> Self {
let message = format!("Failed to save deployment! Error: {e}");
event!(Level::ERROR, message);
VoyagerError {
Self {
message,
status_code: StatusCode::INTERNAL_SERVER_ERROR,
source: Some(e),
Expand Down
18 changes: 15 additions & 3 deletions src/business/services/deployments/delete.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use axum::http::StatusCode;
use tracing::{event, Level};

use crate::{
Expand All @@ -24,8 +25,7 @@ async fn delete(deployment: Deployment) -> Result<(), VoyagerError> {
let name = deployment.container_name;

if is_container_running(name.clone()).await? {
event!(Level::ERROR, "Tried to delete container that is running");
return None;
return Err(VoyagerError::delete_running());
}

delete_image(name.clone()).await?;
Expand All @@ -37,11 +37,23 @@ async fn delete(deployment: Deployment) -> Result<(), VoyagerError> {

// TODO: notify user via email

Some(())
Ok(())
};

SERVICES_RUNTIME
.spawn_handled("services::deployments::delete", future)
.await
.and_then(|f| f)
}

impl VoyagerError {
fn delete_running() -> Self {
let message = "Tried to delete container that is running";
event!(Level::ERROR, message);
Self {
message: message.to_string(),
status_code: StatusCode::BAD_REQUEST,
source: None,
}
}
}
6 changes: 3 additions & 3 deletions src/business/services/deployments/get.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::types::model::deployment::Deployment;
use crate::business::repositories;
use crate::types::model::deployment::Deployment;
use crate::types::other::voyager_error::VoyagerError;


pub async fn get(id: String) -> Option<Deployment> {
pub async fn get(id: String) -> Result<Deployment, VoyagerError> {
repositories::deployments::find_by_id(id).await
}
10 changes: 4 additions & 6 deletions src/business/services/deployments/get_logs.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use crate::business::repositories;
use crate::modules::docker;
use crate::types::other::voyager_error::VoyagerError;

pub async fn get_logs(id: String) -> Result<Vec<String>, VoyagerError> {
let deployment = repositories::deployments::find_by_id(id).await?;

pub async fn get_logs(id: String) -> Option<Vec<String>> {
if let Some(deployment) = repositories::deployments::find_by_id(id).await {
return docker::get_logs(&deployment.container_name).await
}

None
docker::get_logs(&deployment.container_name).await
}
11 changes: 8 additions & 3 deletions src/business/services/deployments/list.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use crate::{business::repositories, types::model::deployment::Deployment};
use crate::{
business::repositories,
types::{model::deployment::Deployment, other::voyager_error::VoyagerError},
};


pub async fn list(repo_url: Option<String>, branch: Option<String>) -> Option<Vec<Deployment>> {
pub async fn list(
repo_url: Option<String>,
branch: Option<String>,
) -> Result<Vec<Deployment>, VoyagerError> {
repositories::deployments::retrieve_all(repo_url, branch).await
}
34 changes: 19 additions & 15 deletions src/business/services/deployments/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ use crate::configs::environment::HOST_IP;
use crate::modules::discord::send_deployment_message;
use crate::modules::{cloudflare, traefik};
use crate::types::model::deployment;
use crate::types::other::voyager_error::VoyagerError;
use crate::utils::get_free_port;
use crate::{business::repositories::deployments, modules::docker};
use axum::http::StatusCode;
use mongodb::bson::Bson;
use tracing::{event, Level};
use uuid::Uuid;
Expand All @@ -27,23 +29,13 @@ pub async fn new(
directory: &str,
repo_url: &str,
branch: &str,
) -> Option<Result<Bson, Vec<Error>>> {
) -> Result<Bson, VoyagerError> {
event!(Level::INFO, "Creating deployment with host {host}, Dockerfile {:?}, mode {mode}, directory {directory}, repo_url {repo_url}, branch {branch}", dockerfile);

let cloudflare_result = cloudflare::add_dns_record(host, &HOST_IP, mode).await?;
let dns_record_id = cloudflare::add_dns_record(host, &HOST_IP, mode).await?;

let dns_record_id = match cloudflare_result {
Ok(id) => id,
Err(errs) => return Some(Err(errs)),
};

let dockerfile_contents = match fs::read_to_string(dockerfile) {
Ok(contents) => contents,
Err(err) => {
event!(Level::ERROR, "Failed to read Dockerfile contents: {}", err);
return None;
}
};
let dockerfile_contents =
fs::read_to_string(dockerfile).map_err(|e| VoyagerError::dockerfile_read(Box::new(e)))?;

let internal_port = docker::find_internal_port(dockerfile_contents.as_str())?;
let free_port = get_free_port()?;
Expand Down Expand Up @@ -74,5 +66,17 @@ pub async fn new(

// TODO: notify user via email

Some(Ok(db_id))
Ok(db_id)
}

impl VoyagerError {
fn dockerfile_read(e: Error) -> Self {
let message = format!("Failed to read Dockerfile contents: {e}");
event!(Level::ERROR, message);
Self {
message,
status_code: StatusCode::INTERNAL_SERVER_ERROR,
source: Some(e),
}
}
}
50 changes: 25 additions & 25 deletions src/controllers/deployments/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,32 @@ use crate::{
use crate::types::to_json_str;

pub async fn get(Query(queries): Query<HashMap<String, String>>) -> impl IntoResponse {
let id_opt = queries.get("deploymentId").cloned();
// let id_opt = queries.get("deploymentId").cloned();

let inner = || async {
let Some(id) = id_opt else {
return Some((
StatusCode::BAD_REQUEST,
to_json_str(&GetDeployment { deployment: None })?,
));
};
// let inner = || async {
// let Some(id) = id_opt else {
// return Some((
// StatusCode::BAD_REQUEST,
// to_json_str(&GetDeployment { deployment: None })?,
// ));
// };

match deployments::get(id).await {
Some(deployment) => Some((
StatusCode::OK,
to_json_str(&GetDeployment {
deployment: Some(deployment),
})?,
)),
None => Some((
StatusCode::NOT_FOUND,
to_json_str(&GetDeployment { deployment: None })?,
)),
}
};
// match deployments::get(id).await {
// Some(deployment) => Some((
// StatusCode::OK,
// to_json_str(&GetDeployment {
// deployment: Some(deployment),
// })?,
// )),
// None => Some((
// StatusCode::NOT_FOUND,
// to_json_str(&GetDeployment { deployment: None })?,
// )),
// }
// };

inner().await.unwrap_or((
StatusCode::INTERNAL_SERVER_ERROR,
"Internal Server Error".to_string(),
))
// inner().await.unwrap_or((
// StatusCode::INTERNAL_SERVER_ERROR,
// "Internal Server Error".to_string(),
// ))
}
Loading

0 comments on commit 5e20ce4

Please sign in to comment.