# Background Jobs This crate provides tooling required to run some processes asynchronously from a usually synchronous application. The standard example of this is Web Services, where certain things need to be processed, but processing them while a user is waiting for their browser to respond might not be the best experience. ### Usage #### Add Background Jobs to your project ```toml [dependencies] background-jobs = "0.1" failure = "0.1" futures = "0.1" tokio = "0.1" ``` #### To get started with Background Jobs, first you should define a job. Jobs are a combination of the data required to perform an operation, and the logic of that operation. They implment the `Job`, `serde::Serialize`, and `serde::DeserializeOwned`. ```rust #[derive(Clone, Debug, Deserialize, Serialize)] pub struct MyJob { some_usize: usize, other_usize: usize, } impl MyJob { pub fn new(some_usize: usize, other_usize: usize) -> Self { MyJob { some_usize, other_usize, } } } impl Job for MyJob { fn run(self) -> Box + Send> { info!("args: {:?}", self); Box::new(Ok(()).into_future()) } } ``` #### Next, define a Processor. Processors are types that define default attributes for jobs, as well as containing some logic used internally to perform the job. Processors must implement `Proccessor` and `Clone`. ```rust #[derive(Clone, Debug)] pub struct MyProcessor; impl Processor for MyProcessor { // The kind of job this processor should execute type Job = MyJob; // The name of the processor. It is super important that each processor has a unique name, // because otherwise one processor will overwrite another processor when they're being // registered. fn name() -> &'static str { "MyProcessor" } // The queue that this processor belongs to // // Workers have the option to subscribe to specific queues, so this is important to // determine which worker will call the processor // // Jobs can optionally override the queue they're spawned on fn queue() -> &'static str { DEFAULT_QUEUE } // The number of times background-jobs should try to retry a job before giving up // // Jobs can optionally override this value fn max_retries() -> MaxRetries { MaxRetries::Count(1) } // The logic to determine how often to retry this job if it fails // // Jobs can optionally override this value fn backoff_strategy() -> Backoff { Backoff::Exponential(2) } } ``` #### Running jobs By default, this crate ships with the `background-jobs-server` feature enabled. This uses the `background-jobs-server` crate to spin up a Server and Workers, and provides a mechanism for spawning new jobs. ##### Starting the job server ```rust use background_jobs::ServerConfig; use failure::Error; use server_jobs_example::queue_set; fn main() -> Result<(), Error> { // Run our job server tokio::run(ServerConfig::init( "127.0.0.1", 5555, 1, queue_set(), "example-db", )); Ok(()) } ``` ##### Starting the job worker ```rust use background_jobs::WorkerConfig; use failure::Error; use server_jobs_example::{queue_map, MyProcessor}; fn main() -> Result<(), Error> { // Create the worker config let mut worker = WorkerConfig::new("localhost".to_owned(), 5555, queue_map()); // Register our processor worker.register_processor(MyProcessor); // Spin up the workers tokio::run(worker.run()); Ok(()) } ``` ##### Queuing jobs ```rust use background_jobs::SpawnerConfig; use futures::{future::lazy, Future}; use server_jobs_example::{MyJob, MyProcessor}; fn main() { // Create 50 new jobs, each with two consecutive values of the fibonacci sequence let (_, _, jobs) = (1..50).fold((0, 1, Vec::new()), |(x, y, mut acc), _| { acc.push(MyJob::new(x, y)); (y, x + y, acc) }); // Create the spawner let spawner = SpawnerConfig::new("localhost", 5555); // Queue each job tokio::run(lazy(move || { for job in jobs { tokio::spawn(spawner.queue::(job).map_err(|_| ())); } Ok(()) })); } ``` #### Not using a ZeroMQ based client/server model If you want to create your own jobs processor based on this idea, you can depend on the `background-jobs-core` crate, which provides the LMDB storage, Processor and Job traits, as well as some other useful types for implementing a jobs processor. ### Contributing Feel free to open issues for anything you find an issue with. Please note that any contributed code will be licensed under the GPLv3. ### License Copyright © 2018 Riley Trautman Background Jobs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Background Jobs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This file is part of Background Jobs. You should have received a copy of the GNU General Public License along with Background Jobs. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).