Skip to main content

PolicyEngine

Struct PolicyEngine 

Source
pub struct PolicyEngine { /* private fields */ }
Expand description

Self-healing circuit-breaker policy engine.

On a memory spike it drives the ladder notify -> freeze (short) -> auto-thaw -> still high? soft-cap -> calm sustained -> lift, never issuing a kill. All of that lives in tick; the struct just holds the state needed to make decisions stable across ticks (hysteresis, cooldowns, growth).

The unit of choice is an app: every cgroup of the chosen app is frozen or capped together as one escalation step.

Implementations§

Source§

impl PolicyEngine

Source

pub fn new(cfg: GuardConfig) -> Self

Source

pub fn tick( &mut self, now_ms: u64, sample: Sample, targets: &[Target], live_cgroups: &HashSet<String>, ) -> Vec<Action>

Advance the state machine one tick and return the actions to apply.

targets are the cgroups eligible for action this tick (already filtered for uid, protect list and min RSS by the Sampler).

live_cgroups is the subset of the engine’s intervened cgroups that still hold a process (see sampler::live_cgroups), with no min-RSS or protect filtering applied; it is deliberately independent of targets. Pruning checks liveness against this set, not against targets: memory.high also bounds file-backed pages, so capping a mapped-file-heavy process can push its rss_kb below the min-RSS floor on the very next tick, dropping it out of targets even though the cgroup is very much still alive. Pruning against targets there would lift the cap while pressure is still Critical and immediately re-trigger it. Victim selection deliberately keeps using targets.

Source

pub fn wants_candidates(&self, sample: Sample) -> bool

True when the caller should gather targets for the next tick: the level would be above Calm, or memory is already scarce. Scanning while scarce keeps growth rates warm, so a sudden drop below the floor can pick the app that is growing instead of the largest one. A disabled engine never wants them.

Source

pub fn level(&self) -> Level

The pressure level as of the last tick.

Source

pub fn interventions(&self) -> Vec<(String, Intervention)>

Currently active interventions (cgroup path -> intervention), sorted by cgroup path so callers get a deterministic order.

Source

pub fn intervened_cgroups(&self) -> Vec<String>

Cgroup paths the engine currently holds an intervention on — frozen or capped. Interventions are already keyed by cgroup, so this is just the key set. For external callers (e.g. RulesEnforcer::reconcile, D1) that must not fight/revert an active guard action: rewriting memory.high on a cgroup the engine just capped would silently no-op the cap and leave PolicyEngine holding a stale Capped intervention that then blocks victim re-selection for the rest of the pressure episode.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more