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
//! The fleet-wide degraded-residency read (#117).
//!
//! `GET /workflows/unrecoverable` answers "which runs did this engine fail to
//! bring back, and why" from the live per-process set startup recovery records
//! into ([`aion::registry::UnrecoverableRuns`]).
//!
//! # Why this endpoint had to exist
//!
//! The per-run half of the same question was already answerable: `POST
//! /workflows/describe` reports a run's degraded residency once you can name the
//! run. That is exactly the thing an operator cannot do here. A run that startup
//! recovery skipped is skipped SILENTLY as far as every read surface is
//! concerned — it still projects `Running`, it still lists, it still describes —
//! and the only place its id was ever named as degraded was one ERROR line at
//! boot, in a stream that has since scrolled away. Cancelling it is now
//! possible (#117(c)), but a lever you cannot aim is not a remedy. This is the
//! read that hands over the id.
//!
//! # It reports a live condition, not a scar list
//!
//! Entries clear the moment the engine observes the run resident, so an EMPTY
//! response is the healthy answer and a non-empty one is always about right now.
//! A degraded flag that outlived its degradation would send an operator to
//! redeploy a run that is running fine, which is worse than no flag at all.
use ;
use Serialize;
use HttpCaller;
use HttpWireError;
use crate::;
/// One run this engine process could not make resident.
pub
/// The single remedy sentence, stated once.
///
/// Both remedies are real and they are ordered: redeploying the pinned version
/// makes the run recoverable on the next boot and loses nothing, so it comes
/// first; cancelling is the terminal answer for a run whose code is gone for
/// good. Naming only the second would push operators toward destroying runs
/// that a redeploy would have saved.
const REMEDY: &str = "redeploy the pinned package version to make this run recoverable, or cancel \
the run to terminate it — a run in this list is not running and will not \
resume under this build";
/// `GET /workflows/unrecoverable`.
///
/// Namespace-filtered by the caller's grant, on the same existence-leak boundary
/// `GET /namespaces` and `GET /queues/unserved` enforce: a caller must never
/// learn that a namespace it cannot access exists, so a run it cannot access is
/// dropped rather than reported. An EMPTY list is the healthy answer, not an
/// error.
///
/// Rows are returned oldest observation first. The backing set is an unordered
/// map, so SOME order has to be chosen; observation order is the one an operator
/// reading a degraded list is actually looking for, and choosing it here keeps
/// the arbitrariness out of the storage layer.
pub async
/// The read and the grant filter, apart from the transport.
///
/// Extracted so the namespace boundary can be tested against a caller with a
/// specific grant. Going through the HTTP surface for that would mean minting a
/// scoped credential per case, which tests the token path rather than the filter
/// this function is responsible for.
pub async
/// Whether this caller may be told the run exists.
///
/// An attributed run is visible on the ordinary grant check. An UNATTRIBUTED
/// run — one whose history carries no owning namespace — is visible only to a
/// caller holding every namespace.
///
/// Both halves matter and they pull in opposite directions. Hiding unattributed
/// runs from everyone would recreate the defect for exactly the runs most likely
/// to hit it: an unattributed run belongs to no tenant, so no enumerated grant
/// would ever match it and it would be permanently invisible to the only person
/// who can fix it. Showing them to enumerated callers would leak the existence
/// of runs outside their tenancy. The all-namespaces operator is the one caller
/// for whom neither is true.