Skip to content
Taskvisor 0.8source v0.8.3

Define a task

Use a closure for simple work

Use TaskFn for an async closure:

rust
use taskvisor::{TaskFn, TaskRef};

let task: TaskRef = TaskFn::arc(|_ctx| async {
    println!("one attempt");
    Ok(())
});

Implement Task for reusable work

Implement Task when a reusable type should hold state or dependencies across attempts. Each call to Task::spawn must return a fresh future. Keep synchronous work in spawn short; put the actual operation inside the returned future.

rust
use std::sync::Arc;
use std::time::Duration;
use taskvisor::{BoxTaskFuture, Task, TaskContext};

struct EndpointProbe {
    endpoint: Arc<str>,
}

impl Task for EndpointProbe {
    fn spawn(&self, ctx: TaskContext) -> BoxTaskFuture {
        let endpoint = Arc::clone(&self.endpoint);

        Box::pin(async move {
            ctx.run_until_cancelled(tokio::time::sleep(Duration::from_millis(100)))
                .await?;
            println!("checked {endpoint}");
            Ok(())
        })
    }
}

The task object keeps endpoint across attempts. The cloned value inside the returned future belongs to one attempt.

Reuse task values safely

A shared TaskRef can back several registrations. Registrations that overlap in one supervisor need different names. A name can be reused after the earlier registration releases it. The registrations receive different task IDs, and their spawn calls may run concurrently when configured attempt capacity permits. Shared task state must support that use.

After a force-abort, Taskvisor may keep the name reserved until it observes that the task attempt has physically returned.

Keep blocking work off Tokio

Keep blocking and CPU-heavy work away from Tokio worker threads. Use a suitable blocking executor, worker pool, or external runtime. Also keep the destructor of an attempt future short: Taskvisor drops that future synchronously when the attempt ends or is canceled.

Run an example

Runnable examples:

Open-source task execution components.