Skip to main content

auralis_task/
lib.rs

1//! auralis-task: Scoped async task runtime with explicit [`TaskScope`]
2//! hierarchy, iterative cancellation, and priority scheduling.
3//!
4//! # Architecture
5//!
6//! - **Global executor** — a [`thread_local!`] singleton with
7//!   high- and low-priority queues.
8//! - **`TaskScope`** — owns spawned futures; dropping a scope cancels
9//!   all descendant scopes and their tasks **iteratively** (no
10//!   recursion), preventing stack overflows in deeply nested UI trees.
11//! - **`set_deferred`** — safe signal mutation from [`Drop`] contexts.
12//! - **Pluggable storage** — [`ScopeStore`] and [`Executor::new_instance`]
13//!   enable multi-request isolation for SSR or multi-threaded runtimes.
14//! - **Diagnostics** — `dump_reactive_graph()` and [`scope_tree`]
15//!   (behind the `debug` feature) provide structured introspection
16//!   of the reactive graph.  [`TaskScope`] supports optional labels
17//!   for diagnostic output.
18//!
19//! # Quick example
20//!
21//! ```
22//! use auralis_task::{TaskScope, spawn_global};
23//!
24//! let scope = TaskScope::new();
25//! scope.spawn(async { /* ... */ });
26//! ```
27//!
28//! # Design decisions
29//!
30//! The crate shares `auralis_signal`'s single-threaded-by-default
31//! philosophy (`Rc` over `Arc`, `RefCell` over `Mutex`).  For
32//! multi-threaded use-cases, create an isolated [`Executor`] instance
33//! per thread or per request.  See the repository design docs for the
34//! full rationale.
35
36#![forbid(unsafe_code)]
37#![warn(missing_docs, clippy::all, clippy::pedantic)]
38#![allow(clippy::module_name_repetitions)]
39
40mod executor;
41pub mod scheduler;
42mod scope;
43pub mod timer;
44
45#[cfg(feature = "debug")]
46mod debug;
47
48#[cfg(feature = "debug")]
49pub use debug::{dump_reactive_graph, dump_task_tree};
50pub use executor::{
51    drain_deferred_signal_callbacks, has_flush_scheduler, init_flush_scheduler, init_time_source,
52    remove_panic_hook, reset_executor_for_test, schedule_callback, set_deferred,
53    set_global_max_deferred_callbacks, set_global_time_budget, set_panic_hook, spawn_global,
54    spawn_global_with_priority, with_executor, yield_now, Executor, PanicInfo, ScheduleFlush,
55    TimeSource, YieldNow,
56};
57#[cfg(test)]
58pub use executor::{TestScheduleFlush, TestTimeSource};
59pub use scheduler::DeferredScheduler;
60pub use scope::{
61    clear_scope_registry, current_scope, find_scope, set_scope_store, with_current_scope,
62    CallbackHandle, JoinHandle, ScopeStore, TaskScope,
63};
64#[cfg(feature = "debug")]
65pub use scope::{scope_debug_label, scope_tree, ScopeTreeNode, TaskNode};
66
67#[cfg(feature = "ssr-tokio")]
68pub use scope::init_scope_store_tokio;
69
70/// Task priority.
71///
72/// High-priority tasks are dequeued before low-priority ones within a
73/// single flush cycle.
74#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
75pub enum Priority {
76    /// Dequeued first during flush.
77    High,
78    /// Dequeued after all high-priority tasks.
79    Low,
80}