Skip to main content

hyperi_rustlib/governor/
mod.rs

1// Project:   hyperi-rustlib
2// File:      src/governor/mod.rs
3// Purpose:   Unified self-regulation pressure governor
4// Language:  Rust
5//
6// License:   BUSL-1.1
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Unified self-regulation governor.
10//!
11//! Combines a set of [`PressureSource`]s into a single normalised
12//! [`level`](UnifiedPressure::level) and a hysteretic
13//! [`should_hold`](UnifiedPressure::should_hold) latch that downstream
14//! stages consult to decide whether to pause inbound work. Feature-gated
15//! (`governor`) and **ON by default** (opt-out `self_regulation.enabled =
16//! false`).
17//!
18//! The pieces: [`UnifiedPressure`] (the latch over the sources),
19//! [`InboundGate`] (turns the latch into pause/resume EDGES on the inbound
20//! source -- never the sink), [`ByteBudgetController`] (the AIMD lever sizing
21//! the streaming sub-block budget), [`SelfRegulationConfig`] (the cascade
22//! `self_regulation` section), and [`SelfRegulationGovernor`] (the built
23//! bundle the runtime threads into transports + driver).
24//!
25//! Full picture in the docs: `docs/SELF-REGULATION.md` (the three brains --
26//! memory is the HARD source of truth, CPU deliberately dropped),
27//! `docs/BACKPRESSURE.md` (gate the source, never the sink), and
28//! `docs/KAFKA-PATH.md` (the three batch sizes + the rho ~ 0.7 loop).
29//!
30//! # Design invariants
31//!
32//! - **HARD signals are never masked.** A HARD source (e.g. the memory
33//!   guard) contributes its raw reading to the level with no weight applied.
34//!   A saturated SOFT signal can never lower the level below what the HARD
35//!   signal demands, nor can a missing HARD signal be hidden by a busy SOFT
36//!   one. This is the never-OOM guarantee: the memory signal always gets
37//!   through.
38//! - **SOFT signals are weighted.** Each SOFT source's reading is scaled by
39//!   its [`weight`](PressureSource::weight) before competing for the level.
40//!   A low-weight SOFT source at full saturation cannot force a hold the
41//!   HARD signal would not.
42//! - **Hysteresis prevents flapping.** The latch arms at `pause_above` and
43//!   releases at `resume_below`; between the two it holds its current state,
44//!   so a reading oscillating around a single threshold cannot rapidly
45//!   toggle pause/resume.
46//!
47//! New source kinds (e.g. a future CPU source) plug in via
48//! [`UnifiedPressure::add_source`] with zero change to the gate API.
49
50mod budget;
51mod config;
52mod gate;
53mod runtime;
54mod source;
55
56pub use budget::{ByteBudgetConfig, ByteBudgetController};
57pub use config::{SelfRegulationConfig, SelfRegulationProfile};
58pub use gate::{Admit, GateActuator, InboundGate, NoopActuator, ObservingActuator};
59pub use runtime::SelfRegulationGovernor;
60pub use source::{
61    Hysteresis, MemoryPressureSource, Pressure, PressureSource, UnifiedPressure,
62    UnifiedPressureSnapshot,
63};