use std::fmt::{self, Debug, Display};
use crate::errors::GraphileWorkerError;
use graphile_worker_crontab_runner::ScheduleCronJobError;
use graphile_worker_runtime as runtime;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum WorkerRuntimeError {
#[error("Unexpected error occurred while processing job : '{0}'")]
ProcessJob(#[from] ProcessJobError),
#[error("Worker task failed : '{0}'")]
WorkerTask(#[from] runtime::JoinError),
#[error("Failed to listen to postgres notifications : '{0}'")]
PgListen(#[from] GraphileWorkerError),
#[error("Error occurred while trying to schedule cron job : {0}")]
Crontab(#[from] ScheduleCronJobError),
}
#[derive(Error, Debug)]
pub enum ProcessJobError {
#[error("An error occurred while releasing a job : '{0}'")]
ReleaseJobError(#[from] ReleaseJobError),
#[error("An error occurred while fetching a job to run : '{0}'")]
GetJobError(#[from] GraphileWorkerError),
}
#[derive(Error, Debug)]
pub(super) enum RunJobError {
#[error("Cannot find any task identifier for given task id '{0}'. This is probably a bug !")]
IdentifierNotFound(i32),
#[error("Cannot find any task fn for given task identifier '{0}'. This is probably a bug !")]
FnNotFound(String),
#[error("Task failed execution to complete : {0}")]
TaskPanic(String),
#[error("Task returned the following error : {0}")]
TaskError(String),
#[error("Task returned the following error : {message}")]
TaskErrorWithReplacement {
message: String,
replacement_payload: Redacted<serde_json::Value>,
},
#[error("Task was aborted by shutdown signal")]
TaskAborted,
}
pub(super) struct Redacted<T>(T);
impl<T> Redacted<T> {
pub(super) fn new(value: T) -> Self {
Self(value)
}
fn get(&self) -> &T {
&self.0
}
}
impl<T> Debug for Redacted<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("[redacted]")
}
}
impl<T> Display for Redacted<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("[redacted]")
}
}
impl RunJobError {
pub(super) fn persisted_error(&self) -> String {
match self {
RunJobError::TaskErrorWithReplacement { message, .. } => {
format!("TaskError({message:?})")
}
_ => format!("{self:?}"),
}
}
pub(super) fn replacement_payload(&self) -> Option<&serde_json::Value> {
match self {
RunJobError::TaskErrorWithReplacement {
replacement_payload,
..
} => Some(replacement_payload.get()),
_ => None,
}
}
}
#[derive(Error, Debug)]
#[error("Failed to release job '{job_id}'. {source}")]
pub struct ReleaseJobError {
pub(super) job_id: i64,
#[source]
pub(super) source: GraphileWorkerError,
}