1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
#![deny(missing_docs)]
//! # Background Jobs Core
//! _basic types and traits for implementing a background jobs processor_
//!
//! This crate shouldn't be depended on directly, except in the case of implementing a custom jobs
//! processor. For a default solution based on Actix and Sled, look at the `background-jobs` crate.
mod box_error;
mod catch_unwind;
mod job;
mod job_info;
mod processor_map;
mod storage;
mod unsend_job;
pub use crate::{
box_error::BoxError,
job::{new_job, new_scheduled_job, process, Job},
job_info::{JobInfo, NewJobInfo, ReturnJobInfo},
processor_map::{CachedProcessorMap, ProcessorMap},
storage::{memory_storage, Storage},
};
pub use unsend_job::{JoinError, UnsendJob, UnsendSpawner};
#[derive(Debug, thiserror::Error)]
/// The error type returned by the `process` method
pub enum JobError {
/// Some error occurred while processing the job
#[error("{0}")]
Processing(#[from] BoxError),
/// Creating a `Job` type from the provided `serde_json::Value` failed
#[error("Could not make JSON value from arguments")]
Json,
/// This job type was not registered for this client
#[error("This job type was not registered for the client")]
Unregistered,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
/// Indicate the state of a job after an attempted run
pub enum JobResult {
/// The job succeeded
Success,
/// The job failed
Failure,
/// The worker had no concept of this job
Unregistered,
/// The worker requesting this job closed
Unexecuted,
}
impl JobResult {
/// Indicate a successful job
pub const fn success() -> Self {
JobResult::Success
}
/// Indicate a failed job
pub const fn failure() -> Self {
JobResult::Failure
}
/// Indicate that the job was not registered for this worker
pub const fn unregistered() -> Self {
JobResult::Unregistered
}
/// Check if the job failed
pub const fn is_failure(self) -> bool {
matches!(self, JobResult::Failure)
}
/// Check if the job succeeded
pub const fn is_success(self) -> bool {
matches!(self, JobResult::Success)
}
/// Check if the job is missing it's processor
pub const fn is_unregistered(self) -> bool {
matches!(self, JobResult::Unregistered)
}
/// Check if the job was returned without an execution attempt
pub const fn is_unexecuted(self) -> bool {
matches!(self, JobResult::Unexecuted)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
/// Different styles for retrying jobs
pub enum Backoff {
/// Seconds between execution
///
/// For example, `Backoff::Linear(5)` will retry a failed job 5 seconds after the previous
/// attempt
Linear(usize),
/// Base for seconds between execution
///
/// For example, `Backoff::Exponential(2)` will retry a failed job 2 seconds after the first
/// failure, 4 seconds after the second failure, 8 seconds after the third failure, and 16
/// seconds after the fourth failure
Exponential(usize),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
/// How many times a job should be retried before giving up
pub enum MaxRetries {
/// Keep retrying forever
Infinite,
/// Put a limit on the number of retries
Count(usize),
}
impl MaxRetries {
fn compare(self, retry_count: u32) -> ShouldStop {
match self {
MaxRetries::Infinite => ShouldStop::Requeue,
MaxRetries::Count(count) => {
if (retry_count as usize) <= count {
ShouldStop::Requeue
} else {
ShouldStop::LimitReached
}
}
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// A type that represents whether a job should be requeued
pub enum ShouldStop {
/// The job has hit the maximum allowed number of retries, and should be failed permanently
LimitReached,
/// The job is allowed to be put back into the job queue
Requeue,
}
impl ShouldStop {
/// A boolean representation of this state
pub const fn should_requeue(&self) -> bool {
matches!(self, ShouldStop::Requeue)
}
}
impl From<serde_json::error::Error> for JobError {
fn from(_: serde_json::error::Error) -> Self {
JobError::Json
}
}