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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*
* Copyright (c) 2024. Govcraft
*
* Licensed under either of
* * 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
* * MIT license: http://opensource.org/licenses/MIT
*
* 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 applicable License for the specific language governing permissions and
* limitations under that License.
*/
//! Asking a supervisor to take a child on, or let one go.
//!
//! A supervisor owns its children's records privately, so nothing outside its
//! task can write to them. Registration therefore travels as a message: the
//! caller starts the child, then asks the supervisor to record it, and the
//! supervisor does so on its own task in message order.
//!
//! The same route carries the answer back when a supervisor starts a child
//! itself: the start runs on its own task and reports through
//! [`SupervisedChildStarted`].
//!
//! Every message here is crate-internal and never reaches the prelude. They are
//! intercepted by the actor's message loop before handler dispatch, so a user
//! cannot register a handler for them.
use Debug;
use Arc;
use Ern;
use ;
use crate;
use crateActorHandle;
/// The cell a caller waits on for the result of its registration.
///
/// An [`Arc`] is load-bearing rather than incidental. [`SetOnce`]'s own `Clone`
/// snapshots the current value into a fresh, independent cell, so a bare
/// `SetOnce` in a message would hand the supervisor a cell the caller can never
/// observe. Sharing the one cell is what makes the answer visible.
pub type RegistrationOutcome = ;
/// Asks a supervisor to record a child it should look after.
///
/// The child has already been created and started by the caller; this only asks
/// the supervisor to take responsibility for it.
/// Reports the outcome of a start the supervisor itself asked for.
///
/// A supervisor does not build its children on its own task: it launches a
/// start task and carries on taking messages. This is how the answer gets back,
/// and it travels the same way every other answer does.
///
/// # Undeliverable means "stop the child"
///
/// The `Ok` case carries the only handle to a live actor. If this message
/// cannot be delivered — the supervisor stopped, its inbox closed — the start
/// task must stop that child rather than drop the handle, because dropping it
/// leaves an actor running that nothing can reach. That obligation belongs to
/// whoever holds the message before it is delivered, which is why the handle
/// travels inside it rather than being registered anywhere first.
/// Tells a supervisor that a child's backoff has elapsed.
///
/// Sent by the timer task a restart decision arms, back into the supervisor's
/// own inbox. The restart itself is not performed on the timer's task: it puts
/// the slot onto the same pending-start queue a deferred first start uses, and
/// the supervisor's next turn hands it to the same start task. The restart path
/// adds a delay and a decision; it adds no second way to create an actor.
///
/// # Why a timer rather than a sleep
///
/// The supervisor cannot wait out the backoff itself without stopping — it
/// would take no messages, including its own `Terminate`, for as long as the
/// backoff lasts, and the default ceiling on that is 30 seconds.
///
/// # Every field is a check, not a convenience
///
/// This is the one input a supervisor's registry can receive arbitrarily late:
/// a timer armed before a child was retired, restarted by another path, or
/// replaced entirely still fires. So the slot is identified three ways over —
/// position, name and incarnation — and a message that does not match all three
/// is discarded rather than acted on.
/// The cell a caller waits on when releasing a child.
///
/// Carries the released child's handle back, because the caller is the one who
/// decides what happens to it next: [`ActorHandle::unsupervise`] stops it,
/// [`ActorHandle::release`] hands it to you still running. `None` where the
/// supervisor held no handle, which means the child was already down.
///
/// [`ActorHandle::unsupervise`]: crate::common::ActorHandle::unsupervise
/// [`ActorHandle::release`]: crate::common::ActorHandle::release
pub type ReleaseOutcome = ;
/// Asks a supervisor to stop looking after a child.
///
/// Releasing a child and stopping it are separate decisions, and only the
/// caller knows which it wants. The supervisor always does the same thing here
/// — retire the slot, hand the handle back — and the caller stops the child or
/// does not. What the supervisor *does* need to know is which was intended,
/// because it is the only side that can reach the IPC registry.