Skip to main content

reinhardt_tasks/
lib.rs

1//! # Reinhardt Background Tasks
2//!
3//! Celery-inspired background task queue for Reinhardt framework.
4//!
5//! ## Features
6//!
7//! - Async task execution
8//! - Task scheduling (cron-like)
9//! - Task retries with exponential backoff
10//! - Task priority
11//! - Task chaining
12//! - Task dependencies and DAG execution
13//! - Result backend
14//! - Task execution metrics and monitoring
15//! - Worker load balancing (Round-robin, Least-connections, Weighted, Random)
16//! - Webhook notifications for task completion
17//!
18//! ## Planned
19//!
20//! - Apply queue-level settings (`name`, `max_retries` from `QueueSettings`)
21//!   to a running queue. Deferred to the post-deprecation queue model, since
22//!   the current `TaskQueue` is a stateless, zero-sized delegator.
23//!
24//! ## Example
25//!
26//! ```rust,no_run
27//! # use reinhardt_tasks::TaskResult;
28//! # trait Task {}
29//! # #[derive(Clone)]
30//! # struct SendEmailTask { to: String, subject: String, body: String }
31//! # trait TaskQueue {
32//! #     fn new() -> Self;
33//! #     async fn enqueue(&self, task: SendEmailTask) -> TaskResult<()>;
34//! # }
35//! # struct QueueImpl;
36//! # impl TaskQueue for QueueImpl {
37//! #     fn new() -> Self { QueueImpl }
38//! #     async fn enqueue(&self, task: SendEmailTask) -> TaskResult<()> { Ok(()) }
39//! # }
40//! #
41//! # #[tokio::main]
42//! # async fn main() -> TaskResult<()> {
43//! // Example: Define a task
44//! // struct SendEmailTask {
45//! //     to: String,
46//! //     subject: String,
47//! //     body: String,
48//! // }
49//!
50//! // #[async_trait]
51//! // impl TaskExecutor for SendEmailTask {
52//! //     async fn execute(&self) -> TaskResult<()> {
53//!         // Send email
54//! //         Ok(())
55//! //     }
56//! // }
57//!
58//! // Queue the task
59//! let queue = QueueImpl::new();
60//! queue.enqueue(SendEmailTask {
61//!     to: "user@example.com".to_string(),
62//!     subject: "Hello".to_string(),
63//!     body: "Test email".to_string(),
64//! }).await?;
65//! # Ok(())
66//! # }
67//! ```
68
69#![warn(missing_docs)]
70
71/// Task backend trait and built-in implementations.
72pub mod backend;
73/// Feature-gated backend implementations (Redis, SQLite, SQS, RabbitMQ).
74pub mod backends;
75/// Task chaining for sequential execution pipelines.
76pub mod chain;
77/// Directed acyclic graph (DAG) based task dependencies.
78pub mod dag;
79/// Worker load balancing strategies.
80pub mod load_balancer;
81/// Distributed task locking to prevent duplicate execution.
82pub mod locking;
83/// Task execution metrics and monitoring.
84pub mod metrics;
85/// Priority-based task queue.
86pub mod priority_queue;
87/// Core task queue with configuration.
88pub mod queue;
89/// Task registry for serialization and discovery.
90pub mod registry;
91/// Result backend for storing task outputs.
92pub mod result;
93/// Retry policies with exponential backoff.
94pub mod retry;
95/// Cron-like task scheduling.
96pub mod scheduler;
97/// Settings-first configuration fragments.
98pub mod settings;
99/// Task trait and execution lifecycle.
100pub mod task;
101/// Webhook notifications for task completion events.
102pub mod webhook;
103/// Task worker execution loop.
104pub mod worker;
105
106pub use backend::{
107	DummyBackend, ImmediateBackend, ResultStatus, TaskBackend, TaskBackends, TaskExecutionError,
108	TaskResultStatus,
109};
110
111#[cfg(feature = "redis-backend")]
112pub use backends::RedisTaskBackend;
113
114#[cfg(feature = "database-backend")]
115pub use backends::SqliteBackend;
116
117#[cfg(feature = "sqs-backend")]
118pub use backends::SqsBackend;
119#[cfg(feature = "sqs-backend")]
120#[allow(deprecated)] // SqsConfig is deprecated in favor of SqsSettings.
121pub use backends::SqsConfig;
122
123#[cfg(feature = "rabbitmq-backend")]
124pub use backends::RabbitMQBackend;
125#[cfg(feature = "rabbitmq-backend")]
126#[allow(deprecated)] // RabbitMQConfig is deprecated in favor of RabbitMQSettings.
127pub use backends::RabbitMQConfig;
128pub use chain::{ChainStatus, TaskChain, TaskChainBuilder};
129pub use dag::{TaskDAG, TaskNode, TaskNodeStatus};
130pub use load_balancer::{LoadBalancer, LoadBalancingStrategy, WorkerId, WorkerInfo, WorkerMetrics};
131pub use locking::{LockToken, MemoryTaskLock, TaskLock};
132
133#[cfg(feature = "redis-backend")]
134pub use locking::RedisTaskLock;
135pub use metrics::{MetricsSnapshot, TaskCounts, TaskMetrics, WorkerStats};
136pub use priority_queue::{Priority, PriorityTaskQueue};
137#[allow(deprecated)] // QueueConfig is deprecated in favor of QueueSettings.
138pub use queue::QueueConfig;
139pub use queue::TaskQueue;
140pub use registry::{SerializedTask, TaskFactory, TaskRegistry};
141pub use result::{
142	MemoryResultBackend, ResultBackend, TaskOutput, TaskResult as TaskResultBackend,
143	TaskResultMetadata,
144};
145
146#[cfg(feature = "redis-backend")]
147pub use backends::redis::RedisTaskResultBackend;
148
149#[cfg(feature = "database-backend")]
150pub use backends::sqlite::SqliteResultBackend;
151
152#[cfg(feature = "sqs-backend")]
153pub use backends::sqs::SqsResultBackend;
154pub use retry::{RetryState, RetryStrategy};
155pub use scheduler::{CronSchedule, Schedule, Scheduler};
156pub use task::{
157	DEFAULT_TASK_QUEUE_NAME, TASK_MAX_PRIORITY, TASK_MIN_PRIORITY, Task, TaskExecutor, TaskId,
158	TaskPriority, TaskStatus,
159};
160pub use webhook::{
161	HttpWebhookSender, TaskStatus as WebhookTaskStatus, WebhookError, WebhookEvent, WebhookSender,
162	is_blocked_ip, validate_resolved_ips, validate_webhook_url,
163};
164#[allow(deprecated)]
165// RetryConfig/WebhookConfig are deprecated in favor of the *Settings fragments.
166pub use webhook::{RetryConfig, WebhookConfig};
167pub use worker::Worker;
168#[allow(deprecated)] // WorkerConfig is deprecated in favor of WorkerSettings.
169pub use worker::WorkerConfig;
170
171// Settings-first configuration API (preferred over the deprecated `*Config` types).
172pub use settings::{
173	QueueSettings, WebhookRetrySettings, WebhookSettings, WorkerSettings,
174	create_webhook_sender_from_settings, create_worker_from_settings,
175};
176#[cfg(feature = "rabbitmq-backend")]
177pub use settings::{RabbitMQSettings, create_rabbitmq_backend_from_settings};
178#[cfg(feature = "sqs-backend")]
179pub use settings::{SqsSettings, create_sqs_backend_from_settings};
180
181use thiserror::Error;
182
183/// Result type for task operations
184pub type TaskResult<T> = Result<T, TaskError>;
185
186/// Task-related errors
187///
188/// # Example
189///
190/// ```rust
191/// use reinhardt_tasks::TaskError;
192///
193/// let error = TaskError::ExecutionFailed("Database connection failed".to_string());
194/// assert_eq!(error.to_string(), "Task execution failed: Database connection failed");
195/// ```
196#[derive(Debug, Error)]
197pub enum TaskError {
198	/// Task execution failed
199	///
200	/// # Example
201	///
202	/// ```rust
203	/// use reinhardt_tasks::TaskError;
204	///
205	/// let error = TaskError::ExecutionFailed("Network error".to_string());
206	/// ```
207	#[error("Task execution failed: {0}")]
208	ExecutionFailed(String),
209
210	/// Task not found
211	///
212	/// # Example
213	///
214	/// ```rust
215	/// use reinhardt_tasks::TaskError;
216	///
217	/// let error = TaskError::TaskNotFound("task-123".to_string());
218	/// assert_eq!(error.to_string(), "Task not found: task-123");
219	/// ```
220	#[error("Task not found: {0}")]
221	TaskNotFound(String),
222
223	/// Queue error
224	#[error("Queue error: {0}")]
225	QueueError(String),
226
227	/// Serialization error
228	#[error("Serialization error: {0}")]
229	SerializationError(String),
230
231	/// Task timeout
232	///
233	/// # Example
234	///
235	/// ```rust
236	/// use reinhardt_tasks::TaskError;
237	///
238	/// let error = TaskError::Timeout;
239	/// assert_eq!(error.to_string(), "Task timeout");
240	/// ```
241	#[error("Task timeout")]
242	Timeout,
243
244	/// Max retries exceeded
245	///
246	/// # Example
247	///
248	/// ```rust
249	/// use reinhardt_tasks::TaskError;
250	///
251	/// let error = TaskError::MaxRetriesExceeded;
252	/// assert_eq!(error.to_string(), "Max retries exceeded");
253	/// ```
254	#[error("Max retries exceeded")]
255	MaxRetriesExceeded,
256}