1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2023 The RocketMQ Rust Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::future::Future;
use tokio_util::sync::CancellationToken;
use crate::critical::CriticalFailureState;
use crate::error::RuntimeResult;
use crate::task_group::TaskGroup;
use crate::task_group::TaskGroupId;
use crate::task_group::TaskId;
use crate::task_group::TaskKind;
/// Narrow capability for spawning work owned by an existing [`TaskGroup`].
///
/// Cloning this value shares lifecycle authority; it cannot create a runtime
/// root, expose a raw Tokio handle, detach work, or outlive owner shutdown.
#[derive(Debug, Clone)]
pub struct TaskSpawner {
task_group: TaskGroup,
}
impl TaskSpawner {
pub(crate) fn new(task_group: TaskGroup) -> Self {
Self { task_group }
}
/// Returns the identity of the owned task group.
pub fn group_id(&self) -> TaskGroupId {
self.task_group.id()
}
/// Returns the diagnostic name of the owned task group.
pub fn group_name(&self) -> &str {
self.task_group.name()
}
/// Returns a child token cancelled by owner shutdown.
///
/// Cancelling the returned token does not cancel the owning task group.
pub fn cancellation_token(&self) -> CancellationToken {
self.task_group.cancellation_token().child_token()
}
/// Registers `future` as parent-owned work.
///
/// The future must be `Send` and tasks have no ordering guarantee relative
/// to other submissions. Owner shutdown cancels and awaits the registered
/// task according to the parent task group's deadline.
///
/// # Errors
///
/// Returns an error when the parent group is shutting down or closed.
pub fn spawn<F>(&self, name: impl Into<crate::TaskName>, kind: TaskKind, future: F) -> RuntimeResult<TaskId>
where
F: Future<Output = ()> + Send + 'static,
{
self.task_group.spawn(name, kind, future)
}
/// Registers a long-lived service future with a custom shutdown protocol.
///
/// The future must observe a cancellation token and perform its own
/// ordered cleanup. Use [`Self::spawn_cancellable_service`] when owner
/// cancellation may drop the future immediately.
///
/// # Errors
///
/// Returns an error when the parent group is shutting down or closed.
pub fn spawn_service<F>(&self, name: impl Into<crate::TaskName>, future: F) -> RuntimeResult<TaskId>
where
F: Future<Output = ()> + Send + 'static,
{
self.task_group.spawn_service(name, future)
}
/// Registers a service that exits when either its future completes or its owner is cancelled.
///
/// # Errors
///
/// Returns an error when the parent group is shutting down or closed.
pub fn spawn_cancellable_service<F>(&self, name: impl Into<crate::TaskName>, future: F) -> RuntimeResult<TaskId>
where
F: Future<Output = ()> + Send + 'static,
{
self.task_group.spawn_cancellable_service(name, future)
}
/// Registers parent-owned work whose panic is recorded as a critical failure.
///
/// The failure record stays pending until a handler takes it, so a full
/// notification channel cannot lose the fact that the task failed.
///
/// # Errors
///
/// Returns an error when the parent group is shutting down or closed.
pub fn spawn_critical<F>(
&self,
name: impl Into<crate::TaskName>,
kind: TaskKind,
failures: CriticalFailureState,
future: F,
) -> RuntimeResult<TaskId>
where
F: Future<Output = ()> + Send + 'static,
{
self.task_group.spawn_critical(name, kind, failures, future)
}
/// Registers a critical service that must run until its owner is cancelled.
///
/// A panic and a return before owner cancellation are both recorded; owner
/// cancellation is an expected exit and records nothing.
///
/// # Errors
///
/// Returns an error when the parent group is shutting down or closed.
pub fn spawn_critical_service<F>(
&self,
name: impl Into<crate::TaskName>,
failures: CriticalFailureState,
future: F,
) -> RuntimeResult<TaskId>
where
F: Future<Output = ()> + Send + 'static,
{
self.task_group.spawn_critical_service(name, failures, future)
}
}