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};