apalis_core/task_fn/
from_request.rs

1//! Traits for offering dependency injection in task functions.
2//!
3//! This allows for more ergonomic access to common types within the task context.
4//! Items have this already implemented:
5//! - [`Attempt`]
6//! - [`WorkerContext`]
7//! - [`Data<T>`] where T is injected via `task.data(...)`
8//! - [`TaskId`]
9//!
10//! # Example
11//!
12//! Say we have a basic task for sending emails given the user id
13//! ```rust
14//! # use apalis_core::error::BoxDynError;
15//! # struct User {
16//! #     id: String,
17//! #     // other fields...
18//! # }
19//! # impl User {
20//! #     async fn find_by_id(id: String) -> Result<Self, BoxDynError> {
21//! #         // Simulate fetching user from DB
22//! #         Ok(User { id })
23//! #     }
24//! # }
25//! struct Email {
26//!     user_id: String,
27//!     subject: String,
28//!     message: String
29//! }
30//! async fn send_email_by_id(email: Email) -> Result<(), BoxDynError> {
31//!     let user_id = email.user_id;
32//!     let user = User::find_by_id(user_id).await?;
33//!     // Do something with user
34//!
35//!     Ok(())
36//! }
37//! ```
38//!
39//! With [`FromRequest`] you can improve the experience by:
40//! ```rust
41//! # use apalis_core::task::Task;
42//! # use apalis_core::error::BoxDynError;
43//! # use apalis_core::task_fn::FromRequest;
44//! # struct User {
45//! #     id: String,
46//! #     // other fields...
47//! # }
48//! # impl User {
49//! #     async fn find_by_id(id: &String) -> Result<Self, BoxDynError> {
50//! #         // Simulate fetching user from DB
51//! #         Ok(User { id: id.clone() })
52//! #     }
53//! # }
54//! # struct Email { user_id: String };
55//! impl <Ctx: Sync> FromRequest<Task<Email, Ctx>> for User {
56//!     type Error = BoxDynError;
57//!     async fn from_request(req: &Task<Email, Ctx>) -> Result<Self, BoxDynError> {
58//!         let user_id = &req.args.user_id;
59//!         let user = User::find_by_id(user_id).await?;
60//!         Ok(user)
61//!     }
62//! }
63//!
64//! async fn send_email(email: Email, user: User) -> Result<(), BoxDynError> {
65//!     // Do something with user
66//!     Ok(())
67//! }
68//! ```
69//! [`FromRequest`]: crate::task_fn::FromRequest
70//! [`Attempt`]: crate::task::attempt::Attempt
71//! [`Data<T>`]: crate::task::data::Data
72//! [`WorkerContext`]: crate::worker::context::WorkerContext
73//! [`TaskId`]: crate::task::task_id::TaskId
74
75use std::future::Future;
76
77/// A trait for extracting types from a task's context.
78pub trait FromRequest<Task>: Sized {
79    /// The error type that can occur during extraction.
80    type Error;
81    /// Perform the extraction.
82    fn from_request(req: &Task) -> impl Future<Output = Result<Self, Self::Error>> + Send;
83}