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
//! Cancelling a run that was never alive (#117(c)).
//!
//! # The hole this closes
//!
//! A run whose pinned package version no longer loads is skipped by startup
//! recovery. It never becomes resident, so it never obtains a `Recorder`, so
//! [`super::terminate::cancel`] — which opens by taking the run's recorder —
//! refuses it. The run stays `Running` forever and the operator's only lever is
//! the one thing denied. Measured on run `0756ecd5`: `describe` returns a full
//! history, `resume` reads its status, and `cancel` answers "not found".
//!
//! # Why this is a separate path and not a relaxation of the ordinary one
//!
//! The ordinary path is correct and stays untouched. What it enforces —
//! exactly one writer per workflow (invariant #3) — is not negotiable, and the
//! reason a never-alive run cannot use it is that it has no writer to take, not
//! that the rule is too strict. So this path does not weaken the rule; it
//! satisfies it by a different primitive: a
//! [`TerminalWriterReservation`](crate::registry::TerminalWriterReservation),
//! which the registry grants only when it can prove, under its own lock, that
//! the workflow has no other writer of any kind.
//!
//! # The door is narrow, and every hinge is measured
//!
//! Four conditions, in this order, all under the reservation once it is held:
//!
//! 1. **This engine recorded a reason the run could not be made resident.** The
//! cancellation cites that verdict. No verdict, no cancellation — a run that
//! is merely not resident right now is not this case.
//! 2. **A writer slot is available.** Proven by the registry, atomically, not by
//! a check here.
//! 3. **The run's pinned package does not resolve right now.** Re-measured
//! against the live catalog through the SAME resolution startup recovery
//! uses, never cited from the boot-time verdict. **If it resolves, this stops
//! and says so**: a redeploy has landed, the run is recoverable, and
//! cancelling it here would take the extraordinary route past a working
//! ordinary one.
//! 4. **The run has recorded no terminal event**, and the history's run id is
//! the run the caller named.
//!
//! On condition 3 there is a window: the catalog is read while the reservation
//! is held, but a deploy can land between that read and the append. That window
//! cannot produce a second writer — the reservation excludes handles for as long
//! as it lives — so its worst case is that a run which became recoverable a
//! microsecond ago is cancelled anyway, which is what the operator asked for.
//! The dangerous failure is closed structurally; this one is not dangerous.
//!
//! # Stated limitation
//!
//! The probe is the package RESOLUTION step, not a spawn. A run that is
//! unrecoverable because spawning fails (rather than because its version is
//! absent) will resolve, and this path will refuse it and say the run is
//! recoverable. That is the conservative direction — refusing the extraordinary
//! route when the ordinary one might work — and it is deliberate: making the
//! probe a real spawn would make a cancellation path leave a resident process
//! behind on success. The measured case for `0756ecd5` is resolution failure.
use ;
use Utc;
use crateEngineError;
use TerminateWorkflowContext;
use upsert_workflow_visibility;
/// Cancels a run that holds no handle and can never obtain one.
///
/// Called only by [`super::terminate::cancel`], after it has established that
/// the `(workflow, run)` pair has no registered handle.
///
/// # Errors
///
/// - [`EngineError::NoResidencyVerdict`] when this engine recorded no reason the
/// run could not be made resident. The verb names the true state: the run
/// exists and is readable — what is missing is the verdict this path must
/// cite.
/// - [`EngineError::RunIsRecoverable`] when the pinned package resolves now.
/// - [`EngineError::TerminalWriterUnavailable`] when the workflow already has a
/// writer.
/// - The typed recorder or store error from the terminal transition.
pub async
/// Refuses a cancellation that names a run the history does not carry.
///
/// A never-alive run has exactly one `WorkflowStarted`, so this is a direct
/// comparison rather than a projection. Without it, an operator naming a stale
/// run id would append a `WorkflowCancelled` that claims to terminate a run the
/// history never contained.