Skip to main content

gunnar_ssh/
governor.rs

1//! **The two load-shedding gates**: a CoDel delay governor (time) and a memory
2//! reservation ledger (space). Both refuse *at admission*, before a single byte
3//! of the operation's work has been allocated.
4//!
5//! [`Admission`](crate::Admission) is the one door; this module is the pair of
6//! locks on it. An operation is admitted only if **both** pass:
7//!
8//! ```text
9//! admit(class):
10//!     if occupied >= governed_limit          -> DENY (time:  the queue is standing)
11//!     if reserved + est(class) > budget      -> DENY (space: the budget is spoken for)
12//!     occupied += 1;  reserved += est(class)     // released by Drop, on every path
13//! ```
14//!
15//! # Gate 1 — CoDel, because it is the one that does not oscillate
16//!
17//! ## Sojourn, not queue length
18//!
19//! Queue *length* is not a saturation signal. A hundred-deep queue draining in
20//! a millisecond is a healthy server doing its job; a three-deep queue that has
21//! not moved in a second is a server that has stopped. What separates them is
22//! how long an item **waited**, so that is what is measured: the interval
23//! between admission (enqueue) and the moment the operation's work actually
24//! starts running ([`AdmissionGuard::entered_service`](crate::AdmissionGuard::entered_service)).
25//!
26//! In gunnar that interval is a real queue and not a bookkeeping fiction. Every
27//! transfer is `tokio::spawn`ed and then bridged onto a blocking-pool thread
28//! (`crate::admission` module docs); the gap between "admitted" and "the task is
29//! running" is the runtime's own ready queue plus the blocking-pool handoff.
30//! That is the *invisible* ceiling behind the unbounded listener, measured directly
31//! instead of inferred.
32//!
33//! ## Minimum, not average
34//!
35//! Over each [`INTERVAL`] window the controller keeps the **minimum** sojourn
36//! per class, never the mean. One item that got through quickly is proof the
37//! queue is not standing — it proves a path existed. An average is moved by a
38//! single outlier, so an averaging controller shrinks on noise, then grows back
39//! when the outlier ages out, then shrinks again: the oscillation CoDel exists
40//! to remove.
41//!
42//! ## Per class, and this is the crux
43//!
44//! **One queue. One shared limit. Sojourn measured per class.**
45//!
46//! The trap is head-of-line blocking of the *signal*, not of the queue. Hold
47//! one target for everything and a 25-minute `linux.git` clone — which does not
48//! care about a 150 ms wait and whose client would never notice one — reads as a
49//! catastrophically standing queue against a 5 ms bar, and the controller sheds
50//! load that the box could have served. The clone poisons the delay signal for
51//! the 10 ms `ls-remote` sharing its queue.
52//!
53//! So each class carries its own [`OpClass::target`], and the rule that sets it
54//! is **half the class's measured median service time** — a client may be made
55//! to wait at most long enough to add 50 % to its own latency. Those medians are
56//! measured, not picked round: the reference desktop, 2026-08-13, gunnar in an
57//! 8 GiB / 8-cpu cgroup.
58//!
59//! | class | measured median | target | note |
60//! |---|---:|---:|---|
61//! | ls-remote | 9–12 ms | **5 ms** | the base [`TARGET`] falls out of the measurement |
62//! | fetch | 90 ms | 45 ms | `fetch`/`diverge` |
63//! | push | 340 ms | 170 ms | `push`/`base` |
64//! | clone | 372 ms | 186 ms | `clone`/`large`; xl was 4350 ms |
65//! | gc | **NOT MEASURED** | 186 ms | no bakeoff row; borrows clone's, and says so |
66//!
67//! `ls-remote` is therefore the canary: it trips first, at exactly the 5 ms the
68//! design asked for, and the slower classes trip only when the wait is large
69//! enough to matter *to them*.
70//!
71//! ## The control law
72//!
73//! When a class's window closes, that class's window-minimum decides, and what
74//! it moves is the **one shared limit**:
75//!
76//! * minimum above the class's target for the whole window → the queue is
77//!   standing → shrink multiplicatively, `limit -= max(limit/8, 1)`;
78//! * otherwise → grow additively, `limit += 1`.
79//!
80//! Clamped to [`LimitBand`]: **[10, 100]** when no ceiling is configured, and
81//! **[10, ceiling]** when one is — an operator's explicit number is never
82//! lowered to the design's default. The `max(_, 1)` is
83//! not cosmetic: without it a limit below 8 has an integer shrink step of zero
84//! and the controller can never come down again.
85//!
86//! It starts at the top of the band. A load shedder has nothing to shed on an
87//! idle server, and starting at the floor would make a cold server refuse work
88//! it could do for the ~90 intervals (9 s) the additive climb takes.
89//!
90//! # Gate 2 — memory as a RESERVATION you own, not a measurement you take
91//!
92//! [`MemoryLedger`] is a budget and a counter. It does not ask the operating
93//! system anything, and that is the design rather than a limitation of it:
94//!
95//! * a free-memory reading is **stale the instant you take it**; a reservation
96//!   you own is exact;
97//! * it denies **before** the allocation, which is the whole principle — asking
98//!   "is memory low?" after an operation has built a multi-gigabyte buffer is
99//!   asking after the damage;
100//! * it is the fixed-pool shape: admission is "is a slab free?".
101//!
102//! ## Why this gate is not theoretical for gunnar — measured
103//!
104//! From the same bakeoff table, peak anonymous RSS on `vs_forge_clone`, on
105//! identical wire bytes: **gunnar 2314 MB, gitea 122 MB, Forgejo 167 MB**.
106//! Memory is the resource gunnar actually exhausts. The cause is known —
107//! `EmitEntry.stored` in `znippy-plugin-git/src/pack_walk.rs:931` is an owned
108//! `Vec<u8>` per object, so a clone materialises the whole pack in RAM before
109//! writing a byte — and it is being fixed elsewhere. It is not fixed here.
110//!
111//! ## The honest limitation, stated rather than papered over
112//!
113//! **A memory budget is only meaningful when an operation's footprint is bounded
114//! and predictable, and a clone's is neither today.** It is proportional to the
115//! pack, and for `linux.git` that is ~6.4 GB across ~27.6 M allocations. So
116//! [`OpClass::estimated_bytes`] is a per-class **constant**, and for
117//! [`OpClass::Clone`] that constant is a **guess** — the marginal figure from
118//! one corpus, not a bound. Until `stored` becomes an extent into the mapped
119//! archive rather than an owned copy, this gate does not bound clone memory
120//! correctly, and nothing here should be read as claiming it does. What it does
121//! do today is stop *unbounded concurrency* of a heavyweight class, which is a
122//! smaller but real property.
123//!
124//! # OS-less, by law
125//!
126//! No `/proc`, no `sysinfo`, no `getrusage`, no CPU/disk/memory probing. The
127//! only inputs are [`std::time::Instant`] and in-process counters, so this works
128//! on bare metal and in a container with equal honesty. The corollary is stated
129//! plainly on [`DEFAULT_MEMORY_BUDGET_BYTES`]: this code **cannot** know how much
130//! RAM the box has, so the default is a constant an operator on a small machine
131//! must lower.
132//!
133//! No rayon, no thread pool, no allocation on the decision path (the multicore
134//! rule: gatling, never rayon): the
135//! per-class windows are a fixed `[ClassWindow; OpClass::COUNT]` array behind one
136//! mutex touched once per transfer, not once per byte.
137
138use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
139use std::sync::Mutex;
140use std::time::{Duration, Instant};
141
142use crate::command::GitService;
143use gunnar_lfs::Operation;
144
145/// The base sojourn a queue may stand at before it counts as standing: the
146/// target for the *fastest* class, [`OpClass::LsRemote`], whose measured median
147/// service time is 9–12 ms.
148///
149/// Every other class scales off its own measurement; see [`OpClass::target`].
150pub const TARGET: Duration = Duration::from_millis(5);
151
152/// How long a class's minimum sojourn must stay above its target before the
153/// shared limit moves.
154///
155/// One window, one decision. Shorter and the controller reacts to a single slow
156/// scheduling turn; longer and a genuinely standing queue keeps standing while
157/// the controller thinks about it.
158pub const INTERVAL: Duration = Duration::from_millis(100);
159
160/// The floor the governed limit may never go below.
161///
162/// A load shedder that can shed itself to zero is a self-inflicted outage. Ten
163/// concurrent git operations is a server that is still a server.
164pub const MIN_LIMIT: usize = 10;
165
166/// The ceiling the governed limit may never go above **when no budget was
167/// declared**. A declared budget is its own ceiling; see
168/// [`LimitBand::for_budget`].
169pub const MAX_LIMIT: usize = 100;
170
171/// A declared budget's floor is `budget / this`.
172///
173/// Half. The governor may shed a saturated box down to half of what the box was
174/// measured to be able to hold, and no further: the budget's three terms —
175/// cores, descriptors, `MemAvailable` — are hard resources, and a controller
176/// reading a *latency* signal has no evidence about them. Below half, the
177/// honest answer to a client is to serve it.
178pub const BUDGET_FLOOR_DENOMINATOR: usize = 2;
179
180/// The default self-imposed memory budget for admitted operations: 8 GiB.
181///
182/// **This is a number about gunnar, not about the machine.** By the OS-less law
183/// this code cannot read the box's RAM, so it cannot size itself; 8 GiB is the
184/// cgroup the bakeoff measurement above was taken in
185/// (measured 2026-08-13), which makes it the one
186/// figure with evidence behind it rather than a round guess.
187///
188/// An operator on a smaller box **must** lower it, and one on a larger box
189/// should raise it. It covers only the footprints of operations admitted through
190/// this gate: gunnar's resident baseline (~330 MB, the `ls-remote` rows, which
191/// send no pack at all) sits outside the budget and must be left as headroom.
192pub const DEFAULT_MEMORY_BUDGET_BYTES: u64 = 8 * 1024 * 1024 * 1024;
193
194const MIB: u64 = 1024 * 1024;
195
196/// How long an operation may **wait** for a slot before it is refused.
197///
198/// # Why there is a wait at all, when this module argued there must not be
199///
200/// The original text (still above, and still right about *unbounded* queues)
201/// said a git client cannot see a queue, so a fast refusal beats a silent
202/// wait. Two of its four premises did not survive measurement:
203///
204/// * **"Queueing keeps the expensive things alive."** So does refusing. A
205///   refused client does not go away: it reconnects, and a reconnect is a
206///   *whole* SSH handshake — a new TCP connection, a new key exchange, a new
207///   signature verification — where a wait is one parked future. MEASURED on
208///   the rig (2026-08-30): at 64 concurrent clients the refusal arm
209///   spent more CPU per **served** operation than the waiting arm, because
210///   three quarters of the handshakes bought nothing.
211/// * **"A queue makes saturation invisible again."** Only an *unmeasured* one
212///   does. This queue is bounded, counted
213///   ([`crate::AdmissionStats::admitted_after_wait`],
214///   [`crate::AdmissionStats::peak_wait_ms`]) and it is the CoDel controller's
215///   input, so it is strictly more visible than the refusal it replaces.
216///
217/// Two seconds because that is well under what a client pays to retry — git
218/// itself has no backoff, so the retry is the user's or CI's, in whole seconds
219/// — and well under [`crate::SshConfig::exec_grace`] (60 s) and
220/// [`crate::SshConfig::inactivity_timeout`] (600 s), so a waiting session can
221/// never be disconnected by the timeouts that exist to kill idle ones.
222///
223/// `Duration::ZERO` restores the 2026-08-05 behaviour exactly: refuse on the
224/// spot. That is what `--admission-wait-ms 0` is for, and it is the arm the
225/// before/after table was measured against.
226pub const DEFAULT_ADMISSION_WAIT: Duration = Duration::from_secs(2);
227
228/// **How long an AUTHENTICATED caller may be queued for a slot**: 30 s.
229///
230/// The two seconds above are right for the anonymous caller this wait was
231/// argued against, and wrong for a key. MEASURED on gunnar.rs, 2026-10-25:
232/// every CI lane pushes and fetches as one key, many at once, and git-lfs's
233/// pure-SSH `git-lfs-transfer` has no retry — a refused session falls back to
234/// `git-lfs-authenticate` and the whole push fails with *"batch request: exec
235/// request failed"*. A key's parked sessions are bounded by its own share, so
236/// queueing it costs one future per session and saves a failed CI job.
237///
238/// Thirty, not more: well under [`crate::SshConfig::exec_grace`] (60 s), so a
239/// queued session is never cut off by the timeout that kills idle ones.
240pub const DEFAULT_KEYED_ADMISSION_WAIT: Duration = Duration::from_secs(30);
241
242/// The share of a transfer's **wire bytes** charged to the memory budget as it
243/// moves ([`crate::AdmissionGuard::reserve_more`]).
244///
245/// A quarter. MEASURED, not guessed: the spool bounds mean the pushed pack
246/// itself is spooled past 64 MiB and read back as a read-only mmap (page cache,
247/// reclaimable, and `MemAvailable` counts it as free), so what a transfer
248/// really holds is the per-object bookkeeping — the walk's entry table
249/// (~56 B/object), the closure check's offset set (~16 B), gunnar-wire's
250/// visited sets (~100 B) — which came to ~2.5 GB against `linux.git`'s 8.58 GiB
251/// pack (the memory limit). 2.5 / 8.58 is 0.29; a quarter
252/// is that, rounded to a shift.
253///
254/// It is a *charge*, not a prediction. Its job is that a transfer which turns
255/// out to be enormous stops **new** admissions long before the box is in
256/// trouble, without a three-object push-create having to pay for the
257/// possibility.
258pub const WIRE_MEMORY_NUMERATOR: u64 = 1;
259/// The denominator of [`WIRE_MEMORY_NUMERATOR`].
260pub const WIRE_MEMORY_DENOMINATOR: u64 = 4;
261
262/// How many bytes must cross the wire between two reservation top-ups.
263///
264/// The ledger is one atomic compare-and-swap, so this is not about the cost of
265/// the call; it is about not turning a per-byte quantity into a per-byte
266/// *decision*. 16 MiB is a quarter of the 64 MiB spool threshold, so a
267/// transfer that is about to spool has already told the ledger about itself
268/// three times.
269pub const WIRE_RESERVE_STEP: u64 = 16 * MIB;
270
271/// The three cost shapes a transfer can have, and the thing a lane floor
272/// protects.
273///
274/// See [`OpClass::lane`] for why the split exists at all, and
275/// [`Governor::lane_ceiling`] for what a floor actually reserves.
276#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
277pub enum Lane {
278    /// A ref advertisement: no pack, milliseconds, 4 MiB.
279    Cheap,
280    /// A pack **out** of the store — clone and fetch. Mostly page cache.
281    Read,
282    /// A pack **in**, and the indexer behind it — push and gc.
283    Write,
284}
285
286impl Lane {
287    /// Every lane, in index order; the per-lane arrays are sized from this.
288    pub const ALL: [Lane; 3] = [Lane::Cheap, Lane::Read, Lane::Write];
289    /// How many lanes there are.
290    pub const COUNT: usize = Lane::ALL.len();
291
292    /// Index into the per-lane arrays.
293    pub const fn index(self) -> usize {
294        match self {
295            Lane::Cheap => 0,
296            Lane::Read => 1,
297            Lane::Write => 2,
298        }
299    }
300
301    /// The name a log or a counter uses.
302    pub const fn name(self) -> &'static str {
303        match self {
304            Lane::Cheap => "cheap",
305            Lane::Read => "read",
306            Lane::Write => "write",
307        }
308    }
309
310    /// The slots of the governed limit this lane is **guaranteed**, as
311    /// `limit * numerator / denominator`, never below [`Lane::floor_min`].
312    ///
313    /// An eighth for `cheap` and a quarter for `read`: a `write` storm can take
314    /// at most five eighths of the box, so an `ls-remote` and a clone always
315    /// have somewhere to land. `write` reserves nothing, because it is the lane
316    /// that would starve the others and it is never the one that is starved —
317    /// whatever the other two are not using is its.
318    pub const fn floor_share(self) -> (usize, usize) {
319        match self {
320            Lane::Cheap => (1, 8),
321            Lane::Read => (1, 4),
322            Lane::Write => (0, 1),
323        }
324    }
325
326    /// The smallest floor a lane keeps however small the limit is.
327    ///
328    /// Two, not one: one slot means a single stuck operation closes the lane,
329    /// and a lane floor exists precisely so that a lane cannot be closed by
330    /// what is happening in another one.
331    pub const fn floor_min(self) -> usize {
332        match self {
333            Lane::Cheap | Lane::Read => 2,
334            Lane::Write => 0,
335        }
336    }
337
338    /// This lane's guaranteed slots under a governed limit of `limit`.
339    pub fn floor(self, limit: usize) -> usize {
340        let (n, d) = self.floor_share();
341        (limit * n / d).max(self.floor_min()).min(limit)
342    }
343}
344
345/// Which kind of user-level git operation is being admitted.
346///
347/// The classes exist for **one** reason: a sojourn measured across a mixed queue
348/// is a number about whichever operation happened to be slowest, so the delay
349/// signal must be split even though the queue is not.
350#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
351pub enum OpClass {
352    /// A ref advertisement and nothing else. The canary: fastest, cheapest, and
353    /// the first to notice a queue that has started to stand.
354    LsRemote,
355    /// An incremental fetch — a negotiated pack over an existing history.
356    Fetch,
357    /// A full clone. The expensive one, in time and (today, badly) in memory.
358    Clone,
359    /// A push, including LFS upload.
360    Push,
361    /// Repository maintenance.
362    Gc,
363}
364
365impl OpClass {
366    /// Every class, in index order. The per-class arrays are sized from this,
367    /// so a new variant that is not added here fails to compile rather than
368    /// silently sharing another class's window.
369    pub const ALL: [OpClass; 5] = [
370        OpClass::LsRemote,
371        OpClass::Fetch,
372        OpClass::Clone,
373        OpClass::Push,
374        OpClass::Gc,
375    ];
376
377    /// How many classes there are; the width of every per-class array here.
378    pub const COUNT: usize = OpClass::ALL.len();
379
380    /// Index into the per-class arrays.
381    pub const fn index(self) -> usize {
382        match self {
383            OpClass::LsRemote => 0,
384            OpClass::Fetch => 1,
385            OpClass::Clone => 2,
386            OpClass::Push => 3,
387            OpClass::Gc => 4,
388        }
389    }
390
391    /// The name a log or a counter uses.
392    pub const fn name(self) -> &'static str {
393        match self {
394            OpClass::LsRemote => "ls-remote",
395            OpClass::Fetch => "fetch",
396            OpClass::Clone => "clone",
397            OpClass::Push => "push",
398            OpClass::Gc => "gc",
399        }
400    }
401
402    /// The sojourn **this class** may stand at before the shared limit shrinks.
403    ///
404    /// Half the class's measured median service time
405    /// (measured on the reference desktop,
406    /// 2026-08-13): a client of
407    /// this class may be made to wait at most long enough to add 50 % to its own
408    /// latency. That rule, not a table of round numbers, is what stops a slow
409    /// class from shrinking the limit on a fast class's behalf — and it lands
410    /// [`OpClass::LsRemote`] exactly on [`TARGET`], because its measured median
411    /// is 10 ms.
412    pub const fn target(self) -> Duration {
413        match self {
414            // measured 9–12 ms → 5 ms, which IS `TARGET`.
415            OpClass::LsRemote => TARGET,
416            // measured 90 ms (`fetch`/`diverge`).
417            OpClass::Fetch => Duration::from_millis(45),
418            // measured 372 ms (`clone`/`large`; `xl` was 4350 ms, so this is the
419            // conservative end of the measured range).
420            OpClass::Clone => Duration::from_millis(186),
421            // measured 340 ms (`push`/`base`).
422            OpClass::Push => Duration::from_millis(170),
423            // NOT MEASURED: the bakeoff run of 2026-08-13 has no `vs_forge_gc`
424            // row, so this borrows clone's rather than inventing a figure. Say
425            // so here rather than let a reader assume it was measured.
426            OpClass::Gc => Duration::from_millis(186),
427        }
428    }
429
430    /// What this class reserves **at admission**, before it knows its size.
431    ///
432    /// # This used to be the whole footprint, and that was the ceiling
433    ///
434    /// Until 2026-08-30 this returned a per-class **constant equal to the whole
435    /// operation's measured peak** — 320 MiB for a push, 2 GiB for a clone —
436    /// and [`MemoryLedger`] refused anything that did not fit in
437    /// [`DEFAULT_MEMORY_BUDGET_BYTES`]. That is an arithmetic ceiling nobody
438    /// chose: 8 GiB / 320 MiB = **25 concurrent pushes on any box**, whatever
439    /// its RAM, and a three-object push-create reserved exactly as much as a
440    /// `linux.git` mirror.
441    ///
442    /// MEASURED on the native desktop rig (gunnar-solo pinned to 4 cpus / 8 GiB,
443    /// 2026-08-30): 500 push-creates at 64 concurrent clients → **118–132 of
444    /// them refused `MemoryBudget`** while the server's RSS never passed
445    /// 1.6 GB of its 8 GiB. The gate was refusing three quarters of the work to
446    /// protect a budget that was 20 % used.
447    ///
448    /// # So the reservation starts small and GROWS with the bytes on the wire
449    ///
450    /// This is the *entry* cost — the session, the state machine, the ref
451    /// advertisement, the first buffers — and it is what admission is decided
452    /// on. Everything proportional to the transfer is added afterwards by
453    /// [`crate::AdmissionGuard::reserve_more`], which the transport calls as
454    /// the pack actually arrives ([`WIRE_MEMORY_NUMERATOR`]). A gate that
455    /// charges a small push for a large one refuses work the box can do; a
456    /// gate that never charges the large one takes the box down. Charging what
457    /// has actually moved is the only rule that is right in both directions.
458    ///
459    /// The numbers below are marginal RSS per concurrent transfer, measured on
460    /// the same rig by walking the concurrency up with the gate wide open
461    /// (`rss-slope.tsv`, a scratch capture outside the repository), rounded up
462    /// to the next power of
463    /// two.
464    pub const fn admission_bytes(self) -> u64 {
465        match self {
466            // No pack at all — the ref advertisement and its framing.
467            OpClass::LsRemote => 4 * MIB,
468            // A negotiation and the first window of a pack.
469            OpClass::Fetch => 16 * MIB,
470            // Same entry cost as a fetch; a clone's real footprint is its pack,
471            // and its pack is charged as it is written.
472            OpClass::Clone => 16 * MIB,
473            // The receive state machine plus the first spool window. MEASURED
474            // 39 MB marginal per concurrent tiny push-create on the rig.
475            OpClass::Push => 32 * MIB,
476            // NOT MEASURED — no bakeoff row, no rig row. Sized at a push's,
477            // and flagged rather than asserted.
478            OpClass::Gc => 32 * MIB,
479        }
480    }
481
482    /// The **lane** this class is metered in.
483    ///
484    /// One queue is still one queue, but a lane may not be starved by another:
485    /// an `ls-remote` that costs 4 MiB and 10 ms must not wait behind an 8 GiB
486    /// mirror push, and on a saturated box it did — every class shared one
487    /// counter against one limit, so a push storm took every slot.
488    ///
489    /// Three lanes, because there are three cost shapes: the ref advertisement
490    /// (no pack), a read (a pack out of the store, mostly page cache), and a
491    /// write (a pack in, plus the indexer behind it).
492    pub const fn lane(self) -> Lane {
493        match self {
494            OpClass::LsRemote => Lane::Cheap,
495            OpClass::Fetch | OpClass::Clone => Lane::Read,
496            OpClass::Push | OpClass::Gc => Lane::Write,
497        }
498    }
499
500    /// The class an SSH `exec` request belongs to.
501    ///
502    /// # What SSH cannot tell you, and it matters
503    ///
504    /// `clone`, `fetch` and `ls-remote` are **the same exec line**:
505    /// `git-upload-pack '<path>'`. Which of the three it turns out to be is
506    /// decided later, by the protocol-v2 command the client sends inside the
507    /// stream (`ls-refs` versus `fetch`), and by whether the client had any
508    /// history to negotiate from. The admission gate runs before any of that,
509    /// by design — the entire value of this gate is refusing before the cost is
510    /// paid.
511    ///
512    /// So over SSH, `git-upload-pack` is classified [`OpClass::Fetch`]: the
513    /// middle of the three, chosen deliberately rather than by accident.
514    /// Classifying it as `Clone` would give every `ls-remote` a 2 GiB
515    /// reservation and a 186 ms delay target; as `LsRemote` it would give every
516    /// clone a 4 MiB reservation and a 5 ms target, which is the poisoned signal
517    /// this module exists to avoid.
518    ///
519    /// Callers that **do** know — the HTTP smart transport, which sees
520    /// `GET /info/refs` separately from `POST /git-upload-pack`, and `gunnar gc`,
521    /// which is not a transport at all — pass the exact class to
522    /// [`Admission::try_admit`](crate::Admission::try_admit) instead of going
523    /// through this function.
524    pub fn for_ssh_service(service: GitService) -> OpClass {
525        match service {
526            GitService::UploadPack => OpClass::Fetch,
527            GitService::ReceivePack => OpClass::Push,
528            GitService::LfsTransfer(Operation::Upload) => OpClass::Push,
529            GitService::LfsTransfer(Operation::Download) => OpClass::Fetch,
530        }
531    }
532}
533
534impl std::fmt::Display for Lane {
535    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
536        f.write_str(self.name())
537    }
538}
539
540impl std::fmt::Display for OpClass {
541    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
542        f.write_str(self.name())
543    }
544}
545
546/// The range the governed limit is clamped to.
547///
548/// Spelled as a type rather than two constants because it has to be **narrowed
549/// by an operator's configured ceiling**: a server told `--max-concurrent-transfers 4`
550/// must serve 4, not the design's floor of 10. See [`LimitBand::for_ceiling`].
551#[derive(Debug, Clone, Copy, PartialEq, Eq)]
552pub struct LimitBand {
553    /// The smallest the controller may shrink to.
554    pub min: usize,
555    /// The largest it may grow to, and where it starts.
556    pub max: usize,
557}
558
559impl LimitBand {
560    /// The design's band: **[10, 100]**.
561    pub const DEFAULT: LimitBand = LimitBand {
562        min: MIN_LIMIT,
563        max: MAX_LIMIT,
564    };
565
566    /// The band for a server whose operator pinned a hard ceiling.
567    ///
568    /// The operator's number is the ceiling, and the FLOOR is clamped under it:
569    /// pinning 4 gives `[4, 4]`, a governor that cannot move, which is exactly
570    /// what "I told you 4" should mean. A configured ceiling below
571    /// [`MIN_LIMIT`] must not be silently RAISED — a gate admitting more than
572    /// it was told to is the one failure mode a limit may not have.
573    ///
574    /// **The ceiling is NOT capped at [`MAX_LIMIT`], and that was a bug.** The
575    /// first form did `MAX_LIMIT.min(ceiling)`, so a server configured with the
576    /// shipped default of 256 got a band of `[10, 100]` and quietly served 100.
577    /// Lowering an operator's explicit number is the same defect as raising it,
578    /// in the other direction: both mean the configured value is not the value.
579    /// `MAX_LIMIT` is the design's default for a server that has NOT been told a
580    /// number — it is not an opinion that outranks one that has.
581    pub fn for_ceiling(ceiling: usize) -> LimitBand {
582        LimitBand {
583            min: MIN_LIMIT.min(ceiling),
584            max: ceiling,
585        }
586    }
587
588    /// The band for a server whose ceiling is a **declared, measured budget**
589    /// rather than a round number an operator typed.
590    ///
591    /// # Why the floor moves with the ceiling — MEASURED
592    ///
593    /// [`LimitBand::for_ceiling`] pins the floor at [`MIN_LIMIT`] = 10. With the
594    /// shipped ceiling of 256 that is a band of `[10, 256]`, and the controller
595    /// walks the whole of it: multiplicative decrease is `limit -= limit/8`, so
596    /// 256 → 224 → 196 → … → 24 → 21 → **19** → 17 … On the appliance under a
597    /// 64-client push storm every 100 ms window stands, and the measurement
598    /// took the gate refusing by name at exactly that — `already serving its
599    /// limit of 19`, 268 of 1000 push-creates admitted. **19 was not a constant
600    /// anybody chose; it is a point on a descent.**
601    ///
602    /// The descent does not stop because shedding does not fix what the
603    /// controller is measuring. The sojourn it reads was the gap between
604    /// admission and the spawned task's first line — the tokio ready queue and
605    /// the blocking-pool handoff — and that gap is set by how many clients are
606    /// *connected and doing crypto*, not by how many transfers are admitted. A
607    /// refused client reconnects, so a refusal makes the input worse. A
608    /// controller with no authority over its own input runs to its floor.
609    ///
610    /// Both halves are fixed here. The controller's input is now the
611    /// **admission wait** — the queue this gate actually owns
612    /// ([`DEFAULT_ADMISSION_WAIT`]) — and its floor is a share of the budget
613    /// rather than a constant: below [`BUDGET_FLOOR_DENOMINATOR`]`⁻¹` of a
614    /// number derived from cores, descriptors and `MemAvailable`, the box is
615    /// provably not the bottleneck and refusing costs more than serving.
616    pub fn for_budget(budget: usize) -> LimitBand {
617        LimitBand {
618            min: (budget / BUDGET_FLOOR_DENOMINATOR).clamp(MIN_LIMIT.min(budget), budget),
619            max: budget,
620        }
621    }
622
623    fn clamp(self, limit: usize) -> usize {
624        limit.clamp(self.min, self.max)
625    }
626}
627
628/// One class's sliding window.
629///
630/// `opened` is `None` until the first sample, so construction never reads the
631/// clock and a test can drive the whole controller off `Instant`s of its own.
632#[derive(Debug, Clone, Copy)]
633struct ClassWindow {
634    opened: Option<Instant>,
635    /// The **minimum** sojourn seen since the window opened. Never a sum, never
636    /// a count: an average would let one outlier shrink the limit.
637    min: Option<Duration>,
638}
639
640impl ClassWindow {
641    const EMPTY: ClassWindow = ClassWindow {
642        opened: None,
643        min: None,
644    };
645}
646
647/// The CoDel controller: per-class delay windows, one shared limit.
648#[derive(Debug)]
649pub struct Codel {
650    band: LimitBand,
651    /// The one shared limit. Read on every admission, written once per closed
652    /// window.
653    limit: AtomicUsize,
654    /// Fixed-size and preallocated: no map, no allocation, no growth.
655    windows: Mutex<[ClassWindow; OpClass::COUNT]>,
656    shrinks: AtomicU64,
657    grows: AtomicU64,
658}
659
660impl Codel {
661    /// A controller starting at the top of its band.
662    pub fn new(band: LimitBand) -> Codel {
663        Codel {
664            band,
665            limit: AtomicUsize::new(band.max),
666            windows: Mutex::new([ClassWindow::EMPTY; OpClass::COUNT]),
667            shrinks: AtomicU64::new(0),
668            grows: AtomicU64::new(0),
669        }
670    }
671
672    /// The band this controller is clamped to.
673    pub fn band(&self) -> LimitBand {
674        self.band
675    }
676
677    /// The shared limit right now.
678    pub fn limit(&self) -> usize {
679        self.limit.load(Ordering::Relaxed)
680    }
681
682    /// How many times a standing queue has shrunk the limit.
683    pub fn shrinks(&self) -> u64 {
684        self.shrinks.load(Ordering::Relaxed)
685    }
686
687    /// How many times a draining queue has grown it.
688    pub fn grows(&self) -> u64 {
689        self.grows.load(Ordering::Relaxed)
690    }
691
692    /// Record one item's sojourn, and adjust the shared limit if this closed
693    /// `class`'s window.
694    pub fn record(&self, class: OpClass, sojourn: Duration) {
695        self.record_at(class, sojourn, Instant::now());
696    }
697
698    /// [`Codel::record`] with the clock supplied.
699    ///
700    /// The seam a test drives: `Instant` cannot be constructed, but it can be
701    /// offset, so a test captures one `Instant::now()` and hands this window
702    /// boundaries to the microsecond instead of sleeping for them.
703    pub fn record_at(&self, class: OpClass, sojourn: Duration, now: Instant) {
704        let mut windows = self.windows.lock().unwrap_or_else(|e| e.into_inner());
705        let window = &mut windows[class.index()];
706
707        let opened = *window.opened.get_or_insert(now);
708        window.min = Some(match window.min {
709            Some(previous) => previous.min(sojourn),
710            None => sojourn,
711        });
712
713        if now.saturating_duration_since(opened) < INTERVAL {
714            return;
715        }
716
717        // The window is closed. Its MINIMUM decides, against THIS class's
718        // target — the head-of-line guard, in one line.
719        let standing = window.min.is_some_and(|min| min > class.target());
720        *window = ClassWindow {
721            opened: Some(now),
722            min: None,
723        };
724        drop(windows);
725
726        if standing {
727            self.shrink();
728        } else {
729            self.grow();
730        }
731    }
732
733    /// Multiplicative decrease: `limit -= max(limit/8, 1)`.
734    ///
735    /// The `max(_, 1)` is load-bearing. `limit/8` is integer division, so at a
736    /// limit of 7 the step would be 0 and a standing queue could never bring the
737    /// limit down — the controller would be dead in exactly the state it exists
738    /// for.
739    fn shrink(&self) {
740        let band = self.band;
741        let _ = self
742            .limit
743            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |limit| {
744                Some(band.clamp(limit.saturating_sub((limit / 8).max(1))))
745            });
746        self.shrinks.fetch_add(1, Ordering::Relaxed);
747    }
748
749    /// Additive increase: `limit += 1`.
750    fn grow(&self) {
751        let band = self.band;
752        let _ = self
753            .limit
754            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |limit| {
755                Some(band.clamp(limit.saturating_add(1)))
756            });
757        self.grows.fetch_add(1, Ordering::Relaxed);
758    }
759}
760
761/// Gate 2: a budget and a counter. Never a probe.
762#[derive(Debug)]
763pub struct MemoryLedger {
764    budget: u64,
765    reserved: AtomicU64,
766}
767
768impl MemoryLedger {
769    /// A ledger with `budget` bytes to give out.
770    pub fn new(budget: u64) -> MemoryLedger {
771        MemoryLedger {
772            budget,
773            reserved: AtomicU64::new(0),
774        }
775    }
776
777    /// The budget.
778    pub fn budget(&self) -> u64 {
779        self.budget
780    }
781
782    /// Bytes currently reserved by operations in flight.
783    pub fn reserved(&self) -> u64 {
784        self.reserved.load(Ordering::Relaxed)
785    }
786
787    /// Reserve `bytes`, or refuse.
788    ///
789    /// A compare-and-swap loop rather than "load, check, add": between a load
790    /// and an add, two concurrent admissions both see room and both take it, and
791    /// a budget that can be exceeded by the number of racing threads is not a
792    /// budget. Nothing is allocated here and nothing is allocated by the caller
793    /// before here — the refusal arrives before the cost.
794    pub fn try_reserve(&self, bytes: u64) -> bool {
795        self.reserved
796            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |reserved| {
797                let wanted = reserved.saturating_add(bytes);
798                (wanted <= self.budget).then_some(wanted)
799            })
800            .is_ok()
801    }
802
803    /// Charge `bytes` **whether or not they fit**, and say which it was.
804    ///
805    /// The reserve path for an operation that is already running: see
806    /// [`Growth`] for why this cannot refuse. The counter is allowed to exceed
807    /// the budget, and while it does, [`MemoryLedger::try_reserve`] refuses
808    /// every new admission — which is the whole mechanism by which one enormous
809    /// transfer quiets the box instead of taking it down.
810    pub fn charge(&self, bytes: u64) -> bool {
811        let before = self.reserved.fetch_add(bytes, Ordering::Relaxed);
812        before.saturating_add(bytes) <= self.budget
813    }
814
815    /// Give `bytes` back.
816    ///
817    /// Saturating, because a ledger that can go negative under a double release
818    /// would hand out the whole budget twice.
819    pub fn release(&self, bytes: u64) {
820        let _ = self
821            .reserved
822            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |reserved| {
823                Some(reserved.saturating_sub(bytes))
824            });
825    }
826}
827
828/// Why the governor shed an operation.
829#[derive(Debug, Clone, Copy, PartialEq, Eq)]
830pub enum Shed {
831    /// Gate 1: the governed concurrency limit is full.
832    Concurrency {
833        /// The limit in force at the moment of the refusal — the *governed*
834        /// one, which is not the configured one and moves on its own. Reported
835        /// rather than assumed, or an operator reads a number in a log that
836        /// matches nothing in a config file.
837        limit: usize,
838        /// How many operations were in flight.
839        in_flight: usize,
840    },
841    /// Gate 1b: this operation's **lane** is full, though the server as a
842    /// whole is not. The other lanes' floors are what is holding the slots; see
843    /// [`Lane::floor`].
844    LaneFull {
845        /// The lane that was full.
846        lane: Lane,
847        /// What that lane may hold under the governed limit right now.
848        ceiling: usize,
849        /// The governed server-wide limit.
850        limit: usize,
851    },
852    /// Gate 1c: the claim asked for a slot the caller had told this governor to
853    /// **hold back** ([`Governor::claim_reserving`]), though the server as a
854    /// whole is not full.
855    ///
856    /// Its own variant rather than [`Shed::Concurrency`] with a smaller `limit`
857    /// in it, because reporting a reduced limit as *the* limit is the exact
858    /// failure the unbounded listener is about: an operator would read `limit: 2` out of a log
859    /// on a box configured for 256 and conclude the gate was broken. Both
860    /// numbers travel, and the caller that supplied the reserve is the one that
861    /// gets to name the rule.
862    Reserved {
863        /// Operations in flight when the claim failed.
864        occupied: usize,
865        /// The **governed** server-wide limit — the real one, unreduced.
866        limit: usize,
867        /// How many slots of it the caller asked to be held back from this
868        /// claim.
869        reserve: usize,
870    },
871    /// Gate 2: the memory budget is spoken for.
872    Memory {
873        /// The class whose estimate did not fit.
874        class: OpClass,
875        /// What [`OpClass::estimated_bytes`] asked for.
876        wanted: u64,
877        /// What was already reserved.
878        reserved: u64,
879        /// The budget.
880        budget: u64,
881    },
882}
883
884/// What an admitted operation holds: a concurrency slot and a memory
885/// reservation, plus the instant it was admitted.
886///
887/// Deliberately **not** a `Drop` guard. The one guard is
888/// [`AdmissionGuard`](crate::AdmissionGuard), which owns this; two `Drop`s over
889/// one reservation is how a ledger comes to be released twice.
890#[derive(Debug, Clone, Copy)]
891pub struct Claim {
892    /// The class, needed to release the right reservation and to file the
893    /// sojourn under the right window.
894    pub class: OpClass,
895    /// What was reserved **at admission** ([`OpClass::admission_bytes`]).
896    /// Everything charged afterwards is counted by the guard that owns this
897    /// claim, so the release is `bytes + grown` and cannot drift.
898    pub bytes: u64,
899    /// Enqueue time — when the operation first asked for a slot, before any
900    /// wait. The sojourn is measured from here.
901    pub enqueued: Instant,
902}
903
904/// What a top-up of a claim's reservation did.
905///
906/// It is deliberately not a `Result`: an operation that is already running
907/// cannot be refused, and pretending otherwise would put a failure on a path
908/// with nothing to do about it. What an overdraw does instead is close the door
909/// behind it — `reserved > budget` makes [`MemoryLedger::try_reserve`] refuse
910/// every *new* admission until this transfer finishes, which is the graceful
911/// degradation the budget exists for.
912#[derive(Debug, Clone, Copy, PartialEq, Eq)]
913pub enum Growth {
914    /// The charge fitted inside the budget.
915    Fitted {
916        /// What this transfer now holds.
917        held: u64,
918    },
919    /// The charge did not fit and was taken anyway. New admissions are refused
920    /// until it is given back.
921    Overdrawn {
922        /// What this transfer now holds.
923        held: u64,
924        /// What the whole server now holds.
925        reserved: u64,
926        /// The budget it is over.
927        budget: u64,
928    },
929}
930
931/// Both gates, and the occupancy they meter.
932#[derive(Debug)]
933pub struct Governor {
934    codel: Codel,
935    memory: MemoryLedger,
936    /// Operations in flight. This *is* the queue occupancy — incremented inside
937    /// the same compare-and-swap that checks the limit, so there is no window in
938    /// which two admissions both see room.
939    occupied: AtomicUsize,
940    /// The same count, split by [`Lane`], so a lane floor can be enforced.
941    /// Fixed-size and preallocated: no map, no allocation on the decision path.
942    per_lane: [AtomicUsize; Lane::COUNT],
943    /// How many operations of each lane are **parked** in
944    /// [`crate::Admission::admit_within`] right now.
945    ///
946    /// This is the demand signal, and it is the whole reason lane floors are
947    /// work-conserving rather than a second wall: see
948    /// [`Governor::lane_ceiling`].
949    waiting: [AtomicUsize; Lane::COUNT],
950    shed_concurrency: AtomicU64,
951    shed_lane: AtomicU64,
952    shed_memory: AtomicU64,
953    overdrawn: AtomicU64,
954}
955
956impl Governor {
957    /// A governor over `band` with `budget` bytes of memory to give out.
958    pub fn new(band: LimitBand, budget: u64) -> Governor {
959        Governor {
960            codel: Codel::new(band),
961            memory: MemoryLedger::new(budget),
962            occupied: AtomicUsize::new(0),
963            per_lane: [const { AtomicUsize::new(0) }; Lane::COUNT],
964            waiting: [const { AtomicUsize::new(0) }; Lane::COUNT],
965            shed_concurrency: AtomicU64::new(0),
966            shed_lane: AtomicU64::new(0),
967            shed_memory: AtomicU64::new(0),
968            overdrawn: AtomicU64::new(0),
969        }
970    }
971
972    /// The delay controller.
973    pub fn codel(&self) -> &Codel {
974        &self.codel
975    }
976
977    /// The memory ledger.
978    pub fn memory(&self) -> &MemoryLedger {
979        &self.memory
980    }
981
982    /// The governed limit right now.
983    pub fn limit(&self) -> usize {
984        self.codel.limit()
985    }
986
987    /// Operations in flight right now.
988    pub fn occupied(&self) -> usize {
989        self.occupied.load(Ordering::Relaxed)
990    }
991
992    /// Operations in flight in one lane.
993    pub fn occupied_in(&self, lane: Lane) -> usize {
994        self.per_lane[lane.index()].load(Ordering::Relaxed)
995    }
996
997    /// **How many slots `lane` may hold right now**: the governed limit, less
998    /// the part of every *other* lane's floor that somebody is actually
999    /// **waiting** for.
1000    ///
1001    /// # A floor that reserves an idle lane's slots is the old bug again
1002    ///
1003    /// The per-principal cap used to bind unconditionally, and measured on the
1004    /// 32-core desktop that meant 32 served and 32 refused against
1005    /// **224 idle slots**
1006    /// (`crate::admission`). A lane floor that reserved an eighth of the box for
1007    /// `ls-remote` whether or not any `ls-remote` existed would be the same
1008    /// mistake with a different noun: it would refuse a push the box could
1009    /// serve, to keep a slot warm for a request nobody had made.
1010    ///
1011    /// So the floor is claimed **on demand**, and demand is now observable:
1012    /// since 2026-08-30 an operation over the limit *parks*
1013    /// ([`crate::Admission::admit_within`]) instead of being refused, so the
1014    /// number of parked operations per lane is a live, exact count of who is
1015    /// asking. A lane with nobody waiting reserves nothing; the instant one
1016    /// `ls-remote` parks, one slot of the cheap floor is held back and the next
1017    /// release goes to it rather than to the push storm that would otherwise
1018    /// take every slot for as long as it lasted.
1019    ///
1020    /// `min(floor, waiting)` is what makes it a floor and not a queue: a lane
1021    /// can never reserve more than [`Lane::floor`] however many of its
1022    /// operations are waiting, so `cheap` cannot starve `write` either.
1023    pub fn lane_ceiling(&self, lane: Lane, limit: usize) -> usize {
1024        let reserved_elsewhere: usize = Lane::ALL
1025            .iter()
1026            .filter(|other| **other != lane)
1027            .map(|other| other.floor(limit).min(self.waiting_in(*other)))
1028            .sum();
1029        limit.saturating_sub(reserved_elsewhere).max(1)
1030    }
1031
1032    /// Operations of `lane` parked waiting for a slot right now.
1033    pub fn waiting_in(&self, lane: Lane) -> usize {
1034        self.waiting[lane.index()].load(Ordering::Relaxed)
1035    }
1036
1037    /// Say that one operation of `lane` has started waiting.
1038    ///
1039    /// Paired with [`Governor::left_wait`] by
1040    /// [`crate::Admission::admit_within`], which is the only caller and which
1041    /// pairs them on every path including cancellation.
1042    pub fn entered_wait(&self, lane: Lane) {
1043        self.waiting[lane.index()].fetch_add(1, Ordering::Relaxed);
1044    }
1045
1046    /// Say that one operation of `lane` has stopped waiting.
1047    pub fn left_wait(&self, lane: Lane) {
1048        let _ = self.waiting[lane.index()].fetch_update(
1049            Ordering::Relaxed,
1050            Ordering::Relaxed,
1051            |waiting| Some(waiting.saturating_sub(1)),
1052        );
1053    }
1054
1055    /// Refusals by gate: (concurrency, lane, memory).
1056    pub fn shed_counts(&self) -> (u64, u64, u64) {
1057        (
1058            self.shed_concurrency.load(Ordering::Relaxed),
1059            self.shed_lane.load(Ordering::Relaxed),
1060            self.shed_memory.load(Ordering::Relaxed),
1061        )
1062    }
1063
1064    /// How many transfers have charged the ledger past its budget while
1065    /// running ([`Growth::Overdrawn`]).
1066    pub fn overdrawn(&self) -> u64 {
1067        self.overdrawn.load(Ordering::Relaxed)
1068    }
1069
1070    /// **The admission decision.** Time first, then the lane, then space, then
1071    /// take all three.
1072    ///
1073    /// Nothing is allocated on any refusal path, and nothing the operation
1074    /// needs is allocated on the success path either: a [`Claim`] is three
1075    /// `Copy` words. That is the point of the gate — the refusal has to arrive
1076    /// before the cost, or it is only a slower way of paying it.
1077    pub fn try_claim(&self, class: OpClass) -> Result<Claim, Shed> {
1078        self.claim(class, 0, true)
1079    }
1080
1081    /// [`Governor::try_claim`] or [`Governor::attempt`], chosen by the caller.
1082    pub fn claim_for(&self, class: OpClass, count: bool) -> Result<Claim, Shed> {
1083        self.claim(class, 0, count)
1084    }
1085
1086    /// [`Governor::claim_for`] against a limit `reserve` slots **lower** than
1087    /// the governed one, so that this claim can never take one of the last
1088    /// `reserve` slots.
1089    ///
1090    /// # Why the reserve is enforced here and not by the caller
1091    ///
1092    /// A caller can read [`Governor::occupied`], compare it to a threshold and
1093    /// only then ask for a claim — and that is a race, for exactly the reason
1094    /// written over the compare-and-swap below: `N` racing admissions all read
1095    /// the same occupancy and all decide they fit. Measured, on a four-slot gate
1096    /// with two hundred anonymous readers: strangers holding *transient* claims
1097    /// while they made that decision filled the server-wide gate, and a keyed
1098    /// caller arriving into that window was refused by gate 1 with
1099    /// `AtCapacity` — the reserve that existed to protect it having never been
1100    /// consulted. A limit that is checked outside the atomic that enforces it is
1101    /// not a limit.
1102    ///
1103    /// So the reserve rides in the same `fetch_update`. `N` racing strangers can
1104    /// then no more collectively exceed `limit - reserve` than they can exceed
1105    /// `limit`, and a refused one never holds a slot at all — which matters
1106    /// twice, because the refusal path of a flood is the path an attacker is
1107    /// trying to make expensive.
1108    ///
1109    /// # Why this moves no shed counter
1110    ///
1111    /// The three [`Governor::shed_counts`] counters count *this* governor's own
1112    /// gates — the limit it controls, the lane floors it computes, the ledger it
1113    /// keeps. The reserve is none of those: it is a number the caller handed in,
1114    /// for a policy the caller owns, and the caller counts it
1115    /// (`AdmissionStats::refused_keyed_reserve`). Counting it here as a
1116    /// concurrency shed would tell an operator the CoDel limit was full when it
1117    /// was nowhere near, and counting it here under a fourth name would give the
1118    /// same event two owners.
1119    pub fn claim_reserving(
1120        &self,
1121        class: OpClass,
1122        reserve: usize,
1123        count: bool,
1124    ) -> Result<Claim, Shed> {
1125        self.claim(class, reserve, count)
1126    }
1127
1128    /// [`Governor::try_claim`] without moving the shed counters.
1129    ///
1130    /// The retry inside [`crate::Admission::admit_within`] asks this door many
1131    /// times for **one** operation. Counting every ask would make
1132    /// `shed_concurrency` a count of *polls* rather than of refusals — the
1133    /// counter would read 21 where one client was refused once, which is worse
1134    /// than no counter. So the wait loop attempts without counting and counts
1135    /// once, at the end, when the refusal is final.
1136    pub fn attempt(&self, class: OpClass) -> Result<Claim, Shed> {
1137        self.claim(class, 0, false)
1138    }
1139
1140    fn claim(&self, class: OpClass, reserve: usize, count: bool) -> Result<Claim, Shed> {
1141        let limit = self.codel.limit();
1142        // What THIS claim may take. `reserve` is 0 for every ordinary caller,
1143        // in which case the two are the same number and nothing below changes.
1144        // See [`Governor::claim_reserving`] for why the reserve is applied here
1145        // rather than checked by the caller beforehand.
1146        let available = limit.saturating_sub(reserve);
1147        // Check and take in ONE compare-and-swap. "Load, compare, then add"
1148        // lets N racing admissions all read `occupied == limit - 1`.
1149        let taken = self
1150            .occupied
1151            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |occupied| {
1152                (occupied < available).then_some(occupied + 1)
1153            });
1154        if let Err(occupied) = taken {
1155            if reserve > 0 {
1156                // The caller's rule refused this, not the governor's, so the
1157                // governor's counters do not move and the governor's variant is
1158                // not used — even when the box happens to ALSO be full. Reported
1159                // this way round on purpose: a caller that supplied a reserve
1160                // has a policy reason for it, and a refusal that flipped between
1161                // two reasons depending on how full the box happened to be would
1162                // be unreadable in a log and, in `Admission`'s case, would decide
1163                // whether the caller gets parked.
1164                return Err(Shed::Reserved {
1165                    occupied,
1166                    limit,
1167                    reserve,
1168                });
1169            }
1170            if count {
1171                self.shed_concurrency.fetch_add(1, Ordering::Relaxed);
1172            }
1173            return Err(Shed::Concurrency {
1174                limit,
1175                in_flight: occupied,
1176            });
1177        }
1178
1179        // The lane, second: the server-wide limit is the resource that actually
1180        // runs out, and a lane floor is only interesting once it does.
1181        let lane = class.lane();
1182        let ceiling = self.lane_ceiling(lane, limit);
1183        let lane_taken = self.per_lane[lane.index()].fetch_update(
1184            Ordering::Relaxed,
1185            Ordering::Relaxed,
1186            |held| (held < ceiling).then_some(held + 1),
1187        );
1188        if lane_taken.is_err() {
1189            self.occupied.fetch_sub(1, Ordering::Relaxed);
1190            if count {
1191                self.shed_lane.fetch_add(1, Ordering::Relaxed);
1192            }
1193            return Err(Shed::LaneFull {
1194                lane,
1195                ceiling,
1196                limit,
1197            });
1198        }
1199
1200        let bytes = class.admission_bytes();
1201        if !self.memory.try_reserve(bytes) {
1202            // Hand the concurrency slot AND the lane slot straight back: a slot
1203            // leaked on the memory path is a server that refuses everything an
1204            // hour after start-up.
1205            self.per_lane[lane.index()].fetch_sub(1, Ordering::Relaxed);
1206            self.occupied.fetch_sub(1, Ordering::Relaxed);
1207            if count {
1208                self.shed_memory.fetch_add(1, Ordering::Relaxed);
1209            }
1210            return Err(Shed::Memory {
1211                class,
1212                wanted: bytes,
1213                reserved: self.memory.reserved(),
1214                budget: self.memory.budget(),
1215            });
1216        }
1217
1218        Ok(Claim {
1219            class,
1220            bytes,
1221            enqueued: Instant::now(),
1222        })
1223    }
1224
1225    /// **Charge a running transfer for what has actually crossed the wire.**
1226    ///
1227    /// Called by [`crate::AdmissionGuard::reserve_more`] and by nothing else,
1228    /// so the guard stays the single owner of "what this operation holds" and
1229    /// the release cannot drift. See [`Growth`] for why it cannot refuse and
1230    /// [`WIRE_MEMORY_NUMERATOR`] for what fraction of the wire is charged.
1231    pub fn charge(&self, held_after: u64, extra: u64) -> Growth {
1232        if self.memory.charge(extra) {
1233            Growth::Fitted { held: held_after }
1234        } else {
1235            self.overdrawn.fetch_add(1, Ordering::Relaxed);
1236            Growth::Overdrawn {
1237                held: held_after,
1238                reserved: self.memory.reserved(),
1239                budget: self.memory.budget(),
1240            }
1241        }
1242    }
1243
1244    /// Give a claim's slot and reservation back. Called from exactly one place:
1245    /// [`AdmissionGuard`](crate::AdmissionGuard)'s `Drop`, which passes what it
1246    /// grew the reservation to on top of [`Claim::bytes`].
1247    pub fn release(&self, claim: &Claim, grown: u64) {
1248        self.memory.release(claim.bytes.saturating_add(grown));
1249        let lane = claim.class.lane();
1250        let _ = self.per_lane[lane.index()].fetch_update(
1251            Ordering::Relaxed,
1252            Ordering::Relaxed,
1253            |held| Some(held.saturating_sub(1)),
1254        );
1255        let _ = self
1256            .occupied
1257            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |occupied| {
1258                Some(occupied.saturating_sub(1))
1259            });
1260    }
1261
1262    /// File one **admission wait** against its class's window.
1263    ///
1264    /// This is the controller's input, and the change of input is the point:
1265    /// see [`LimitBand::for_budget`] for what it used to be (the runtime's
1266    /// spawn-to-run gap) and why a controller that cannot move its own input
1267    /// runs to its floor. A wait of zero — the ordinary case on an unloaded
1268    /// server — is a sample too, and it is the one that grows the limit back.
1269    pub fn record_sojourn(&self, class: OpClass, sojourn: Duration) {
1270        self.codel.record(class, sojourn);
1271    }
1272}
1273
1274/// A one-shot latch for "this operation's work has actually started".
1275///
1276/// Its own type so the "was the sojourn ever measured?" question has one
1277/// answer-holder rather than a bool copied into two structs.
1278#[derive(Debug, Default)]
1279pub struct ServiceMark(AtomicBool);
1280
1281impl ServiceMark {
1282    /// Claim the mark. `true` the first time, `false` for every later call, so a
1283    /// caller that marks twice files one sample rather than two.
1284    pub fn claim(&self) -> bool {
1285        !self.0.swap(true, Ordering::Relaxed)
1286    }
1287
1288    /// Whether the mark was ever claimed.
1289    pub fn claimed(&self) -> bool {
1290        self.0.load(Ordering::Relaxed)
1291    }
1292}
1293
1294#[cfg(test)]
1295mod tests {
1296    use super::*;
1297
1298    /// Drive `class` through exactly one closed window at `sojourn`.
1299    ///
1300    /// Two samples: one to open the window, one at `INTERVAL` later to close it.
1301    /// Returns the instant the window closed, so a caller can chain windows.
1302    fn one_window(codel: &Codel, class: OpClass, sojourn: Duration, from: Instant) -> Instant {
1303        codel.record_at(class, sojourn, from);
1304        let closed = from + INTERVAL;
1305        codel.record_at(class, sojourn, closed);
1306        closed
1307    }
1308
1309    /// **A standing queue shrinks the limit.**
1310    ///
1311    /// # Seen red
1312    ///
1313    /// By changing `Codel::record_at`'s decision to
1314    /// `let standing = window.min.is_some_and(|min| min > INTERVAL);` — i.e.
1315    /// comparing the window minimum against the window length instead of the
1316    /// class's target, the natural "off by one constant" of this controller.
1317    /// Failure:
1318    ///
1319    /// ```text
1320    /// a queue standing at 50ms against a 5ms target did not shrink the limit:
1321    /// it is still 100 after 8 closed windows (shrinks=0)
1322    /// ```
1323    #[test]
1324    fn a_standing_queue_shrinks_the_limit() {
1325        let codel = Codel::new(LimitBand::DEFAULT);
1326        assert_eq!(
1327            codel.limit(),
1328            MAX_LIMIT,
1329            "a governor starts at the top of its band"
1330        );
1331
1332        // Ten times the ls-remote target, for eight windows.
1333        let mut at = Instant::now();
1334        for _ in 0..8 {
1335            at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(50), at);
1336        }
1337
1338        assert!(
1339            codel.limit() < MAX_LIMIT,
1340            "a queue standing at 50ms against a {:?} target did not shrink the limit: it is \
1341             still {} after 8 closed windows (shrinks={})",
1342            OpClass::LsRemote.target(),
1343            codel.limit(),
1344            codel.shrinks()
1345        );
1346        assert_eq!(
1347            codel.shrinks(),
1348            8,
1349            "every closed standing window must shrink"
1350        );
1351        // 100 → 88 → 78 → 69 → 61 → 54 → 48 → 42 → 37: multiplicative, not -8.
1352        assert_eq!(
1353            codel.limit(),
1354            37,
1355            "the decrease must be MULTIPLICATIVE (limit -= limit/8); an additive one would \
1356             leave a different number here and would not back off fast enough to matter"
1357        );
1358        assert_eq!(codel.grows(), 0);
1359    }
1360
1361    /// **A draining queue grows the limit.**
1362    ///
1363    /// # Seen red
1364    ///
1365    /// By making `Codel::grow` a no-op (`fn grow(&self) { }`). Failure:
1366    ///
1367    /// ```text
1368    /// a queue draining at 1ms did not grow the limit: 10 after 20 closed
1369    /// windows, and a controller that only shrinks is a ratchet
1370    /// ```
1371    #[test]
1372    fn a_draining_queue_grows_the_limit() {
1373        let codel = Codel::new(LimitBand::DEFAULT);
1374        // Start from the floor so growth is visible: shrink it there first.
1375        let mut at = Instant::now();
1376        for _ in 0..40 {
1377            at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(50), at);
1378        }
1379        assert_eq!(
1380            codel.limit(),
1381            MIN_LIMIT,
1382            "the standing phase must reach the floor"
1383        );
1384
1385        for _ in 0..20 {
1386            at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(1), at);
1387        }
1388        assert!(
1389            codel.limit() > MIN_LIMIT,
1390            "a queue draining at 1ms did not grow the limit: {} after 20 closed windows, and a \
1391             controller that only shrinks is a ratchet",
1392            codel.limit()
1393        );
1394        assert_eq!(
1395            codel.limit(),
1396            MIN_LIMIT + 20,
1397            "growth must be ADDITIVE, one per closed draining window"
1398        );
1399    }
1400
1401    /// **The limit never leaves its band**, in either direction, however long
1402    /// the load runs.
1403    ///
1404    /// # Seen red
1405    ///
1406    /// By dropping the clamp from `Codel::shrink`
1407    /// (`Some(limit.saturating_sub((limit / 8).max(1)))`). Failure:
1408    ///
1409    /// ```text
1410    /// the limit left the band: 9 is outside [10, 100]
1411    /// ```
1412    ///
1413    /// It fails on the FIRST step past the floor, not after drifting to zero,
1414    /// which is what makes the assertion inside the loop worth having: a check
1415    /// only at the end would report `0` and hide when it started.
1416    #[test]
1417    fn the_limit_never_leaves_the_band() {
1418        let codel = Codel::new(LimitBand::DEFAULT);
1419        let mut at = Instant::now();
1420
1421        // Far past the floor.
1422        for _ in 0..200 {
1423            at = one_window(&codel, OpClass::LsRemote, Duration::from_secs(1), at);
1424            let limit = codel.limit();
1425            assert!(
1426                (MIN_LIMIT..=MAX_LIMIT).contains(&limit),
1427                "the limit left the band: {limit} is outside [{MIN_LIMIT}, {MAX_LIMIT}]"
1428            );
1429        }
1430        assert_eq!(codel.limit(), MIN_LIMIT);
1431
1432        // …and far past the ceiling.
1433        for _ in 0..500 {
1434            at = one_window(&codel, OpClass::LsRemote, Duration::from_micros(1), at);
1435            let limit = codel.limit();
1436            assert!(
1437                (MIN_LIMIT..=MAX_LIMIT).contains(&limit),
1438                "the limit left the band: {limit} is outside [{MIN_LIMIT}, {MAX_LIMIT}]"
1439            );
1440        }
1441        assert_eq!(codel.limit(), MAX_LIMIT);
1442    }
1443
1444    /// **THE HEAD-OF-LINE TEST.** A slow class does not shrink the limit on a
1445    /// fast class's behalf.
1446    ///
1447    /// A `linux.git` clone waiting 150 ms is a clone that has not noticed. An
1448    /// `ls-remote` waiting 150 ms has had its latency multiplied by fifteen.
1449    /// One number cannot say both, so the target is per class — and this test is
1450    /// the difference between the two designs.
1451    ///
1452    /// # Seen red
1453    ///
1454    /// By replacing the per-class bar in `Codel::record_at` with the single
1455    /// shared one the naive design has:
1456    /// `let standing = window.min.is_some_and(|min| min > TARGET);`
1457    /// Failure:
1458    ///
1459    /// ```text
1460    /// a clone waiting 150ms — well inside its own 186ms target, and a wait its
1461    /// client cannot perceive — shrank the shared limit to 42. That is the
1462    /// slow class poisoning the fast class's delay signal, which is the exact
1463    /// trap per-class sojourn exists to close (shrinks=8)
1464    /// ```
1465    #[test]
1466    fn a_slow_class_does_not_shrink_the_limit_on_a_fast_class_behalf() {
1467        let codel = Codel::new(LimitBand::DEFAULT);
1468        let mut at = Instant::now();
1469
1470        // Eight windows of clones waiting 150 ms — thirty times the ls-remote
1471        // target, and comfortably INSIDE clone's own 186 ms target.
1472        assert!(Duration::from_millis(150) > OpClass::LsRemote.target());
1473        assert!(Duration::from_millis(150) < OpClass::Clone.target());
1474        for _ in 0..8 {
1475            at = one_window(&codel, OpClass::Clone, Duration::from_millis(150), at);
1476        }
1477        assert_eq!(
1478            codel.limit(),
1479            MAX_LIMIT,
1480            "a clone waiting 150ms — well inside its own {:?} target, and a wait its client \
1481             cannot perceive — shrank the shared limit to {}. That is the slow class poisoning \
1482             the fast class's delay signal, which is the exact trap per-class sojourn exists to \
1483             close (shrinks={})",
1484            OpClass::Clone.target(),
1485            codel.limit(),
1486            codel.shrinks()
1487        );
1488        assert_eq!(codel.shrinks(), 0);
1489
1490        // The other half of the bar, or the test above would also pass on a
1491        // controller that had simply stopped shrinking: the SAME 150 ms, filed
1492        // under ls-remote, must shrink hard.
1493        for _ in 0..8 {
1494            at = one_window(&codel, OpClass::LsRemote, Duration::from_millis(150), at);
1495        }
1496        assert!(
1497            codel.limit() < MAX_LIMIT,
1498            "150ms of ls-remote sojourn is thirty times its {:?} target and MUST shed load; a \
1499             controller that shrinks for nobody is not a controller",
1500            OpClass::LsRemote.target()
1501        );
1502        assert_eq!(codel.shrinks(), 8);
1503
1504        // …and the clone class is still healthy while the shared limit came
1505        // down. One queue, one limit, two signals.
1506        let before = codel.limit();
1507        let shrinks_before = codel.shrinks();
1508        for _ in 0..4 {
1509            at = one_window(&codel, OpClass::Clone, Duration::from_millis(150), at);
1510        }
1511        assert!(
1512            codel.limit() > before,
1513            "the clone class must still read as DRAINING and grow the shared limit back from \
1514             {before}, even though its absolute sojourn is thirty times the ls-remote target; \
1515             it is {} instead",
1516            codel.limit()
1517        );
1518        assert_eq!(
1519            codel.shrinks(),
1520            shrinks_before,
1521            "not one of those clone windows may be read as standing"
1522        );
1523    }
1524
1525    /// Each class keeps its **own** window: a sample filed under one class may
1526    /// not open, close or lower another's.
1527    ///
1528    /// # Seen red
1529    ///
1530    /// By indexing every class into slot 0 in `Codel::record_at`
1531    /// (`&mut windows[0]`). Failure:
1532    ///
1533    /// ```text
1534    /// assertion `left == right` failed: push's own windows must close and grow
1535    ///   left: 10
1536    ///  right: 9
1537    /// ```
1538    ///
1539    /// The tenth growth is the ls-remote sample's own window being closed by a
1540    /// push, which is exactly the crossing this test forbids — one class's
1541    /// sample opening and closing another's window.
1542    #[test]
1543    fn a_sample_lands_in_its_own_class_window_only() {
1544        let codel = Codel::new(LimitBand::DEFAULT);
1545        let at = Instant::now();
1546
1547        // Open ls-remote's window, then push a full INTERVAL of PUSH samples
1548        // through. Nothing may close ls-remote's window but an ls-remote sample.
1549        codel.record_at(OpClass::LsRemote, Duration::from_millis(50), at);
1550        for step in 0..10 {
1551            codel.record_at(
1552                OpClass::Push,
1553                Duration::from_millis(1),
1554                at + INTERVAL * (step + 1),
1555            );
1556        }
1557        // Push closed its own windows and they were healthy, so it GREW.
1558        assert_eq!(codel.grows(), 9, "push's own windows must close and grow");
1559        assert_eq!(
1560            codel.shrinks(),
1561            0,
1562            "a push sample closed the ls-remote window: shrinks={} grows={} after one ls-remote \
1563             sample that could not have closed anything",
1564            codel.shrinks(),
1565            codel.grows()
1566        );
1567    }
1568
1569    /// **Reserving up to the budget admits; the next operation is denied.**
1570    ///
1571    /// # Seen red
1572    ///
1573    /// By making `MemoryLedger::try_reserve` compare `reserved` rather than
1574    /// `reserved + bytes` against the budget — the classic off-by-one-operation
1575    /// budget check, which lets the last admission overshoot by a whole
1576    /// estimate. Failure:
1577    ///
1578    /// ```text
1579    /// the ledger admitted 5 clones against a 4-clone budget: 10737418240
1580    /// reserved of 8589934592
1581    /// ```
1582    #[test]
1583    fn the_budget_admits_up_to_itself_and_then_denies() {
1584        let clone = OpClass::Clone.admission_bytes();
1585        let ledger = MemoryLedger::new(clone * 4);
1586
1587        let mut admitted = 0;
1588        while ledger.try_reserve(clone) {
1589            admitted += 1;
1590            assert!(
1591                admitted <= 4,
1592                "the ledger admitted {admitted} clones against a 4-clone budget: {} reserved of {}",
1593                ledger.reserved(),
1594                ledger.budget()
1595            );
1596        }
1597        assert_eq!(admitted, 4, "a 4-clone budget must admit exactly 4 clones");
1598        assert_eq!(ledger.reserved(), ledger.budget());
1599
1600        // …and a SMALLER operation still fits nowhere, which is the property a
1601        // "there is some room" check would lose.
1602        assert!(
1603            !ledger.try_reserve(1),
1604            "a full ledger handed out one more byte"
1605        );
1606    }
1607
1608    /// **A completed operation releases its reservation and the next one is
1609    /// then admitted.**
1610    ///
1611    /// # Seen red
1612    ///
1613    /// By making `MemoryLedger::release` a no-op. Failure:
1614    ///
1615    /// ```text
1616    /// the 4th clone finished and gave its 2147483648 bytes back, but the next
1617    /// clone was still refused: 8589934592 reserved of 8589934592. A budget
1618    /// that is never released is a server that wedges after N operations
1619    /// ```
1620    #[test]
1621    fn a_completed_operation_releases_its_reservation() {
1622        let clone = OpClass::Clone.admission_bytes();
1623        let ledger = MemoryLedger::new(clone * 4);
1624        for _ in 0..4 {
1625            assert!(ledger.try_reserve(clone));
1626        }
1627        assert!(!ledger.try_reserve(clone), "the budget is full");
1628
1629        ledger.release(clone);
1630        assert!(
1631            ledger.try_reserve(clone),
1632            "the 4th clone finished and gave its {clone} bytes back, but the next clone was \
1633             still refused: {} reserved of {}. A budget that is never released is a server that \
1634             wedges after N operations",
1635            ledger.reserved(),
1636            ledger.budget()
1637        );
1638    }
1639
1640    /// **The budget is never exceeded, however hard it is raced.**
1641    ///
1642    /// # This test was HOLLOW twice, and both failures are worth keeping
1643    ///
1644    /// 1. First written as 64 `thread::spawn`s in a loop, it **passed against a
1645    ///    deliberately broken `try_reserve`**: spawning a thread costs orders of
1646    ///    magnitude more than the three instructions being raced, so the racers
1647    ///    arrived one at a time. A concurrency test whose threads never overlap
1648    ///    is a test of `thread::spawn`.
1649    /// 2. Adding a `Barrier` was not enough either — five runs, still green.
1650    ///    One release of 64 threads gives the bug exactly one chance to happen
1651    ///    inside a window a few nanoseconds wide.
1652    ///
1653    /// What makes it fail is **many chances at the boundary**: a budget of four
1654    /// slabs, every thread cycling reserve/release, so the "is there room for
1655    /// one more" edge is crossed millions of times instead of once. The
1656    /// invariant is checked by the racers themselves, not after the fact.
1657    ///
1658    /// # Seen red
1659    ///
1660    /// By rewriting `try_reserve` as load / compare / `fetch_add`, which is what
1661    /// it looks like it could be. On the reference desktop, 2026-08-14:
1662    ///
1663    /// ```text
1664    /// 32 racers cycling 20000 times each drove the ledger to 23068672 bytes
1665    /// against a budget of 4194304: it was exceeded by 18874368 bytes, which
1666    /// is a budget that the number of concurrent admissions can walk straight
1667    /// past
1668    /// ```
1669    ///
1670    /// Five and a half times the budget. The naive version does not overshoot
1671    /// by one slab, it overshoots by however many threads are in the window.
1672    #[test]
1673    fn the_budget_is_not_exceeded_by_racing_admissions() {
1674        use std::sync::{Arc, Barrier};
1675
1676        let slab = 1024 * 1024u64;
1677        let slabs = 4u64;
1678        let racers = 32;
1679        let rounds = 20_000;
1680        let budget = slab * slabs;
1681        let ledger = Arc::new(MemoryLedger::new(budget));
1682        // The high-water mark any racer ever SAW, which is the applied output:
1683        // a budget is not a budget if a reader can observe it exceeded.
1684        let peak = Arc::new(AtomicU64::new(0));
1685        let gate = Arc::new(Barrier::new(racers));
1686
1687        // Plain std threads: these are one-shot racers, not data-parallel work,
1688        // so there is nothing for gatling to rotate over and rayon is forbidden
1689        // outright (the multicore rule: gatling, never rayon).
1690        let threads: Vec<_> = (0..racers)
1691            .map(|_| {
1692                let ledger = Arc::clone(&ledger);
1693                let peak = Arc::clone(&peak);
1694                let gate = Arc::clone(&gate);
1695                std::thread::spawn(move || {
1696                    gate.wait();
1697                    for _ in 0..rounds {
1698                        if ledger.try_reserve(slab) {
1699                            peak.fetch_max(ledger.reserved(), Ordering::Relaxed);
1700                            ledger.release(slab);
1701                        }
1702                    }
1703                })
1704            })
1705            .collect();
1706        for thread in threads {
1707            thread.join().expect("racer");
1708        }
1709
1710        assert_eq!(
1711            ledger.reserved(),
1712            0,
1713            "every reservation was released, so the ledger must be empty"
1714        );
1715        assert!(
1716            peak.load(Ordering::Relaxed) <= budget,
1717            "{} racers cycling {rounds} times each drove the ledger to {} bytes against a budget \
1718             of {budget}: it was exceeded by {} bytes, which is a budget that the number of \
1719             concurrent admissions can walk straight past",
1720            racers,
1721            peak.load(Ordering::Relaxed),
1722            peak.load(Ordering::Relaxed) - budget
1723        );
1724        // …and the racers really did reach the boundary, or the assertion above
1725        // passed on a ledger nobody ever filled.
1726        assert_eq!(
1727            peak.load(Ordering::Relaxed),
1728            budget,
1729            "the ledger never actually filled ({} of {budget}), so the boundary this test is \
1730             about was never crossed",
1731            peak.load(Ordering::Relaxed)
1732        );
1733    }
1734
1735    /// A memory refusal must give the **concurrency** slot straight back.
1736    ///
1737    /// # Seen red
1738    ///
1739    /// By deleting the `self.occupied.fetch_sub(1, ...)` from the memory arm of
1740    /// `Governor::try_claim`. Failure:
1741    ///
1742    /// ```text
1743    /// 40 memory refusals leaked 40 concurrency slots: occupied is 44 with 4
1744    /// operations actually in flight, so the gate now refuses on TIME for a
1745    /// reason that has nothing to do with time
1746    /// ```
1747    #[test]
1748    fn a_memory_refusal_does_not_leak_a_concurrency_slot() {
1749        let clone = OpClass::Clone.admission_bytes();
1750        let governor = Governor::new(LimitBand::DEFAULT, clone * 4);
1751        let held: Vec<_> = (0..4)
1752            .map(|i| {
1753                governor
1754                    .try_claim(OpClass::Clone)
1755                    .unwrap_or_else(|shed| panic!("clone {i} of 4 was shed: {shed:?}"))
1756            })
1757            .collect();
1758
1759        for _ in 0..40 {
1760            let shed = governor
1761                .try_claim(OpClass::Clone)
1762                .expect_err("the budget is full");
1763            assert!(matches!(shed, Shed::Memory { .. }), "{shed:?}");
1764        }
1765        assert_eq!(
1766            governor.occupied(),
1767            4,
1768            "40 memory refusals leaked {} concurrency slots: occupied is {} with 4 operations \
1769             actually in flight, so the gate now refuses on TIME for a reason that has nothing \
1770             to do with time",
1771            governor.occupied() - 4,
1772            governor.occupied()
1773        );
1774
1775        for claim in &held {
1776            governor.release(claim, 0);
1777        }
1778        assert_eq!(governor.occupied(), 0);
1779        assert_eq!(governor.memory().reserved(), 0);
1780    }
1781
1782    /// The operator's ceiling is the upper bound of the whole band, floor
1783    /// included.
1784    ///
1785    /// # Seen red
1786    ///
1787    /// By writing `LimitBand::for_ceiling` as `{ min: MIN_LIMIT, max: MAX_LIMIT.min(ceiling) }`
1788    /// — the obvious version. Failure:
1789    ///
1790    /// ```text
1791    /// assertion `left == right` failed: a server told to serve 4 has a band of
1792    /// [10, 4] and a limit of 4: the governor admits more than the operator
1793    /// configured
1794    ///   left: LimitBand { min: 10, max: 4 }
1795    ///  right: LimitBand { min: 4, max: 4 }
1796    /// ```
1797    ///
1798    /// An inverted band — `min` above `max` — which `usize::clamp` panics on
1799    /// the moment the controller tries to move. The band has to be well formed
1800    /// at construction, not corrected later.
1801    #[test]
1802    fn a_configured_ceiling_below_the_floor_is_still_the_ceiling() {
1803        let band = LimitBand::for_ceiling(4);
1804        assert_eq!(
1805            band,
1806            LimitBand { min: 4, max: 4 },
1807            "a server told to serve 4 has a band of [{}, {}] and a limit of {}: the governor \
1808             admits more than the operator configured",
1809            band.min,
1810            band.max,
1811            Codel::new(band).limit()
1812        );
1813        assert_eq!(Codel::new(band).limit(), 4);
1814
1815        // ★ A ceiling ABOVE the design default is honoured, not capped.
1816        //
1817        // The first form did `MAX_LIMIT.min(ceiling)`, so the shipped default of
1818        // 256 became a band of [10, 100] and the server quietly served 100.
1819        // Lowering an operator's explicit number is the same defect as raising
1820        // it. Seen RED by restoring that `.min()`: left `LimitBand { min: 10,
1821        // max: 100 }`, right `LimitBand { min: 10, max: 256 }`.
1822        assert_eq!(
1823            LimitBand::for_ceiling(256),
1824            LimitBand { min: 10, max: 256 },
1825            "a configured ceiling of 256 was lowered to the design's default"
1826        );
1827        assert_eq!(LimitBand::for_ceiling(32), LimitBand { min: 10, max: 32 });
1828        // With no ceiling configured, the design's band still applies.
1829        assert_eq!(LimitBand::DEFAULT, LimitBand { min: 10, max: 100 });
1830    }
1831
1832    /// Every class has a distinct index, or two classes share a window and the
1833    /// head-of-line guard is silently off.
1834    #[test]
1835    fn every_class_has_its_own_window_slot() {
1836        let mut seen = [false; OpClass::COUNT];
1837        for class in OpClass::ALL {
1838            assert!(
1839                !std::mem::replace(&mut seen[class.index()], true),
1840                "{class} shares window slot {} with another class",
1841                class.index()
1842            );
1843        }
1844        assert!(seen.iter().all(|&s| s));
1845    }
1846
1847    /// The service mark is one-shot, so a caller that marks twice files one
1848    /// sojourn sample rather than two.
1849    #[test]
1850    fn the_service_mark_is_one_shot() {
1851        let mark = ServiceMark::default();
1852        assert!(!mark.claimed());
1853        assert!(mark.claim(), "the first claim wins");
1854        assert!(!mark.claim(), "the second claim must not");
1855        assert!(mark.claimed());
1856    }
1857}