1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
//! A high-performance, type-safe task processing framework for rust.
//!
//! `apalis-core` provides the fundamental abstractions and runtime components for building
//! scalable background task systems with middleware support, graceful shutdown, and monitoring capabilities.
//!
//! This is advanced documentation, for guide level documentation is found on the [website](https://apalis.dev).
//!
//! # Core Concepts
//!
//! `apalis-core` is built around four primary abstractions that provide a flexible and extensible task processing system:
//!
//! - **[`Tasks`](#tasks)**: Type-safe task data structures with processing metadata
//! - **[`Backends`](#backends)**: Pluggable task storage and streaming implementations
//! - **[`Workers`](#workers)**: Task processing engines with lifecycle management
//! - **[`Monitor`](#monitor)**: Multi-worker coordination and observability
//!
//! The framework leverages the `tower` service abstraction to provide a rich middleware
//! ecosystem like error handling, timeouts, rate limiting,
//! and observability.
//!
//!
//! ## Tasks
//!
//! The task struct provides type-safe components for task data and metadata:
//! - [`Args`](crate::task::task_fn) - The primary structure for the task
//! - [`ExecutionContext`](crate::task::ExecutionContext) - Backend persisted info on task execution.
//! - [`TaskContext`](crate::task::context::TaskContext) - Worker provided context for a currently task in execution.
//! - [`Status`](crate::task::status::Status) - Represents the current state of a task
//! - [`TaskId`](crate::task::task_id::TaskId) - Unique identifier for task tracking
//! - [`Attempt`](crate::task::attempt::Attempt) - Retry tracking and attempt information
//! - [`Extensions`](crate::task::data) - Type-safe storage for additional task data
//! - [`Metadata`](crate::task::metadata) - metadata associated with the task
//!
//! ### Example: Using `TaskBuilder`
//!
//! ```ignore
//! let task: Task<String> = TaskBuilder::new("my-task".to_string())
//! .id("task-123".into())
//! .max_attempts(3)
//! .timeout(Duration::from_secs(30))
//! .run_in_minutes(10)
//! .build();
//! ```
//! Specific documentation for tasks can be found in the [`task`] and [`task::builder`] modules.
//!
//! #### Relevant Guides:
//! - [**Defining Task arguments**](crate::task::task_fn) - Creating effective task arguments that are scalable and type-safe
//!
//! ## Backends
//!
//! The [`Backend`](crate::backend::Backend) trait serves as the core abstraction for all task sources.
//! It defines task polling mechanisms, streaming interfaces, and middleware integration points.
//!
//! ### Inbuilt Implementations
//! - [`MemoryStorage`](crate::backend::memory::MemoryStorage) : In-memory storage based on channels
//! - [`CustomBackend`](crate::backend::custom) : Flexible backend composition allowing custom functions for task management
//!
//! Backends handle task persistence, distribution, and reliability concerns while providing
//! a uniform interface for worker consumption.
//!
//! ## Workers
//!
//! The [`Worker`](crate::worker) is the core runtime component responsible for task polling, execution, and lifecycle management:
//!
//! ### Worker Lifecycle
//!
//! - Workers are responsible for task polling, processing, and lifecycle management.
//! - Workers can be run as a future or as a stream of events.
//! - Workers readiness is conditioned on the backend and service (and middleware) being ready.
//! - This means any blocking middleware eg (concurrency) will block the worker from polling tasks.
//!
//! ### Worker Components
//!
//! The following are the main components the worker module:
//!
//! - [`WorkerBuilder`] - Fluent builder for configuring and constructing workers
//! - [`Worker`] - Actual worker implementation that processes tasks
//! - [`WorkerContext`] - Runtime state including task counts and execution status
//! - [`Event`] - Worker event enumeration (`Start`, `Engage`, `Idle`, `Error`, `Stop`)
//! - [`Ext`](crate::worker::ext) - Extension traits and middleware for adding functionality to workers
//!
//! ### Example: Building and Running a Worker
//! ```rust
//! # use apalis_core::worker::{builder::WorkerBuilder, context::WorkerContext};
//! # use apalis_core::backend::memory::MemoryStorage;
//! # use apalis_core::error::BoxDynError;
//! # use std::time::Duration;
//! # use crate::apalis_core::worker::ext::event_listener::EventListenerExt;
//! # use crate::apalis_core::backend::TaskSink;
//! #[tokio::main]
//! async fn main() {
//! let mut in_memory = MemoryStorage::new();
//! in_memory.push(1u32).await.unwrap();
//!
//! async fn task(
//! task: u32,
//! worker: WorkerContext,
//! ) -> Result<(), BoxDynError> {
//! /// Do some work
//! tokio::time::sleep(Duration::from_secs(1)).await;
//! worker.stop().unwrap();
//! Ok(())
//! }
//!
//! let worker = WorkerBuilder::new("rango-tango")
//! .backend(in_memory)
//! .on_event(|worker, ev| {
//! println!("On Event = {:?}, {:?}", ev, worker.name());
//! })
//! .build(task);
//! worker.run().await.unwrap();
//! }
//! ```
//!
//! Learn more about workers in the [`worker`](crate::worker) and [`worker::builder`](crate::worker::builder) modules.
//!
//! #### Relevant Tutorials:
//! - [**Creating task handlers**](crate::task::task_fn) - Defining task processing functions using the [`TaskFn`] trait
//!
//! ## Monitor
//!
//! The [`Monitor`](crate::monitor::Monitor) helps manage and coordinate multiple workers:
//!
//! **Main Features:**
//! - **Worker Registry** - Keeps track of active workers
//! - **Event Handling** - Handles and processes worker events
//! - **Graceful Shutdown** - Stops all workers together safely
//! - **Health Monitoring** - Restarts and manages worker health
//! ### Example: Using `Monitor` with a Worker
//!
//! ```rust
//! # use apalis_core::monitor::Monitor;
//! # use apalis_core::worker::builder::WorkerBuilder;
//! # use apalis_core::task::Task;
//! # use apalis_core::backend::{TaskSink, dequeue::VecDequeBackend};
//! # use tower::service_fn;
//! # use std::time::Duration;
//! # use apalis_core::worker::context::WorkerContext;
//! #[tokio::main]
//! async fn main() {
//! let mut storage = VecDequeBackend::new();
//! storage.push(1u32).await.unwrap();
//!
//! let monitor = Monitor::new()
//! .on_event(|worker, event| println!("{}: {:?}", worker.name(), event))
//! .register(move |_| {
//! WorkerBuilder::new("demo-worker")
//! .backend(storage.clone())
//! .build(|req: u32, worker: WorkerContext| async move {
//! println!("Processing task: {:?}", req);
//! # worker.stop().unwrap();
//! Ok::<_, std::io::Error>(req)
//! })
//! });
//!
//! // Start monitor and run all registered workers
//! monitor.run().await.unwrap();
//! }
//! ```
//!
//! Learn more about the monitor in the [`monitor` module](crate::monitor).
//!
//! ## Middleware
//!
//! Built on the `tower` ecosystem, `apalis-core` provides extensive middleware support like error handling, timeouts, rate limiting, and observability.
//!
//! ### Core Middleware
//!
//! The following middleware layers are included with their worker extensions:
//! - [`AcknowledgmentLayer`] - Task acknowledgment after processing
//! - [`EventListenerLayer`] - Worker event emission and handling
//! - [`CircuitBreakerLayer`] - Circuit breaker pattern for failure handling
//! - [`LongRunningLayer`] - Support for tracking long-running tasks
//!
//! ### Extending with middleware
//!
//! You can write your own middleware to run code before or after a task is processed.
//!
//! <details>
//! <summary>Creating Custom Middleware</summary>
//!
//! Here's a simple example of a logging middleware layer:
//!
//! ```rust
//! use apalis_core::task::Task;
//! use tower::{Layer, Service};
//! use std::task::{Context, Poll};
//!
//! // Define a logging service that wraps another service
//! pub struct LoggingService<S> {
//! inner: S,
//! }
//!
//! impl<S, Args, Res, Err> Service<Task<Args>> for LoggingService<S>
//! where
//! S: Service<Task<Args>, Response = Res, Error = Err>,
//! Args: std::fmt::Debug,
//! {
//! type Response = Res;
//! type Error = Err;
//! type Future = S::Future;
//!
//! fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
//! self.inner.poll_ready(cx)
//! }
//!
//! fn call(&mut self, req: Task<Args>) -> Self::Future {
//! println!("Processing task: {:?}", req.args);
//! self.inner.call(req)
//! }
//! }
//!
//! // Define a layer that wraps services with LoggingService
//! pub struct LoggingLayer;
//!
//! impl<S> Layer<S> for LoggingLayer {
//! type Service = LoggingService<S>;
//!
//! fn layer(&self, service: S) -> Self::Service {
//! LoggingService { inner: service }
//! }
//! }
//! ```
//! </details>
//!
//! If you want your middleware to do more than just intercept requests and responses, you can use extension traits. See the [`worker::ext`](crate::worker::ext) module for examples.
//!
//! ## Error Handling
//!
//! `apalis-core` defines a comprehensive error taxonomy for robust error handling:
//!
//! - [`AbortError`] - Non-retryable fatal errors requiring immediate termination
//! - [`RetryAfterError`] - Retryable execution errors triggering retry mechanisms after a delay
//! - [`DeferredError`] - Retryable execution errors triggering immediate retry
//!
//! This error classification enables precise error handling strategies and
//! appropriate retry behavior for different failure scenarios.
//!
//! ## Graceful Shutdown
//!
//! `apalis-core` has a reliable graceful shutdown system that makes sure
//! workers stop safely and all tasks finish before shutting down:
//!
//! **Key Features:**
//! - Task tracking: Workers keep track of how many tasks are running.
//! - Shutdown control: The system waits until all tasks are finished before shutting down.
//! - Monitor coordination: A shared [`Shutdown`] token helps all workers stop together.
//! - Timeout: You can set a time limit for shutdown using [`with_terminator`](crate::monitor::Monitor::with_terminator).
//!
//! Learn more about the graceful shutdown process in the [`monitor`](crate::monitor#graceful-shutdown-with-timeout) module.
//!
//! # Feature flags
//!
//! # Development
//! `apalis-core` provides comprehensive extensibility mechanisms such as middleware and ext traits.
//! Beyond there one may want to dive deeper into the following topics:
//!
//! - [**Using CustomBackend**](crate::backend::custom) - using custom backend to integrate with already existing systems
//! - [**Extending Workers using extension traits**](crate::worker::ext#creating-a-custom-worker-extension-trait) - implementing custom worker functionality via extension traits
//!
//! # Observability
//! You can track tasks using [apalis-board](https://github.com/apalis-dev/apalis-board).
//! 
//!
//! [`Backend`]: crate::backend::Backend
//! [`TaskFn`]: crate::task::task_fn::TaskFn
//! [`Service`]: tower_service::Service
//! [`Task`]: crate::task
//! [`WorkerBuilder`]: crate::worker::builder
//! [`Worker`]: crate::worker
//! [`Monitor`]: crate::monitor
//! [`AcknowledgmentLayer`]: crate::worker::ext::ack
//! [`EventListenerLayer`]: crate::worker::ext::event_listener
//! [`CircuitBreakerLayer`]: crate::worker::ext::circuit_breaker
//! [`LongRunningLayer`]: crate::worker::ext::long_running
//! [`AbortError`]: crate::error::AbortError
//! [`RetryAfterError`]: crate::error::RetryAfterError
//! [`DeferredError`]: crate::error::DeferredError
//! [`WorkerContext`]: crate::worker::context::WorkerContext
//! [`Event`]: crate::worker::event::Event
//! [`ExecutionContext`]: crate::task::ExecutionContext
//! [`Status`]: crate::task::status::Status
//! [`TaskId`]: crate::task::task_id::TaskId
//! [`Attempt`]: crate::task::attempt::Attempt
//! [`FromRequest`]: crate::task::from_request::FromRequest
//! [`Shutdown`]: crate::monitor::shutdown::Shutdown
pub
/// Includes internal error types.
/// Actively manage and observe workers
/// Layers for building middleware stacks
/// Timing and delaying utilities