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;