pub struct TaskSupervisor { /* private fields */ }Expand description
Shared, cloneable handle to the supervised lifecycle task registry.
TaskSupervisor manages named, long-lived background tasks with restart
policies, health snapshots, and graceful shutdown. It is Clone + Send + Sync
so it can be distributed to bootstrap code, TUI, and shutdown orchestration
without any additional synchronisation.
§Thread safety
Interior state is guarded by a parking_lot::Mutex. The lock is never
held across .await points.
§Examples
use std::time::Duration;
use tokio_util::sync::CancellationToken;
use zeph_core::task_supervisor::{RestartPolicy, TaskDescriptor, TaskSupervisor};
let cancel = CancellationToken::new();
let sup = TaskSupervisor::new(cancel.clone());
let _handle = sup.spawn(TaskDescriptor {
name: "watcher",
restart: RestartPolicy::RunOnce,
factory: || async { tokio::time::sleep(std::time::Duration::from_secs(1)).await },
});
sup.shutdown_all(Duration::from_secs(5)).await;Implementations§
Source§impl TaskSupervisor
impl TaskSupervisor
Sourcepub fn new(cancel: CancellationToken) -> Self
pub fn new(cancel: CancellationToken) -> Self
Create a new supervisor and start its reap driver.
The cancel token is propagated into every spawned task via tokio::select!.
When the token is cancelled, all tasks exit cooperatively on their next
cancellation check. Call shutdown_all to wait for
them to finish.
Sourcepub fn spawn<F, Fut>(&self, desc: TaskDescriptor<F>) -> TaskHandle
pub fn spawn<F, Fut>(&self, desc: TaskDescriptor<F>) -> TaskHandle
Spawn a named, supervised async task.
If a task with the same name already exists, it is aborted before the
new one is started.
§Examples
use std::time::Duration;
use tokio_util::sync::CancellationToken;
use zeph_core::task_supervisor::{RestartPolicy, TaskDescriptor, TaskHandle, TaskSupervisor};
let cancel = CancellationToken::new();
let sup = TaskSupervisor::new(cancel.clone());
let handle: TaskHandle = sup.spawn(TaskDescriptor {
name: "config-watcher",
restart: RestartPolicy::Restart { max: 3, base_delay: Duration::from_secs(1) },
factory: || async { /* watch loop */ },
});Sourcepub fn spawn_blocking<F, R>(&self, name: Arc<str>, f: F) -> BlockingHandle<R>
pub fn spawn_blocking<F, R>(&self, name: Arc<str>, f: F) -> BlockingHandle<R>
Spawn a CPU-bound closure on the OS blocking thread pool.
The closure runs via tokio::task::spawn_blocking — it is never polled
on tokio worker threads and cannot block async I/O. The task is registered
in the supervisor registry and is visible to snapshot
and shutdown_all.
Dropping the returned BlockingHandle without calling .join() does
not cancel the task; it runs to completion but the result is discarded.
A panic inside f is captured and returned as BlockingError::Panicked
rather than propagating to the caller.
§Examples
use std::sync::Arc;
use tokio_util::sync::CancellationToken;
use zeph_core::task_supervisor::{BlockingHandle, TaskSupervisor};
let cancel = CancellationToken::new();
let sup = TaskSupervisor::new(cancel);
let handle: BlockingHandle<u32> = sup.spawn_blocking(Arc::from("compute"), || {
// CPU-bound work — safe to block here
42_u32
});
let result = handle.join().await.unwrap();
assert_eq!(result, 42);§Capacity limit
At most 8 spawn_blocking tasks run concurrently. Additional tasks wait for a
semaphore permit, bounding thread-pool growth under burst load.
§Panics
Panics inside f are captured and returned as BlockingError::Panicked — they
do not propagate to the caller.
Sourcepub fn spawn_oneshot<F, Fut, R>(
&self,
name: Arc<str>,
factory: F,
) -> BlockingHandle<R>
pub fn spawn_oneshot<F, Fut, R>( &self, name: Arc<str>, factory: F, ) -> BlockingHandle<R>
Spawn an async task that produces a typed result value (runs on tokio worker thread).
Unlike spawn, no restart policy is supported — the task
runs once. The task is registered in the supervisor registry under the
provided name and is visible to snapshot and
shutdown_all.
For CPU-bound work that must not block tokio workers, use
spawn_blocking instead.
§Examples
use std::sync::Arc;
use tokio_util::sync::CancellationToken;
use zeph_core::task_supervisor::{BlockingHandle, TaskSupervisor};
let cancel = CancellationToken::new();
let sup = TaskSupervisor::new(cancel.clone());
let handle: BlockingHandle<u32> = sup.spawn_oneshot(Arc::from("compute"), || async { 42_u32 });
let result = handle.join().await.unwrap();
assert_eq!(result, 42);Sourcepub fn abort(&self, name: &'static str)
pub fn abort(&self, name: &'static str)
Abort a task by name. No-op if no task with that name is registered.
Sourcepub async fn shutdown_all(&self, timeout: Duration)
pub async fn shutdown_all(&self, timeout: Duration)
Gracefully shut down all supervised tasks.
Cancels the supervisor’s CancellationToken and waits up to timeout
for all tasks to exit. Tasks that do not exit within the timeout are
aborted forcefully and their registry entries updated to TaskStatus::Aborted.
§Note
This cancels the token passed to TaskSupervisor::new. If you share
that token with other subsystems, they will be cancelled too. Use a child
token (cancel.child_token()) when the supervisor should not affect
unrelated components.
Sourcepub fn snapshot(&self) -> Vec<TaskSnapshot>
pub fn snapshot(&self) -> Vec<TaskSnapshot>
Return a point-in-time snapshot of all registered tasks.
Suitable for TUI status panels and structured logging. The returned
list is sorted by started_at ascending.
Sourcepub fn active_count(&self) -> usize
pub fn active_count(&self) -> usize
Return the number of tasks currently in Running or Restarting state.
Sourcepub fn cancellation_token(&self) -> CancellationToken
pub fn cancellation_token(&self) -> CancellationToken
Return a clone of the supervisor’s CancellationToken.
Callers can use this to check whether shutdown has been initiated.
Trait Implementations§
Source§impl BlockingSpawner for TaskSupervisor
impl BlockingSpawner for TaskSupervisor
Source§fn spawn_blocking_named(
&self,
name: Arc<str>,
f: Box<dyn FnOnce() + Send + 'static>,
) -> JoinHandle<()>
fn spawn_blocking_named( &self, name: Arc<str>, f: Box<dyn FnOnce() + Send + 'static>, ) -> JoinHandle<()>
Spawn a named blocking closure through the supervisor.
The task is registered in the supervisor registry (visible in
snapshot and subject to graceful shutdown) before
the closure begins executing.
Source§impl Clone for TaskSupervisor
impl Clone for TaskSupervisor
Source§fn clone(&self) -> TaskSupervisor
fn clone(&self) -> TaskSupervisor
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for TaskSupervisor
impl !RefUnwindSafe for TaskSupervisor
impl Send for TaskSupervisor
impl Sync for TaskSupervisor
impl Unpin for TaskSupervisor
impl UnsafeUnpin for TaskSupervisor
impl !UnwindSafe for TaskSupervisor
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request