Skip to main content

graphile_worker/runner/
errors.rs

1use std::fmt::{self, Debug, Display};
2
3use crate::errors::GraphileWorkerError;
4use graphile_worker_crontab_runner::ScheduleCronJobError;
5use graphile_worker_runtime as runtime;
6use thiserror::Error;
7
8/// Errors that can occur during worker runtime.
9///
10/// These errors represent various failure scenarios that can happen
11/// while the worker is running and processing jobs.
12#[derive(Error, Debug)]
13pub enum WorkerRuntimeError {
14    /// An error occurred while processing or releasing a job
15    #[error("Unexpected error occurred while processing job : '{0}'")]
16    ProcessJob(#[from] ProcessJobError),
17    #[error("Worker task failed : '{0}'")]
18    WorkerTask(#[from] runtime::JoinError),
19    /// Failed to listen to PostgreSQL notifications for new jobs
20    #[error("Failed to listen to postgres notifications : '{0}'")]
21    PgListen(#[from] GraphileWorkerError),
22    /// An error occurred while scheduling or executing a cron job
23    #[error("Error occurred while trying to schedule cron job : {0}")]
24    Crontab(#[from] ScheduleCronJobError),
25}
26
27/// Errors that can occur while processing a job.
28#[derive(Error, Debug)]
29pub enum ProcessJobError {
30    /// Error occurred when trying to complete or fail a job after processing
31    #[error("An error occurred while releasing a job : '{0}'")]
32    ReleaseJobError(#[from] ReleaseJobError),
33    /// Error occurred when trying to fetch a job from the database
34    #[error("An error occurred while fetching a job to run : '{0}'")]
35    GetJobError(#[from] GraphileWorkerError),
36}
37
38/// Errors that can occur during the execution of a job's task handler.
39#[derive(Error, Debug)]
40pub(super) enum RunJobError {
41    /// No task identifier was found for the given task ID
42    #[error("Cannot find any task identifier for given task id '{0}'. This is probably a bug !")]
43    IdentifierNotFound(i32),
44    /// No task handler function was registered for the given task identifier
45    #[error("Cannot find any task fn for given task identifier '{0}'. This is probably a bug !")]
46    FnNotFound(String),
47    /// The task handler panicked during execution
48    #[error("Task failed execution to complete : {0}")]
49    TaskPanic(String),
50    /// The task handler returned an error string
51    #[error("Task returned the following error : {0}")]
52    TaskError(String),
53    /// The batch task handler returned partial failures with a replacement payload
54    #[error("Task returned the following error : {message}")]
55    TaskErrorWithReplacement {
56        message: String,
57        replacement_payload: Redacted<serde_json::Value>,
58    },
59    /// The task was aborted due to a shutdown signal
60    #[error("Task was aborted by shutdown signal")]
61    TaskAborted,
62}
63
64pub(super) struct Redacted<T>(T);
65
66impl<T> Redacted<T> {
67    pub(super) fn new(value: T) -> Self {
68        Self(value)
69    }
70
71    fn get(&self) -> &T {
72        &self.0
73    }
74}
75
76impl<T> Debug for Redacted<T> {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        f.write_str("[redacted]")
79    }
80}
81
82impl<T> Display for Redacted<T> {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        f.write_str("[redacted]")
85    }
86}
87
88impl RunJobError {
89    pub(super) fn persisted_error(&self) -> String {
90        match self {
91            RunJobError::TaskErrorWithReplacement { message, .. } => {
92                format!("TaskError({message:?})")
93            }
94            _ => format!("{self:?}"),
95        }
96    }
97
98    pub(super) fn replacement_payload(&self) -> Option<&serde_json::Value> {
99        match self {
100            RunJobError::TaskErrorWithReplacement {
101                replacement_payload,
102                ..
103            } => Some(replacement_payload.get()),
104            _ => None,
105        }
106    }
107}
108
109/// Error that occurs when trying to mark a job as completed or failed.
110#[derive(Error, Debug)]
111#[error("Failed to release job '{job_id}'. {source}")]
112pub struct ReleaseJobError {
113    /// The ID of the job that could not be released
114    pub(super) job_id: i64,
115    /// The underlying error that caused the release operation to fail
116    #[source]
117    pub(super) source: GraphileWorkerError,
118}