Skip to content
This repository has been archived by the owner on Mar 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request #58 from golemcloud/nice-error-messages
Browse files Browse the repository at this point in the history
Nicer error messages
  • Loading branch information
vigoo authored Feb 4, 2024
2 parents 7d1667c + 87d1011 commit 034cc08
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 32 deletions.
165 changes: 136 additions & 29 deletions src/clients/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
use golem_client::api::{TemplateError, WorkerError};
use golem_client::model::{
GolemError, GolemErrorFailedToResumeWorker, GolemErrorGetLatestVersionOfTemplateFailed,
GolemErrorInterrupted, GolemErrorInvalidRequest, GolemErrorInvalidShardId,
GolemErrorPromiseAlreadyCompleted, GolemErrorPromiseDropped, GolemErrorPromiseNotFound,
GolemErrorRuntimeError, GolemErrorTemplateDownloadFailed, GolemErrorTemplateParseFailed,
GolemErrorUnexpectedOplogEntry, GolemErrorUnknown, GolemErrorValueMismatch,
GolemErrorWorkerAlreadyExists, GolemErrorWorkerCreationFailed, GolemErrorWorkerNotFound,
PromiseId, WorkerId,
};
use itertools::Itertools;

pub trait ResponseContentErrorMapper {
fn map(self) -> String;
Expand All @@ -7,43 +17,140 @@ pub trait ResponseContentErrorMapper {
impl ResponseContentErrorMapper for TemplateError {
fn map(self) -> String {
match self {
TemplateError::Error400(errors) => {
format!("BadRequest: {errors:?}")
}
TemplateError::Error401(error) => {
format!("Unauthorized: {error:?}")
}
TemplateError::Error403(error) => {
format!("Forbidden: {error:?}")
}
TemplateError::Error404(error) => {
format!("NotFound: {error:?}")
}
TemplateError::Error409(error) => {
format!("Conflict: {error:?}")
}
TemplateError::Error500(error) => {
format!("InternalError: {error:?}")
}
TemplateError::Error400(errors) => errors.errors.iter().join(", "),
TemplateError::Error401(error) => error.error,
TemplateError::Error403(error) => error.error,
TemplateError::Error404(error) => error.error,
TemplateError::Error409(error) => error.error,
TemplateError::Error500(error) => error.error,
}
}
}

impl ResponseContentErrorMapper for WorkerError {
fn map(self) -> String {
match self {
WorkerError::Error400(errors) => {
format!("BadRequest: {errors:?}")
}
WorkerError::Error404(error) => {
format!("NotFound: {error:?}")
}
WorkerError::Error409(error) => {
format!("Conflict: {error:?}")
}
WorkerError::Error500(error) => {
format!("InternalError: {error:?}")
WorkerError::Error400(errors) => errors.errors.iter().join(", "),
WorkerError::Error404(error) => error.error,
WorkerError::Error409(error) => error.error,
WorkerError::Error500(error) => display_golem_error(error.golem_error),
}
}
}

fn display_golem_error(error: golem_client::model::GolemError) -> String {
match error {
GolemError::InvalidRequest(GolemErrorInvalidRequest { details }) => {
format!("Invalid request: {details}")
}
GolemError::WorkerAlreadyExists(GolemErrorWorkerAlreadyExists { worker_id }) => {
format!("Worker already exists: {}", display_worker_id(worker_id))
}
GolemError::WorkerNotFound(GolemErrorWorkerNotFound { worker_id }) => {
format!("Worker not found: {}", display_worker_id(worker_id))
}
GolemError::WorkerCreationFailed(GolemErrorWorkerCreationFailed { worker_id, details }) => {
format!(
"Failed to create worker {}: {}",
display_worker_id(worker_id),
details
)
}
GolemError::FailedToResumeWorker(GolemErrorFailedToResumeWorker { worker_id }) => {
format!("Failed to resume worker: {}", display_worker_id(worker_id))
}
GolemError::TemplateDownloadFailed(GolemErrorTemplateDownloadFailed {
template_id,
reason,
}) => {
format!(
"Failed to download template {}#{}: {}",
template_id.template_id, template_id.version, reason
)
}
GolemError::TemplateParseFailed(GolemErrorTemplateParseFailed {
template_id,
reason,
}) => {
format!(
"Failed to parse template {}#{}: {}",
template_id.template_id, template_id.version, reason
)
}
GolemError::GetLatestVersionOfTemplateFailed(
GolemErrorGetLatestVersionOfTemplateFailed {
template_id,
reason,
},
) => {
format!(
"Failed to get latest version of template {}: {}",
template_id, reason
)
}
GolemError::PromiseNotFound(GolemErrorPromiseNotFound { promise_id }) => {
format!("Promise not found: {}", display_promise_id(promise_id))
}
GolemError::PromiseDropped(GolemErrorPromiseDropped { promise_id }) => {
format!("Promise dropped: {}", display_promise_id(promise_id))
}
GolemError::PromiseAlreadyCompleted(GolemErrorPromiseAlreadyCompleted { promise_id }) => {
format!(
"Promise already completed: {}",
display_promise_id(promise_id)
)
}
GolemError::Interrupted(GolemErrorInterrupted {
recover_immediately,
}) => {
if recover_immediately {
"Simulated crash".to_string()
} else {
"Worker interrupted".to_string()
}
}
GolemError::ParamTypeMismatch(_) => "Parameter type mismatch".to_string(),
GolemError::NoValueInMessage(_) => "No value in message".to_string(),
GolemError::ValueMismatch(GolemErrorValueMismatch { details }) => {
format!("Parameter value mismatch: {}", details)
}
GolemError::UnexpectedOplogEntry(GolemErrorUnexpectedOplogEntry { expected, got }) => {
format!("Unexpected oplog entry: expected {}, got {}", expected, got)
}
GolemError::RuntimeError(GolemErrorRuntimeError { details }) => {
format!("Runtime error: {}", details)
}
GolemError::InvalidShardId(GolemErrorInvalidShardId {
shard_id,
shard_ids,
}) => {
format!(
"Invalid shard id: {} not in [{}]",
shard_id.value,
shard_ids.iter().map(|id| id.value).join(", ")
)
}
GolemError::PreviousInvocationFailed(_) => {
"The previously invoked function failed".to_string()
}
GolemError::PreviousInvocationExited(_) => {
"The previously invoked function exited".to_string()
}
GolemError::Unknown(GolemErrorUnknown { details }) => {
format!("Unknown error: {}", details)
}
GolemError::InvalidAccount(_) => "Invalid account".to_string(),
}
}

fn display_worker_id(worker_id: WorkerId) -> String {
format!("{}/{}", worker_id.template_id, worker_id.worker_name)
}

fn display_promise_id(promise_id: PromiseId) -> String {
format!(
"{}/{}",
display_worker_id(promise_id.worker_id),
promise_id.oplog_idx
)
}
6 changes: 3 additions & 3 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub struct GolemError(pub String);

impl From<reqwest::Error> for GolemError {
fn from(error: reqwest::Error) -> Self {
GolemError(format!("Unexpected reqwest error: {error}"))
GolemError(format!("Unexpected client error: {error}"))
}
}

Expand All @@ -57,11 +57,11 @@ impl<T: crate::clients::errors::ResponseContentErrorMapper> From<golem_client::E
match value {
golem_client::Error::Reqwest(error) => GolemError::from(error),
golem_client::Error::Serde(error) => {
GolemError(format!("Unexpected serde error: {error}"))
GolemError(format!("Unexpected serialization error: {error}"))
}
golem_client::Error::Item(data) => {
let error_str = crate::clients::errors::ResponseContentErrorMapper::map(data);
GolemError(format!("Response error: {error_str}"))
GolemError(error_str)
}
golem_client::Error::Unexpected { code, data } => {
match String::from_utf8(Vec::from(data)) {
Expand Down

0 comments on commit 034cc08

Please sign in to comment.