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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
//! One awaited call: hand an already-built task to an already-chosen worker,
//! over whichever transport that worker registered on.
//!
//! # Why this seam exists
//!
//! Before it, the dispatcher's delivery line assumed gRPC. A worker whose
//! `sender()` was `None` — which is every liminal-delivered worker — was
//! **deregistered like a closed stream**, on the premise that its presence could
//! only be a leak. That premise held while the outbox chose one transport for
//! the whole server, and stops holding the moment a row is routed by the
//! worker's own delivery ([aion#52]).
//!
//! # The contract, and why the blocking shape wins
//!
//! "Enqueued onto the stream" is the weakest truth a transport can offer: it
//! says a message was accepted by a channel, not that a worker took the work.
//! The liminal path already offers a stronger one — a correlated reply, with the
//! run id resolved **before** an owner is bound — and that is the truth the
//! completion fences actually want. So the seam is a single awaited call
//! returning a typed outcome, and gRPC is the fast-completing case of it rather
//! than a different shape. Latency is not the dispatcher's concern; it awaits
//! either.
//!
//! # The outcome carries the deregistration decision as a TYPE
//!
//! The distinction that used to live in a comment at the delivery line is now
//! [`Undeliverable`]'s two variants, so a caller cannot act on it by accident:
//! a worker the transport says is **gone** is deregistered, and a delivery that
//! failed while the worker is **alive** leaves the registration standing.
//!
//! [aion#52]: https://github.com/ablative-io/aion/issues/52
use async_trait;
use ProtoActivityTask;
use SharedDeliveryIntent;
use WorkerHandle;
/// How a delivered task's liveness is tracked, as a value the transport must
/// interpret rather than a bare number it must remember the meaning of.
///
/// Distinct from [`TaskLiveness`](super::heartbeat::TaskLiveness), which is
/// the tracker's RECORD of an in-flight activity. This type says whether a
/// task is tracked that way at all.
///
/// # Why this is a type and not `0`
///
/// [`ProtoActivityTask`] carries no heartbeat window, so a transport that needs
/// one — liminal's `DispatchRequest` has the field — cannot derive it and must
/// **assign** it. Today's assignment is `0`, and it is correct only while liminal
/// dispatches stay outside the server's per-task liveness tracker: the outbox
/// retry loop is their backstop, so the worker pumps no beats for them.
///
/// Written as an exhaustive enum so that the day a liminal dispatch *is* tracked
/// per task, adding the variant makes every `match` on it non-exhaustive and the
/// compiler names each site that has to decide again. A literal `0` would simply
/// keep compiling, silently claiming "no window" for a dispatch that now needs
/// one.
/// Why one delivery attempt did not place its task with a worker.
///
/// The two variants are the whole reason this is a type rather than a `bool`:
/// they carry **opposite obligations** for the worker's registration, and
/// conflating them either destroys a live worker's registration or keeps a dead
/// one's forever.
/// The outcome of one delivery attempt to one already-chosen worker.
/// What a transport arm calls at the instant the worker HOLDS the task — the
/// gRPC stream accepted the frame; the liminal push was acknowledged — and
/// before it waits for any reply.
///
/// The one implementation in production records the attempt's lease
/// ([`super::lease_record::LeaseHandoff`]). It is a trait rather than that type
/// so the transport arms depend on the moment, not on what is done with it,
/// and so a test can hand in a recorder of its own.
/// A transport that can place one task with one already-selected worker.
///
/// 🔴 **Selection is NOT this trait's job, and that is the point.** The worker
/// arrives already chosen by the dispatcher's single selection — with its
/// `Prefer`/`Pinned` tier walk and placement cache already applied — so a
/// transport cannot select again. Two selections per placement would let the
/// spill resolve differently from the delivery, which is the defect a composite
/// dispatcher would have reintroduced.