pub trait Job:
Serialize
+ DeserializeOwned
+ Send
+ Sync
+ 'static {
const NAME: &'static str;
const TRIES: u32 = 3;
const QUEUE: &'static str = "default";
const UNIQUE_FOR: Duration = _;
// Required method
fn handle<'life0, 'life1, 'async_trait>(
&'life0 self,
context: &'life1 JobContext,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided methods
fn backoff(attempt: u32) -> Duration { ... }
fn failed<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
context: &'life1 JobContext,
error: &'life2 Error,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn unique_id(&self) -> Option<String> { ... }
}Expand description
Work to be done later.
use rainier_queue::{Job, JobContext};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct SendWelcomeEmail {
user_id: u64,
}
#[async_trait::async_trait]
impl Job for SendWelcomeEmail {
const NAME: &'static str = "mail.welcome";
async fn handle(&self, _context: &JobContext) -> rainier_support::Result<()> {
println!("emailing user {}", self.user_id);
Ok(())
}
}Required Associated Constants§
Provided Associated Constants§
Sourceconst UNIQUE_FOR: Duration = _
const UNIQUE_FOR: Duration = _
How long the uniqueness lock is held if the job never finishes.
The safety net for a worker that dies mid-job: without it, one crash would block that job’s id forever. Set it longer than the job takes.
Required Methods§
Sourcefn handle<'life0, 'life1, 'async_trait>(
&'life0 self,
context: &'life1 JobContext,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn handle<'life0, 'life1, 'async_trait>(
&'life0 self,
context: &'life1 JobContext,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Do the work.
Returning Err releases the job for another attempt, until
TRIES is exhausted and it is marked failed.
Provided Methods§
Sourcefn backoff(attempt: u32) -> Duration
fn backoff(attempt: u32) -> Duration
How long to wait before retrying after attempt failures.
Exponential by default — 1s, 2s, 4s, … — because the usual reason a job fails is a dependency that is briefly unavailable, and retrying at full speed makes that worse.
Sourcefn failed<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
context: &'life1 JobContext,
error: &'life2 Error,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn failed<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
context: &'life1 JobContext,
error: &'life2 Error,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Called after the final attempt fails. For recording the failure somewhere the application will notice.
Sourcefn unique_id(&self) -> Option<String>
fn unique_id(&self) -> Option<String>
What makes two of these job “the same one”, or None for jobs that are
never duplicates.
Laravel’s ShouldBeUnique. Returning Some makes dispatch take an
atomic lock on this id, so a second dispatch
while the first is still pending is dropped rather than queued.
impl Job for RebuildSearchIndex {
const NAME: &'static str = "search.rebuild";
// One rebuild at a time, whatever asks for it.
fn unique_id(&self) -> Option<String> {
Some(String::new())
}
}
impl Job for SendInvoice {
const NAME: &'static str = "billing.invoice";
// One per invoice, but two different invoices are two jobs.
fn unique_id(&self) -> Option<String> {
Some(self.invoice_id.to_string())
}
}The lock key is NAME and this id, so two job types returning the
same id do not collide.
§This deduplicates dispatch, not execution
The lock is released when the job finishes, so it stops a queue filling
with a hundred copies of the same work. It does not stop two workers
running one job twice — that is the queue’s reservation, a different
mechanism — and it does not survive the lock expiring under a job that
overran UNIQUE_FOR.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".