taskvisor/lib.rs
1//! # taskvisor
2//!
3//! **Taskvisor** is a lightweight task orchestration library for Rust.
4//!
5//! It provides primitives to define, supervise, and restart async tasks
6//! with configurable policies. The crate is designed as a building block
7//! for higher-level orchestrators and agents.
8//!
9//! ## Architecture
10//! ### Overview
11//! ```text
12//! ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
13//! │ TaskSpec │ │ TaskSpec │ │ TaskSpec │
14//! │(user task #1)│ │(user task #2)│ │(user task #3)│
15//! └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
16//! ▼ ▼ ▼
17//! ┌───────────────────────────────────────────────────────────────────┐
18//! │ Supervisor (runtime orchestrator) │
19//! │ - Bus (broadcast events) │
20//! │ - AliveTracker (tracks task state with sequence numbers) │
21//! │ - SubscriberSet (fans out to user subscribers) │
22//! │ - Registry (manages active tasks by name) │
23//! └──────┬──────────────────┬──────────────────┬───────────────┬──────┘
24//! ▼ ▼ ▼ │
25//! ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
26//! │ TaskActor │ │ TaskActor │ │ TaskActor │ │
27//! │ (retry loop) │ │ (retry loop) │ │ (retry loop) │ │
28//! └┬─────────────┘ └┬─────────────┘ └┬─────────────┘ │
29//! │ │ │ │
30//! │ Publishes │ Publishes │ Publishes │
31//! │ Events: │ Events: │ Events: │
32//! │ - TaskStarting │ - TaskStarting │ - TaskStarting │
33//! │ - TaskFailed │ - TaskStopped │ - TimeoutHit │
34//! │ - BackoffSched. │ - ActorExhausted │ - ... │
35//! │ │ │ │
36//! ▼ ▼ ▼ ▼
37//! ┌───────────────────────────────────────────────────────────────────┐
38//! │ Bus (broadcast channel) │
39//! │ (capacity: SupervisorConfig::bus_capacity) │
40//!└─────────────────────────────────┬─────────────────────────────────┘
41//! ▼
42//! ┌────────────────────────┐
43//! │ subscriber_listener │
44//! │ (in Supervisor) │
45//! └───┬────────────────┬───┘
46//! ▼ ▼
47//! AliveTracker SubscriberSet
48//! (sequence-based) (per-sub queues)
49//! ┌─────────┼─────────┐
50//! ▼ ▼ ▼
51//! worker1 worker2 workerN
52//! ▼ ▼ ▼
53//! sub1.on sub2.on subN.on
54//! _event() _event() _event()
55//! ```
56//!
57//! ### Lifecycle
58//! ```text
59//! TaskSpec ──► Supervisor ──► Registry ──► TaskActor::run()
60//!
61//! loop {
62//! ├─► attempt += 1
63//! ├─► acquire semaphore (optional, cancellable)
64//! ├─► publish TaskStarting{ task, attempt }
65//! ├─► run_once(task, timeout, attempt)
66//! │ │
67//! │ ├─ Ok ──► publish TaskStopped
68//! │ │ ├─ RestartPolicy::Never ─► ActorExhausted, exit
69//! │ │ ├─ RestartPolicy::OnFailure ─► ActorExhausted, exit
70//! │ │ └─ RestartPolicy::Always ─► reset delay, continue
71//! │ │
72//! │ └─ Err ──► publish TaskFailed{ task, error, attempt }
73//! │ ├─ RestartPolicy::Never ─► ActorExhausted, exit
74//! │ └─ RestartPolicy::OnFailure/Always:
75//! │ ├─ compute delay = backoff.next(prev_delay)
76//! │ ├─ publish BackoffScheduled{ delay, attempt }
77//! │ ├─ sleep(delay) (cancellable)
78//! │ └─ continue
79//! │
80//! └─ exit conditions:
81//! - runtime_token cancelled (OS signal or explicit remove)
82//! - RestartPolicy forbids continuation ─► ActorExhausted
83//! - Fatal error ─► ActorDead
84//! - semaphore closed
85//! }
86//!
87//! On exit: actor cleanup removes from Registry (if PolicyExhausted/Fatal)
88//! ```
89//!
90//! ## Features
91//! | Area | Description | Key types / traits |
92//! |-------------------|------------------------------------------------------------------------|----------------------------------------|
93//! | **Subscriber API**| Hook into task lifecycle events (logging, metrics, custom subscribers).| [`Subscribe`] |
94//! | **Policies** | Configure restart/backoff strategies for tasks. | [`RestartPolicy`], [`BackoffPolicy`] |
95//! | **Supervision** | Manage groups of tasks and their lifecycle. | [`Supervisor`] |
96//! | **Errors** | Typed errors for orchestration and task execution. | [`TaskError`], [`RuntimeError`] |
97//! | **Tasks** | Define tasks as functions or specs, easy to compose and run. | [`TaskRef`], [`TaskFn`], [`TaskSpec`] |
98//! | **Configuration** | Centralize runtime settings. | [`SupervisorConfig`] |
99//!
100//! ## Optional features
101//! - `logging`: exports a simple built-in [`LogWriter`] _(demo/reference only)_.
102//! - `controller`: exposes controller runtime and admission types.
103//!
104//! ## Example
105//! ```rust
106//! use std::sync::Arc;
107//! use std::time::Duration;
108//! use tokio_util::sync::CancellationToken;
109//! use taskvisor::{BackoffPolicy, SupervisorConfig, RestartPolicy, Supervisor, TaskFn, TaskRef, TaskSpec};
110//!
111//! #[tokio::main(flavor = "current_thread")]
112//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
113//! let mut cfg = SupervisorConfig::default();
114//! cfg.timeout = Duration::from_secs(5);
115//!
116//! // Build subscribers (optional)
117//! #[cfg(feature = "logging")]
118//! let subs: Vec<Arc<dyn taskvisor::Subscribe>> = {
119//! use taskvisor::LogWriter;
120//! vec![Arc::new(LogWriter::default())]
121//! };
122//! #[cfg(not(feature = "logging"))]
123//! let subs: Vec<Arc<dyn taskvisor::Subscribe>> = Vec::new();
124//!
125//! // Create supervisor
126//! let sup = taskvisor::Supervisor::builder(cfg)
127//! .with_subscribers(subs)
128//! // .with_controller(ControllerConfig { ... }) // if feature = "controller"
129//! .build();
130//!
131//! // Define a simple task that runs once and exits
132//! let hello: TaskRef = TaskFn::arc("hello", |ctx: CancellationToken| async move {
133//! if ctx.is_cancelled() { return Ok(()); }
134//! println!("Hello from task!");
135//! Ok(())
136//! });
137//!
138//! // Build specification - use RestartPolicy::Never for one-shot task
139//! let spec = TaskSpec::new(
140//! hello,
141//! RestartPolicy::Never,
142//! BackoffPolicy::default(),
143//! Some(Duration::from_secs(5)),
144//! );
145//!
146//! // Pass initial tasks to run() - they will be added by the registry listener
147//! sup.run(vec![spec]).await?;
148//! Ok(())
149//! }
150//! ```
151mod core;
152mod error;
153mod events;
154mod policies;
155mod subscribers;
156mod tasks;
157
158// ---- Public re-exports ----
159
160pub use core::{Supervisor, SupervisorConfig};
161pub use error::{RuntimeError, TaskError};
162pub use events::{BackoffSource, Event, EventKind};
163pub use policies::{BackoffPolicy, JitterPolicy, RestartPolicy};
164pub use subscribers::{Subscribe, SubscriberSet};
165pub use tasks::{Task, TaskFn, TaskRef, TaskSpec};
166
167// Optional: expose a controller object.
168// Enable with: `--features controller`
169#[cfg(feature = "controller")]
170mod controller;
171#[cfg(feature = "controller")]
172pub use controller::{AdmissionPolicy, ControllerConfig, ControllerError, ControllerSpec};
173
174// Optional: expose a simple built-in logger subscriber (demo/reference).
175// Enable with: `--features logging`
176#[cfg(feature = "logging")]
177pub use subscribers::LogWriter;