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 backend;
95pub mod beat;
96pub mod broker;
97pub mod error;
98pub mod prelude;
99pub mod protocol;
100pub mod task;
101
102#[cfg(feature = "codegen")]
103mod codegen;
104
105/// A procedural macro for generating a [`Task`](crate::task::Task) from a function.
106///
107/// If the annotated function has a return value, the return value must be a
108/// [`TaskResult<R>`](task/type.TaskResult.html).
109///
110/// # Parameters
111///
112/// - `name`: The name to use when registering the task. Should be unique. If not given the name
113///   will be set to the name of the function being decorated.
114/// - `time_limit`: Set a task-level [`TaskOptions::time_limit`](task/struct.TaskOptions.html#structfield.time_limit).
115/// - `hard_time_limit`: Set a task-level [`TaskOptions::hard_time_limit`](task/struct.TaskOptions.html#structfield.hard_time_limit).
116/// - `max_retries`: Set a task-level [`TaskOptions::max_retries`](task/struct.TaskOptions.html#structfield.max_retries).
117/// - `min_retry_delay`: Set a task-level [`TaskOptions::min_retry_delay`](task/struct.TaskOptions.html#structfield.min_retry_delay).
118/// - `max_retry_delay`: Set a task-level [`TaskOptions::max_retry_delay`](task/struct.TaskOptions.html#structfield.max_retry_delay).
119/// - `retry_for_unexpected`: Set a task-level [`TaskOptions::retry_for_unexpected`](task/struct.TaskOptions.html#structfield.retry_for_unexpected).
120/// - `acks_late`: Set a task-level [`TaskOptions::acks_late`](task/struct.TaskOptions.html#structfield.acks_late).
121/// - `content_type`: Set a task-level [`TaskOptions::content_type`](task/struct.TaskOptions.html#structfield.content_type).
122/// - `bind`: A bool. If true, the task will be run like an instance method and so the function's
123///   first argument should be a reference to `Self`. Note however that Rust won't allow you to call
124///   the argument `self`. Instead, you could use `task` or just `t`.
125/// - `on_failure`: An async callback function to run when the task fails. Should accept a reference to
126///   a task instance and a reference to a [`TaskError`](error/enum.TaskError.html).
127/// - `on_success`: An async callback function to run when the task succeeds. Should accept a reference to
128///   a task instance and a reference to the value returned by the task.
129///
130/// For more information see the [tasks chapter](https://rusty-celery.github.io/guide/defining-tasks.html)
131/// in the Rusty Celery Book.
132///
133/// ## Examples
134///
135/// Create a task named `add` with all of the default options:
136///
137/// ```rust
138/// use celery::prelude::*;
139///
140/// #[celery::task]
141/// fn add(x: i32, y: i32) -> TaskResult<i32> {
142///     Ok(x + y)
143/// }
144/// ```
145///
146/// Use a name different from the function name:
147///
148/// ```rust
149/// # use celery::prelude::*;
150/// #[celery::task(name = "sum")]
151/// fn add(x: i32, y: i32) -> TaskResult<i32> {
152///     Ok(x + y)
153/// }
154/// ```
155///
156/// Customize the default retry behavior:
157///
158/// ```rust
159/// # use celery::prelude::*;
160/// #[celery::task(
161///     time_limit = 3,
162///     max_retries = 100,
163///     min_retry_delay = 1,
164///     max_retry_delay = 60,
165/// )]
166/// async fn io_task() -> TaskResult<()> {
167///     // Do some async IO work that could possible fail, such as an HTTP request...
168///     Ok(())
169/// }
170/// ```
171///
172/// Bind the function to the task instance so it runs like an instance method:
173///
174/// ```rust
175/// # use celery::prelude::*;
176/// #[celery::task(bind = true)]
177/// fn bound_task(task: &Self) {
178///     println!("Hello, World! From {}", task.name());
179/// }
180/// ```
181///
182/// Run custom callbacks on failure and on success:
183///
184/// ```rust
185/// # use celery::task::{Task, TaskResult};
186/// # use celery::error::TaskError;
187/// #[celery::task(on_failure = failure_callback, on_success = success_callback)]
188/// fn task_with_callbacks() {}
189///
190/// async fn failure_callback<T: Task>(task: &T, err: &TaskError) {
191///     println!("{} failed with {:?}", task.name(), err);
192/// }
193///
194/// async fn success_callback<T: Task>(task: &T, ret: &T::Returns) {
195///     println!("{} succeeded: {:?}", task.name(), ret);
196/// }
197/// ```
198#[cfg(feature = "codegen")]
199pub use codegen::task;
200
201#[cfg(feature = "codegen")]
202#[doc(hidden)]
203pub mod export;
204
205#[cfg(feature = "codegen")]
206extern crate async_trait;
207
208#[cfg(feature = "codegen")]
209extern crate serde;
210
211#[cfg(feature = "codegen")]
212extern crate tokio;