Skip to main content

behavior_actors/atomic/worker/
initialization.rs

1//! Worker initialization and its exact returned input shared by atomic owners.
2
3use std::sync::Arc;
4
5use core::marker::PhantomData;
6
7use behavior::{
8    ActionItem, Behavior, BehaviorAddr, EndpointAddress, EstablishedRecipient, Here,
9    InterpretationProgress, InterpreterRequest, ItemSettlement, Never, ReturnsToEmitter,
10    finish_item, prepare_item,
11};
12
13use crate::ChildStopped;
14
15use super::WorkerAttempt;
16
17/// Non-reused correlation for one worker's initialization settlement.
18#[derive(Clone)]
19pub struct InitializationAttempt {
20    worker: WorkerAttempt,
21    token: Arc<()>,
22}
23
24impl InitializationAttempt {
25    pub(in crate::atomic) fn issued(worker: &WorkerAttempt) -> Self {
26        Self {
27            worker: worker.clone(),
28            token: Arc::new(()),
29        }
30    }
31}
32
33impl core::fmt::Debug for InitializationAttempt {
34    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35        formatter
36            .debug_tuple("InitializationAttempt")
37            .field(&self.worker)
38            .finish()
39    }
40}
41
42impl PartialEq for InitializationAttempt {
43    fn eq(&self, other: &Self) -> bool {
44        self.worker == other.worker && Arc::ptr_eq(&self.token, &other.token)
45    }
46}
47
48impl Eq for InitializationAttempt {}
49
50/// One-shot authority to begin activation for one initialized worker.
51///
52/// ```
53/// fn accept<W>(permit: behavior_actors::atomic::ActivationPermit<W>)
54/// where
55///     W: behavior::Behavior,
56///     behavior::BehaviorAddr<W>: behavior::EndpointAddress,
57/// {
58///     let _accepted = permit;
59/// }
60/// ```
61///
62/// ```compile_fail,E0382
63/// fn duplicate<W>(permit: behavior_actors::atomic::ActivationPermit<W>)
64/// where
65///     W: behavior::Behavior,
66///     behavior::BehaviorAddr<W>: behavior::EndpointAddress,
67/// {
68///     let _accepted = permit;
69///     let _duplicate = permit;
70/// }
71/// ```
72#[must_use = "activation authority must be consumed or retained"]
73pub struct ActivationPermit<W>
74where
75    W: Behavior,
76    BehaviorAddr<W>: EndpointAddress,
77{
78    worker: WorkerAttempt,
79    initialization: InitializationAttempt,
80    target: EstablishedRecipient<W::Protocol>,
81    worker_type: PhantomData<fn() -> W>,
82}
83
84impl<W> ActivationPermit<W>
85where
86    W: Behavior,
87    BehaviorAddr<W>: EndpointAddress,
88{
89    /// Worker correlation authorized by this permit.
90    #[must_use]
91    pub fn worker(&self) -> WorkerAttempt {
92        self.worker.clone()
93    }
94
95    /// Initialization correlation authorized by this permit.
96    #[must_use]
97    pub fn initialization(&self) -> InitializationAttempt {
98        self.initialization.clone()
99    }
100
101    /// Exact installed worker authorized by this permit.
102    #[must_use]
103    pub fn target(&self) -> EstablishedRecipient<W::Protocol> {
104        self.target.clone()
105    }
106
107    pub(in super::super) fn worker_evidence(&self) -> &WorkerAttempt {
108        &self.worker
109    }
110}
111
112/// One child-host request retaining the exact activation plan.
113///
114/// ```compile_fail,E0382
115/// fn duplicate<W, P>(request: behavior_actors::atomic::InitializeWorker<W, P>)
116/// where
117///     W: behavior::Behavior,
118///     behavior::BehaviorAddr<W>: behavior::EndpointAddress,
119/// {
120///     let _accepted = request;
121///     let _duplicate = request;
122/// }
123/// ```
124#[must_use = "worker initialization custody must settle or transfer outward"]
125pub struct InitializeWorker<W, P>
126where
127    W: Behavior,
128    BehaviorAddr<W>: EndpointAddress,
129{
130    worker: WorkerAttempt,
131    initialization: InitializationAttempt,
132    target: EstablishedRecipient<W::Protocol>,
133    activation: P,
134}
135
136impl<W, P> InitializeWorker<W, P>
137where
138    W: Behavior,
139    BehaviorAddr<W>: EndpointAddress,
140{
141    pub(in crate::atomic) fn new(
142        worker: WorkerAttempt,
143        initialization: InitializationAttempt,
144        target: EstablishedRecipient<W::Protocol>,
145        activation: P,
146    ) -> Self {
147        Self {
148            worker,
149            initialization,
150            target,
151            activation,
152        }
153    }
154
155    /// Exact installed-worker target retained by this request.
156    #[must_use]
157    pub fn target(&self) -> EstablishedRecipient<W::Protocol> {
158        self.target.clone()
159    }
160
161    /// Worker-creation correlation retained by the proxy.
162    #[must_use]
163    pub fn worker(&self) -> WorkerAttempt {
164        self.worker.clone()
165    }
166
167    /// Initialization correlation retained by the proxy.
168    #[must_use]
169    pub fn initialization(&self) -> InitializationAttempt {
170        self.initialization.clone()
171    }
172
173    /// Reunite the host result with the affine activation plan.
174    #[must_use]
175    pub fn resolve(
176        self,
177        result: WorkerInitializationOutcome<W>,
178    ) -> WorkerInitializationReport<W, P> {
179        let Self {
180            worker,
181            initialization,
182            target,
183            activation,
184        } = self;
185        match result {
186            WorkerInitializationOutcome::ReadyForActivation => {
187                WorkerInitializationReport::ReadyForActivation {
188                    worker: worker.clone(),
189                    initialization: initialization.clone(),
190                    activation,
191                    permit: ActivationPermit {
192                        worker,
193                        initialization,
194                        target,
195                        worker_type: PhantomData,
196                    },
197                }
198            }
199            WorkerInitializationOutcome::EffectsRejected(failure) => {
200                WorkerInitializationReport::EffectsRejected {
201                    worker,
202                    initialization,
203                    activation,
204                    failure,
205                }
206            }
207            WorkerInitializationOutcome::Stopped(stopped) => WorkerInitializationReport::Stopped {
208                worker,
209                initialization,
210                activation,
211                stopped,
212            },
213        }
214    }
215}
216
217impl<W, P> InterpreterRequest for InitializeWorker<W, P>
218where
219    W: Behavior,
220    BehaviorAddr<W>: EndpointAddress,
221{
222    type ReturnToEmitter = ReturnsToEmitter<WorkerInitializationReport<W, P>, Here>;
223    type LogicalProtocols = behavior::NoBirthProtocols;
224}
225
226impl<W, P> ActionItem for InitializeWorker<W, P>
227where
228    W: Behavior,
229    BehaviorAddr<W>: EndpointAddress,
230    EstablishedRecipient<W::Protocol>: Send,
231    P: Send,
232{
233    type Custody = (Option<Self>, Option<Self::Reply>);
234    type Input<'a>
235        = &'a mut Option<Self>
236    where
237        Self: 'a;
238    type Reply = ItemSettlement<Self, Self::Accepted, Self::Rejection, Self::Prerequisite>;
239
240    fn prepare_interpretation(
241        progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
242    ) {
243        prepare_item::<Self>(progress);
244    }
245
246    fn interpretation_input<'a>(
247        custody: &'a mut Self::Custody,
248    ) -> Option<(Self::Input<'a>, &'a mut Option<Self::Reply>)>
249    where
250        Self: 'a,
251    {
252        match custody {
253            (input @ Some(_), received @ None) => Some((input, received)),
254            _ => None,
255        }
256    }
257
258    fn finish_interpretation(
259        progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
260    ) {
261        finish_item::<Self>(progress);
262    }
263
264    type Accepted = ();
265    type Rejection = Never;
266    type Prerequisite = Never;
267}
268
269/// Result selected by the child host after total initialization settlement.
270pub enum WorkerInitializationOutcome<W>
271where
272    W: Behavior,
273{
274    ReadyForActivation,
275    EffectsRejected(WorkerInitializationFailure),
276    Stopped(ChildStopped<BehaviorAddr<W>>),
277}
278
279/// Exact initialization result returned to the worker owner.
280pub enum WorkerInitializationReport<W, P>
281where
282    W: Behavior,
283    BehaviorAddr<W>: EndpointAddress,
284{
285    ReadyForActivation {
286        worker: WorkerAttempt,
287        initialization: InitializationAttempt,
288        activation: P,
289        permit: ActivationPermit<W>,
290    },
291    EffectsRejected {
292        worker: WorkerAttempt,
293        initialization: InitializationAttempt,
294        activation: P,
295        failure: WorkerInitializationFailure,
296    },
297    Stopped {
298        worker: WorkerAttempt,
299        initialization: InitializationAttempt,
300        activation: P,
301        stopped: ChildStopped<BehaviorAddr<W>>,
302    },
303}
304
305impl<W, P> WorkerInitializationReport<W, P>
306where
307    W: Behavior,
308    BehaviorAddr<W>: EndpointAddress,
309{
310    pub(in crate::atomic) fn worker(&self) -> &WorkerAttempt {
311        match self {
312            Self::ReadyForActivation { worker, .. }
313            | Self::EffectsRejected { worker, .. }
314            | Self::Stopped { worker, .. } => worker,
315        }
316    }
317
318    pub(in crate::atomic) fn initialization(&self) -> &InitializationAttempt {
319        match self {
320            Self::ReadyForActivation { initialization, .. }
321            | Self::EffectsRejected { initialization, .. }
322            | Self::Stopped { initialization, .. } => initialization,
323        }
324    }
325}
326
327/// Semantic classification returned after Bombay retains a failed worker
328/// initialization settlement in runtime retirement custody.
329#[derive(Clone, Copy, Debug, Eq, PartialEq)]
330pub enum WorkerInitializationFailure {
331    /// At least one initialization item was rejected or dependency-blocked.
332    EffectsRejected,
333    /// Interpretation corrupted or left an unattempted suffix.
334    InterpreterCorrupt,
335}