pub struct RuleCache { /* private fields */ }Expand description
Per-instance cache of Vec<Rule> keyed by AgentAction::kind().
The cache is owned by a Connection-bearing context (HTTP
AppState, MCP main loop, or the substrate GOVERNANCE_PRE_WRITE
/ GOVERNANCE_PRE_ACTION hook installer that captures a
long-lived Connection). Pass &RuleCache (or wrap in Arc for
shared ownership) to the cached entry points
(check_agent_action_cached, etc.). Cache hits return an
Arc<Vec<Rule>> clone — no row data is cloned on the fast path.
Implementations§
Source§impl RuleCache
impl RuleCache
Sourcepub fn get_or_load(
&self,
conn: &Connection,
kind: &str,
) -> Result<Arc<Vec<Rule>>, RuleCacheError>
pub fn get_or_load( &self, conn: &Connection, kind: &str, ) -> Result<Arc<Vec<Rule>>, RuleCacheError>
Return the cached rule list for kind, loading via
crate::governance::rules_store::list_enabled_by_kind on
cache miss. The Ed25519 signature verify side-effect on the
loader path runs on miss; cache hits skip it.
v0.7.0 #1020 (Agent-1 #6) — returns the typed
RuleCacheError enum at the substrate-public boundary
(was bare anyhow::Result pre-#1020).
RuleCacheError: Into<anyhow::Error> is implemented so
existing anyhow-chained callers can keep their ? operator
with no signature changes.
§Errors
RuleCacheError::Loadwraps any error fromlist_enabled_by_kind(rusqlite errors, signature-verify panics).RuleCacheError::Poisonedindicates the innerRwLockis poisoned by a prior thread panic. The legacy fallback returned a fresh snapshot anyway; callers wanting that posture can branch viaRuleCacheError::is_poisonedand re-calllist_enabled_by_kinddirectly.
Sourcepub fn invalidate(&self, kind: &str)
pub fn invalidate(&self, kind: &str)
Drop the cached entry for kind. Currently no caller takes
this path because the rules_store writers don’t know the
affected kind without inspecting the row;
Self::invalidate_all is simpler.
Sourcepub fn invalidate_all(&self)
pub fn invalidate_all(&self)
Drop every cached entry. Used by the rules_store write paths (insert / remove / set_enabled / update_signature) so the next reader rebuilds against the post-write state.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Number of currently-cached entries — for test inspection.
#1018 (2026-05-21): poison semantics changed from “lie as
empty” to “return None via Self::len_checked”. The legacy
len() returns 0 on poison (matches the pre-#1018 contract
some tests still depend on); call sites that need to
distinguish “empty” from “poisoned” use len_checked.
Sourcepub fn len_checked(&self) -> Option<usize>
pub fn len_checked(&self) -> Option<usize>
#1018 (2026-05-21): poison-aware variant of Self::len.
Returns Some(len) on a healthy lock, None if the RwLock
is poisoned. Pre-#1018 a poisoned cache reported len() == 0
and is_empty() == true — invisible to callers and test
assertions. Operator inspection paths + future health-probe
surfaces should consume this variant; legacy paths keep len().
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether the cache is empty — for test inspection.
#1018: the legacy contract treats poison as “empty” (returns
true). Use Self::is_empty_checked when the distinction
matters.
Sourcepub fn is_empty_checked(&self) -> Option<bool>
pub fn is_empty_checked(&self) -> Option<bool>
#1018 (2026-05-21): poison-aware variant of Self::is_empty.
Returns Some(true) when the cache is healthy AND empty,
Some(false) when healthy AND populated, None when the
RwLock is poisoned. Operator inspection paths use this.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for RuleCache
impl RefUnwindSafe for RuleCache
impl Send for RuleCache
impl Sync for RuleCache
impl Unpin for RuleCache
impl UnsafeUnpin for RuleCache
impl UnwindSafe for RuleCache
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more