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
//! The terminal-writer reservation: the sole writer for a run that can never
//! obtain a handle (#117(c)).
//!
//! # What this is, and why it is not a handle
//!
//! A run whose pinned package version no longer loads is skipped by startup
//! recovery, never becomes resident, and therefore never obtains a
//! [`WorkflowHandle`] — so it never obtains a `Recorder`, so it can never be
//! cancelled, so it stays `Running` forever. Cancel, the operator's only lever,
//! is the one thing refused.
//!
//! The obvious fix — give the run a handle so it has a recorder — is dead, and
//! was eliminated by measurement before this was written.
//! [`WorkflowHandleParts`] requires a `pid` and a `loaded_version`: precisely
//! the two facts an unrecoverable run cannot supply. Three independent
//! subsystems read those fields as facts (the startup recovery skip, the
//! live-version set gating package unload, and delivery routing), so a
//! fabricated value corrupts each of them.
//!
//! > The cheap route is worse than the expensive one.
//!
//! This is the expensive one. It carries **no pid, no `loaded_version`, and no
//! residency**, and it is invisible to [`Registry::live_pid`] — nothing that
//! reads the registry for a live process can see it, because there is no
//! process.
//!
//! # Why it is a guard, and what that buys
//!
//! The reservation is an RAII guard borrowed from the registry. It cannot be
//! cloned, and [`Drop`] releases the slot unconditionally. That matters more
//! than it looks: a reservation that could be *taken* and never *released*
//! would wedge the `(workflow, run)` pair against every future writer for the
//! life of the process — the same defect class this exists to fix, reborn one
//! level up. Release is therefore not a call any caller can forget.
//!
//! It is also **process-local and non-durable**: the [`Registry`] holds no store
//! handle and no persistence of any kind, and is rebuilt empty by `Default` at
//! every boot. A crash between reservation and append leaves no reservation (the
//! registry is gone) and no append (the store never received one) — exactly
//! where the system was.
//!
//! # Exactly one append
//!
//! [`Self::record_cancelled`] **consumes** the reservation. There is no other
//! way to reach the recorder it holds, so the type itself licenses one terminal
//! transition and then ends. That transition is byte-for-byte the shape every
//! other terminal writer records: `WorkflowCancelled`, then the run's
//! outstanding declared-timeout deadline retired under the same recorder — a
//! cancelled run must not leave an armed deadline behind.
//!
//! [`WorkflowHandle`]: super::handle::WorkflowHandle
//! [`WorkflowHandleParts`]: super::handle::WorkflowHandleParts
//! [`Registry::live_pid`]: super::table::Registry::live_pid
use Arc;
use ;
use EventStore;
use ;
use crateEngineError;
use crateRecorder;
use Registry;
/// The sole writer for a `(workflow, run)` pair that holds no handle and never
/// will under this build.
///
/// Obtained from [`Registry::reserve_terminal_writer`], which grants it only
/// when the registry can prove — under its own lock, at that moment — that the
/// workflow has no live handle and no other reservation. Held exclusively
/// against both for as long as this value lives.
///
/// `Debug` is written by hand: `dyn EventStore` is not `Debug`, and the store is
/// an implementation detail of the append rather than part of the reservation's
/// identity. What identifies it is the pair it holds.
///
/// [`Registry::reserve_terminal_writer`]: super::table::Registry::reserve_terminal_writer