Skip to main content

Module controller

Module controller 

Source
Available on crate feature controller only.
Expand description

Coordinates tasks that target the same application resource.

The controller is an optional admission layer in front of the runtime registry. It gives each application-defined slot at most one owner. Work in different slots can proceed independently.

Use SupervisorHandle::submit for keyed work that must not overlap. Use SupervisorHandle::add when keyed admission is not needed. Direct adds bypass this module.

The controller crate feature is enabled by default. A supervisor still needs an explicit SupervisorBuilder::with_controller call before controller methods can accept work.

§Quick start

This example submits a job to a customer-specific lane. A dedicated waiter returns its final result.

use taskvisor::prelude::*;

let supervisor = Supervisor::builder(SupervisorConfig::default())
    .with_controller(ControllerConfig::default())
    .build();
let handle = supervisor.serve()?;

let task = TaskFn::arc(|_ctx| async { Ok(()) });
let request = ControllerSpec::queue(TaskSpec::once("customer-42-job-7", task))
    .with_slot("customer-42");

let waiter = handle.submit(request).watch().execute().await?;
println!("{:?}", waiter.wait().await?);
handle.shutdown().await?;

§Architecture

application
     │ ControllerSpec
     ▼
SupervisorHandle::submit
     │ command intake
     ▼
controller slot
     ├── idle ──► runtime registry ──► managed task
     └── busy ──► queue, replace, or reject

A slot stays occupied while its owner is being admitted, registered, or physically released. “One owner” does not mean that a task body is polling at every moment. Runtime-wide admission limits still apply after the controller selects work from a slot.

§Slot, task name, and task ID

These values have separate roles:

  • a slot groups work that must not overlap;
  • a TaskSpec name is a unique registry key and label;
  • a TaskId is the identity of one submission and outcome.

The task name is the default slot. Use ControllerSpec::with_slot to put differently named tasks in one admission lane. Slot admission does not reserve a task name. The runtime registry still checks name uniqueness.

Cancellation and removal never act on an entire slot. TaskId targets can claim queued or registered work. Name targets passed to SupervisorHandle::remove or SupervisorHandle::cancel see only registered work. Queued submissions do not own a registered name. Removing one queued item leaves the other submissions in its slot unchanged.

§Choose a busy-slot policy

After preflight, every policy takes the same idle-slot path and attempts registry admission. Replace changes only the queue head. Older FIFO entries behind it remain.

§Configure a submission

SupervisorHandle::submit is the direct entry point to a Submit operation.

  • execute().await waits for ownership and command capacity, then returns the task ID.
  • ownership_timeout(duration) bounds only ownership admission before execute().await.
  • try_intake() requires ownership and command capacity to be available immediately.
  • watch() changes a successful terminal result from TaskId to TaskWaiter, including for ownership-bounded and fail-fast intake.
  • SupervisorHandle::prepare_submission allocates the TaskId before intake or events.

Ok(id) from an unwatched terminal confirms only command intake. Slot admission and runtime registration happen later. Add watch() when application logic must know whether work was rejected or how an admitted task ended. TaskWaiter delivers that result directly. Lifecycle events remain a best-effort observability path. ownership_timeout stops its timer after the permit is acquired. It does not bound controller-command capacity or slot admission. It also does not bound later registry admission or task execution. A timeout produces no command or lifecycle event. PreparedSubmission::submit preserves the preallocated ID in that operation.

During shutdown, buffered and controller-owned pending submissions are rejected. A watched pending submission reports RejectionKind::ControllerShuttingDown. Work already accepted by the runtime follows the normal runtime shutdown process.

§Operations

Structs§

ControllerConfig
Resource limits for one supervisor’s controller.
ControllerSnapshot
A rolling read-only view of the slots tracked by one controller.
ControllerSpec
A task, admission slot, and busy-slot policy submitted as one request.
PreparedSubmission
A controller request with an identity allocated before intake.
SlotView
One controller slot captured at a single point during collection.
Submit
An explicit single-use controller submission operation.

Enums§

AdmissionPolicy
The conflict policy for one controller submission.
ControllerError
A failure before controller slot admission.
SlotStatusKind
The admission and ownership state of a controller slot.