Skip to main content

TaskSupervisor

Struct TaskSupervisor 

Source
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

Source

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.

Source

pub fn spawn<F, Fut>(&self, desc: TaskDescriptor<F>) -> TaskHandle
where F: Fn() -> Fut + Send + Sync + 'static, Fut: Future<Output = ()> + Send + 'static,

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 */ },
});
Source

pub fn spawn_blocking<F, R>(&self, name: Arc<str>, f: F) -> BlockingHandle<R>
where F: FnOnce() -> R + Send + 'static, R: Send + 'static,

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.

Source

pub fn spawn_oneshot<F, Fut, R>( &self, name: Arc<str>, factory: F, ) -> BlockingHandle<R>
where F: FnOnce() -> Fut + Send + 'static, Fut: Future<Output = R> + Send + 'static, R: Send + 'static,

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);
Source

pub fn abort(&self, name: &'static str)

Abort a task by name. No-op if no task with that name is registered.

Source

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.

Source

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.

Source

pub fn active_count(&self) -> usize

Return the number of tasks currently in Running or Restarting state.

Source

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

Source§

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

Source§

fn clone(&self) -> TaskSupervisor

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more