celery/
lib.rs

1#![allow(non_local_definitions)]
2
3//! A Rust implementation of [Celery](http://www.celeryproject.org/) for producing and consuming
4//! asynchronous tasks with a distributed message queue.
5//!
6//! # Examples
7//!
8//! Define tasks by decorating functions with the [`macro@task`] attribute:
9//!
10//! ```rust
11//! use celery::prelude::*;
12//!
13//! #[celery::task]
14//! fn add(x: i32, y: i32) -> TaskResult<i32> {
15//!     Ok(x + y)
16//! }
17//! ```
18//!
19//! Then create a [`Celery`] app with the [`app!`]
20//! macro and register your tasks with it:
21//!
22//! ```rust,no_run
23//! # use anyhow::Result;
24//! # use celery::prelude::*;
25//! # #[celery::task]
26//! # fn add(x: i32, y: i32) -> celery::task::TaskResult<i32> {
27//! #     Ok(x + y)
28//! # }
29//! # #[tokio::main]
30//! # async fn main() -> Result<()> {
31//! let my_app = celery::app!(
32//!     broker = AMQPBroker { std::env::var("AMQP_ADDR").unwrap() },
33//!     tasks = [add],
34//!     task_routes = [],
35//! ).await?;
36//! # Ok(())
37//! # }
38//! ```
39//!
40//! The [`Celery`] app can be used as either a producer or consumer (worker). To send tasks to a
41//! queue for a worker to consume, use the [`Celery::send_task`] method:
42//!
43//! ```rust,no_run
44//! # use anyhow::Result;
45//! # use celery::prelude::*;
46//! # #[celery::task]
47//! # fn add(x: i32, y: i32) -> celery::task::TaskResult<i32> {
48//! #     Ok(x + y)
49//! # }
50//! # #[tokio::main]
51//! # async fn main() -> Result<()> {
52//! # let my_app = celery::app!(
53//! #     broker = AMQPBroker { std::env::var("AMQP_ADDR").unwrap() },
54//! #     tasks = [add],
55//! #     task_routes = [],
56//! # ).await?;
57//! my_app.send_task(add::new(1, 2)).await?;
58//! # Ok(())
59//! # }
60//! ```
61//!
62//! And to act as a worker to consume tasks sent to a queue by a producer, use the
63//! [`Celery::consume`] method:
64//!
65//! ```rust,no_run
66//! # use anyhow::Result;
67//! # use celery::prelude::*;
68//! # #[celery::task]
69//! # fn add(x: i32, y: i32) -> celery::task::TaskResult<i32> {
70//! #     Ok(x + y)
71//! # }
72//! # #[tokio::main]
73//! # async fn main() -> Result<()> {
74//! # let my_app = celery::app!(
75//! #     broker = AMQPBroker { std::env::var("AMQP_ADDR").unwrap() },
76//! #     tasks = [add],
77//! #     task_routes = [],
78//! # ).await?;
79//! my_app.consume().await?;
80//! # Ok(())
81//! # }
82//! ```
83
84#![doc(
85    html_favicon_url = "https://raw.githubusercontent.com/rusty-celery/rusty-celery/main/img/favicon.ico"
86)]
87#![doc(
88    html_logo_url = "https://raw.githubusercontent.com/rusty-celery/rusty-celery/main/img/rusty-celery-logo-only.png"
89)]
90
91mod app;
92mod routing;
93pub use app::{Celery, CeleryBuilder};
94pub mod beat;
95pub mod broker;
96pub mod error;
97pub mod prelude;
98pub mod protocol;
99pub mod task;
100
101#[cfg(feature = "codegen")]
102mod codegen;
103
104/// A procedural macro for generating a [`Task`](crate::task::Task) from a function.
105///
106/// If the annotated function has a return value, the return value must be a
107/// [`TaskResult<R>`](task/type.TaskResult.html).
108///
109/// # Parameters
110///
111/// - `name`: The name to use when registering the task. Should be unique. If not given the name
112///   will be set to the name of the function being decorated.
113/// - `time_limit`: Set a task-level [`TaskOptions::time_limit`](task/struct.TaskOptions.html#structfield.time_limit).
114/// - `hard_time_limit`: Set a task-level [`TaskOptions::hard_time_limit`](task/struct.TaskOptions.html#structfield.hard_time_limit).
115/// - `max_retries`: Set a task-level [`TaskOptions::max_retries`](task/struct.TaskOptions.html#structfield.max_retries).
116/// - `min_retry_delay`: Set a task-level [`TaskOptions::min_retry_delay`](task/struct.TaskOptions.html#structfield.min_retry_delay).
117/// - `max_retry_delay`: Set a task-level [`TaskOptions::max_retry_delay`](task/struct.TaskOptions.html#structfield.max_retry_delay).
118/// - `retry_for_unexpected`: Set a task-level [`TaskOptions::retry_for_unexpected`](task/struct.TaskOptions.html#structfield.retry_for_unexpected).
119/// - `acks_late`: Set a task-level [`TaskOptions::acks_late`](task/struct.TaskOptions.html#structfield.acks_late).
120/// - `content_type`: Set a task-level [`TaskOptions::content_type`](task/struct.TaskOptions.html#structfield.content_type).
121/// - `bind`: A bool. If true, the task will be run like an instance method and so the function's
122///   first argument should be a reference to `Self`. Note however that Rust won't allow you to call
123///   the argument `self`. Instead, you could use `task` or just `t`.
124/// - `on_failure`: An async callback function to run when the task fails. Should accept a reference to
125///   a task instance and a reference to a [`TaskError`](error/enum.TaskError.html).
126/// - `on_success`: An async callback function to run when the task succeeds. Should accept a reference to
127///   a task instance and a reference to the value returned by the task.
128///
129/// For more information see the [tasks chapter](https://rusty-celery.github.io/guide/defining-tasks.html)
130/// in the Rusty Celery Book.
131///
132/// ## Examples
133///
134/// Create a task named `add` with all of the default options:
135///
136/// ```rust
137/// use celery::prelude::*;
138///
139/// #[celery::task]
140/// fn add(x: i32, y: i32) -> TaskResult<i32> {
141///     Ok(x + y)
142/// }
143/// ```
144///
145/// Use a name different from the function name:
146///
147/// ```rust
148/// # use celery::prelude::*;
149/// #[celery::task(name = "sum")]
150/// fn add(x: i32, y: i32) -> TaskResult<i32> {
151///     Ok(x + y)
152/// }
153/// ```
154///
155/// Customize the default retry behavior:
156///
157/// ```rust
158/// # use celery::prelude::*;
159/// #[celery::task(
160///     time_limit = 3,
161///     max_retries = 100,
162///     min_retry_delay = 1,
163///     max_retry_delay = 60,
164/// )]
165/// async fn io_task() -> TaskResult<()> {
166///     // Do some async IO work that could possible fail, such as an HTTP request...
167///     Ok(())
168/// }
169/// ```
170///
171/// Bind the function to the task instance so it runs like an instance method:
172///
173/// ```rust
174/// # use celery::prelude::*;
175/// #[celery::task(bind = true)]
176/// fn bound_task(task: &Self) {
177///     println!("Hello, World! From {}", task.name());
178/// }
179/// ```
180///
181/// Run custom callbacks on failure and on success:
182///
183/// ```rust
184/// # use celery::task::{Task, TaskResult};
185/// # use celery::error::TaskError;
186/// #[celery::task(on_failure = failure_callback, on_success = success_callback)]
187/// fn task_with_callbacks() {}
188///
189/// async fn failure_callback<T: Task>(task: &T, err: &TaskError) {
190///     println!("{} failed with {:?}", task.name(), err);
191/// }
192///
193/// async fn success_callback<T: Task>(task: &T, ret: &T::Returns) {
194///     println!("{} succeeded: {:?}", task.name(), ret);
195/// }
196/// ```
197#[cfg(feature = "codegen")]
198pub use codegen::task;
199
200#[cfg(feature = "codegen")]
201#[doc(hidden)]
202pub mod export;
203
204#[cfg(feature = "codegen")]
205extern crate async_trait;
206
207#[cfg(feature = "codegen")]
208extern crate serde;
209
210#[cfg(feature = "codegen")]
211extern crate tokio;