A distributed background job manager and runner for Rust. This is currently in PoC stage.
Click to expand: One-time setup during application startup!
later
and required dependencies```toml later = "0.0.3" serde = "1.0"
```
```ignore use serde::{Deserialize, Serialize};
pub struct SendEmail { pub address: String, pub body: String, }
// ... more as required
```
```ignore later::background_job! { struct Jobs { // Use the format // name: Payload type (defined above)
send_email: SendEmail,
// ..
}
} ```
This generates two types
* JobsBuilder
- used to bootstrap the background job server - which can be used to enqueue jobs,
* JobContext<T>
- used to pass application context (T
) in the handler as well as enqueue jobs,
For struct Jobs
a type JobsBuilder
will be generated. Use this to bootstrap the server.
``ignore
// bootstrap the server
let job_ctx = JobContext {};
let ctx = MyContext{ /*..*/ }; // Any context to pass onto the handlers
let storage = Redis::new("redis://127.0.0.1/") // More storage option to be available later
.await
.expect("connect to redis");
let ctx = JobsBuilder::new(
ctx, // Pass the context here
"later-example".into(), // Unique name for this app
// Ensure the this is same in multiple
// instances of this app.
"amqp://guest:guest@localhost:5672".into(), // RabbitMq instance
)
// for each payload defined in the
struct Jobs` above
// the generated fn name uses the pattern "with[name]handler"
.withsendemailhandler(handlesend_email) // Pass the handler function
// ..
.build()
.expect("start BG Jobs server");
// use ctx.enqueue(SendEmail{ ... }) to enqueue jobs, // or ctx.enqueuecontinue(parentjob_id, SendEmail{ ... }) to chain jobs. // this will only accept types defined inside the macro above
// define handler
async fn handlesendemail(
ctx: JobContextpayload
// ctx.app -> Access the MyContext passed during bootstrapping
// ctx.enqueue(_).await to enqueue more jobs
// ctx.enqueue_continue(_).await to chain jobs
Ok(()) // or Err(_) to retry this message
}
```
Fire and forget jobs are executed only once and executed by an available worker almost immediately.
```ignore ctx.enqueue(SendEmail{ address: "hello@rust-lang.org".tostring(), body: "You rock!".tostring() }).await;
```
One or many jobs are chained together to create an workflow. Child jobs are executed only when parent job has been finished.
```ignore let emailwelcome = ctx.enqueue(SendEmail{ address: "customer@example.com".tostring(), body: "Creating your account!".to_string() }).await;
let createaccount = ctx.enqueuecontinue(email_welcome, CreateAccount { ... }).await;
let emailconfirmation = ctx.enqueuecontinue(createaccount, SendEmail{ address: "customer@example.com".tostring(), body: "Your account has been created!".to_string() }).await;
```
Just like fire and forget jobs that starts after a certain interval.
```ignore // delay ctx.enqueuedelayed(SendEmail{ address: "hello@rust-lang.org".tostring(), body: "You rock!".tostring() }, std::time::Duration::fromsecs(60)).await;
// specific time
let runjobat : chrono::DateTime
```
(Coming soon)
This is PoC at this moment. Upcoming features are