rustlavel-queue: background jobs and scheduling.
Work that should not happen while someone is waiting for a response — sending mail, resizing an image, calling a slow API — goes on a queue and is run by a worker. Work that should happen at a particular time goes on a schedule.
// Define a job.
struct SendWelcomeEmail { user_id: i64 }
impl Job for SendWelcomeEmail {
const NAME: &'static str = "send-welcome-email";
fn payload(&self) -> Json {
Json::object([("user_id", Json::from(self.user_id))])
}
fn from_payload(payload: &Json) -> Result<Self> {
Ok(SendWelcomeEmail {
user_id: payload.get("user_id").and_then(Json::as_i64).unwrap_or_default(),
})
}
fn handle(&self) -> impl Future<Output = Result<()>> + Send {
async move { Ok(()) }
}
}
// Dispatch it from a handler.
queue.dispatch(&SendWelcomeEmail { user_id }).await?;
// Run it, in `queue:work`.
let mut jobs = JobRegistry::new();
jobs.register::<SendWelcomeEmail>();
let shutdown = Shutdown::new();
shutdown.on_ctrl_c();
run_pool(Worker::new(queue, Arc::new(jobs)), 4, shutdown).await?;
The one thing that is not like Laravel
Laravel serialises the job object and asks PHP to bring the class back. A
compiled language cannot resurrect a type from a string, so the way back
from a stored name to running code is stated once, at boot, in a
[JobRegistry]. That is the only line of ceremony the design adds, and it
buys a queue:work that fails to compile against a renamed job rather than
failing at three in the morning against a class that is no longer there.
What is in here
- [
Job] and [JobRegistry] — defining work and finding it again. - [
Queue] and [QueueExt] — the driver contract and its conveniences. - [
MemoryQueue], [DatabaseQueue], [FakeQueue] — the three drivers. - [
Worker], [run_pool], [Shutdown] — running jobs, and stopping well. - [
Scheduler] and [Cron] — running work at a time rather than on demand. - [
QueueDashboard] — the plugin that exposes it all over HTTP.
Everything the queue does is reported on rustlavel_core::events as
queue.pushed, queue.processed and queue.failed, so Telescope shows
jobs without this crate knowing Telescope exists.