pub struct ComponentSpawner { /* private fields */ }Expand description
Component-scoped spawner for child tasks.
Every component in a topology consists of a primary task which runs the “core loop” of the component, and optionally a number of child tasks that range from handling network connections to processing compute-heavy work in a separate thread pool.
ComponentSpawner provides a component-scoped mechanism for spawning those child tasks under supervision. It is
tied specifically to the dedicated per-component supervisor that each component gets, which ensures that child tasks
spawned through this mechanism are properly attributed to the component, and also that their lifecycle is one-to-one
with the component itself.
§Child lifecycle, and one-shot vs supervisable
We classify tasks as either one-shot or supervisable: one-shot tasks are those based on a provided closure,
which cannot be reinitialized and so cannot be restarted, and supervisable tasks are those based on an implementation
of Supervisable, which allows for (potentially) initializing the underlying task future multiple times.
One-shot tasks are always temporary, since they cannot be
reinitialized. Supervisable tasks default to the same, and opt into being restarted via
ChildBuilder::with_restart_type when the worker is built to be initialized more than once.
All child tasks default to being marked as non-significant, so their termination – clean or otherwise – leaves the component running. This is usually the correct behavior, but a component that cannot function without a particular child may wish to mark it significant, which stops the component when that child terminates.
See ChildBuilder::with_significant for more information.
§Interruptible vs non-interruptible
ComponentSpawner allows spawning two styles of child task: “interruptible” and “non-interruptible.”
Interruptible tasks are wrapped such that when the supervisor signals shutdown, the shutdown signal is
honored/polled despite whatever the logic is in the task itself does. Non-interruptible tasks still received a
shutdown handle, but the task logic itself is responsible for honoring shutdown signals.
Non-interruptible tasks aren’t truly uninterrupible: following the normal behavior of async Rust and the behavior of futures, the future associated with a task can simply be no longer polled or dropped, effectively interrupting it when considered at the level of “will this task run to completion?”
§Worker pool
ComponentSpawner is topology-aware, which means callers have the ability to specify a child task runs on the
shared “global” thread pool attached to a given topology. This should be used for compute-heavy tasks, which
otherwise can affect the scheduling latency of I/O-heavy tasks.
§Task naming
Child task names should generally not contain unique patterns/tokens – such as monotonic IDs or high-cardinality
values – as they are used for internal telemetry about the task. Generally, task names should be thought of as a
category label: if a component spawns tasks for handling connections, it should prefer to name them like
conn_handler instead of conn_handler_<ID or IP>.
A child task that must finish draining before the component stops:
spawner.spawn_noninterruptible("queue_drainer", |shutdown| drain(shutdown)).await?;A compute-heavy task that belongs on the shared worker pool, which needs the builder to say so:
spawner.interruptible("encoder", encode()).on_worker_pool().spawn().await?;Implementations§
Source§impl ComponentSpawner
impl ComponentSpawner
Sourcepub fn new(handle: SupervisorHandle, worker_pool: Handle) -> Self
pub fn new(handle: SupervisorHandle, worker_pool: Handle) -> Self
Creates a new ComponentSpawner.
worker_pool is the shared worker pool owned by the topology, used by children that opt in via
ChildBuilder::on_worker_pool.
The supervisor behind handle MUST carry a shutdown budget
(Supervisor::with_shutdown_budget). Children spawned here
have no deadline of their own, so without one a child that ignores shutdown stalls the drain indefinitely.
Sourcepub fn interruptible<N, Fut>(&self, name: N, fut: Fut) -> ChildBuilder<'_>
pub fn interruptible<N, Fut>(&self, name: N, fut: Fut) -> ChildBuilder<'_>
Creates a builder for an interruptible child task.
Interruptible tasks are implicitly wrapped such that shutdown is polled alongside the underlying task future, ensuring that shutdown is observed at the earliest possible moment. They are best used for work which has no requirements on orderly shutdown, draining of remaining work, and so on.
Use this method when advanced configuration of the underlying task is required. Otherwise, prefer
spawn_interruptible.
Sourcepub fn noninterruptible<N, F, Fut>(&self, name: N, f: F) -> ChildBuilder<'_>
pub fn noninterruptible<N, F, Fut>(&self, name: N, f: F) -> ChildBuilder<'_>
Creates a builder for a non-interruptible child task.
Non-interruptible tasks are those which handle shutdown signals directly in order to precisely control when the task completes. They are best used for tasks which must perform some operation, or operations, between the receiving of a shutdown signal and completion.
Non-interruptible tasks are not necessarily blocking: running a non-interruptible does not mean that it is guaranteed to complete, only that it won’t be wrapped in a way that tries to shutdown at the earliest possible moment.
Use this method when advanced configuration of the underlying task is required. Otherwise, prefer
spawn_noninterruptible.
Sourcepub fn supervisable<T>(&self, worker: T) -> ChildBuilder<'_, Restartable>where
T: Supervisable + 'static,
pub fn supervisable<T>(&self, worker: T) -> ChildBuilder<'_, Restartable>where
T: Supervisable + 'static,
Creates a builder for a supervisable child task.
Supervisable tasks are those where the worker already implements Supervisable, which lets
ComponentSpawner serve as a consistent control surface for spawning both arbitrary asynchronous functions
and more full-fledged workers.
Supervisable tasks are set to permanently restart by default.
Use this method when advanced configuration of the underlying task is required. Otherwise, prefer
spawn_supervisable.
Sourcepub async fn spawn_interruptible<N, Fut>(
&self,
name: N,
fut: Fut,
) -> Result<ChildId, SpawnError>
pub async fn spawn_interruptible<N, Fut>( &self, name: N, fut: Fut, ) -> Result<ChildId, SpawnError>
Spawns an interruptible child task.
Interruptible tasks are implicitly wrapped such that shutdown is polled alongside the underlying task future, ensuring that shutdown is observed at the earliest possible moment. They are best used for work which has no requirements on orderly shutdown, draining of remaining work, and so on.
Use interruptible when advanced configuration of the underlying task is required.
§Errors
If the component’s supervisor isn’t running, or the child specification is invalid, an error is returned.
Sourcepub async fn spawn_noninterruptible<N, F, Fut>(
&self,
name: N,
f: F,
) -> Result<ChildId, SpawnError>
pub async fn spawn_noninterruptible<N, F, Fut>( &self, name: N, f: F, ) -> Result<ChildId, SpawnError>
Spawns a non-interruptible child task.
Non-interruptible tasks are those which handle shutdown signals directly in order to precisely control when the task completes. They are best used for tasks which must perform some operation, or operations, between the receiving of a shutdown signal and completion.
Non-interruptible tasks are not necessarily blocking: running a non-interruptible does not mean that it is guaranteed to complete, only that it won’t be wrapped in a way that tries to shutdown at the earliest possible moment.
Use noninterruptible when advanced configuration of the underlying task is required.
§Errors
If the component’s supervisor isn’t running, or the child specification is invalid, an error is returned.
Sourcepub async fn spawn_supervisable<T>(
&self,
worker: T,
) -> Result<ChildId, SpawnError>where
T: Supervisable + 'static,
pub async fn spawn_supervisable<T>(
&self,
worker: T,
) -> Result<ChildId, SpawnError>where
T: Supervisable + 'static,
Spawns a supervisable child task.
Supervisable tasks are those where the worker already implements Supervisable, which lets
ComponentSpawner serve as a consistent control surface for spawning both arbitrary asynchronous functions
and more full-fledged workers.
Use supervisable when advanced configuration of the underlying task is required.
§Errors
If the component’s supervisor isn’t running, or the child specification is invalid, an error is returned.
Sourcepub fn worker_pool(&self) -> &Handle
pub fn worker_pool(&self) -> &Handle
Returns a handle to the shared worker pool owned by the topology.
Sourcepub fn handle(&self) -> &SupervisorHandle
pub fn handle(&self) -> &SupervisorHandle
Returns the underlying supervisor handle.
Sourcepub fn active_children(&self) -> usize
pub fn active_children(&self) -> usize
Returns the number of children currently running that were spawned through a spawner.
Statically registered children – the component itself, in a topology – are not counted.
Trait Implementations§
Source§impl Clone for ComponentSpawner
impl Clone for ComponentSpawner
Source§fn clone(&self) -> ComponentSpawner
fn clone(&self) -> ComponentSpawner
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 ComponentSpawner
impl RefUnwindSafe for ComponentSpawner
impl Send for ComponentSpawner
impl Sync for ComponentSpawner
impl Unpin for ComponentSpawner
impl UnwindSafe for ComponentSpawner
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> 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::RequestSource§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> Track for T
impl<T> Track for T
§fn track_resources(self, token: ResourceGroupToken) -> Tracked<Self>
fn track_resources(self, token: ResourceGroupToken) -> Tracked<Self>
Tracked wrapper. Read more§fn in_current_resource_group(self) -> Tracked<Self>
fn in_current_resource_group(self) -> Tracked<Self>
Tracked wrapper. Read more