pub struct RuleEngine { /* private fields */ }Implementations§
Source§impl RuleEngine
impl RuleEngine
pub fn new() -> Self
pub fn rules(&self) -> impl Iterator<Item = &RuleDef>
pub fn is_owned(&self, etype: u32, src: u32, dst: u32) -> bool
Sourcepub fn provenance(&self) -> &BTreeMap<String, BTreeSet<(u32, u32, u32)>>
pub fn provenance(&self) -> &BTreeMap<String, BTreeSet<(u32, u32, u32)>>
Read-only view of the provenance map: rule name → set of (etype_sym, src, dst).
Triggers a one-time lazy decode from retained bytes when called before the first mutation on a clean-open (no-WAL) store.
Sourcepub fn provenance_touching(
&self,
node: u32,
) -> impl Iterator<Item = (&str, u32, u32, u32)> + '_
pub fn provenance_touching( &self, node: u32, ) -> impl Iterator<Item = (&str, u32, u32, u32)> + '_
O(degree) reverse-index lookup: every provenance triple that touches node.
Dispatches to the lazy-decoded or live index depending on whether retained bytes have already been consumed by a mutation.
Sourcepub fn provenance_touching_len(&self, node: u32) -> usize
pub fn provenance_touching_len(&self, node: u32) -> usize
Number of provenance triples incident on node.
Sourcepub fn is_tripped(&self, name: &str) -> bool
pub fn is_tripped(&self, name: &str) -> bool
One-way latch: true after a budget breach until Self::rebuild
is the only exit (and only if the full desired set then fits).
Sourcepub fn fire_count(&self, name: &str) -> u64
pub fn fire_count(&self, name: &str) -> u64
Evaluations of this rule: one tick per on_node_changed fire, and
one tick per participating node on backfill and rebuild (even
when rebuild is a provenance no-op).
Sourcepub fn drain_deltas(&mut self) -> Vec<EngineEdgeDelta>
pub fn drain_deltas(&mut self) -> Vec<EngineEdgeDelta>
Drain and return all pending edge-fire / retract deltas since the last
call. Callers (db.rs log_then_apply_with) invoke this after a
successful WAL commit + apply to build [DbEvent]s for live
subscriptions. [GraphDb::open_with] drains and discards after WAL
replay so replay noise never leaks to subscribers.
§T2 note (as-of replay)
When Plan-15 T2 adds as-of replay for subscribers, that path should
call apply-only (no log_then_apply_with) and then call
drain_deltas() to feed those events to the replaying subscriber.
The suppression is already in place: apply accumulates but never
emits; drain_deltas is the only emission gate.
Sourcepub fn pending_delta_count(&self) -> usize
pub fn pending_delta_count(&self) -> usize
Number of accumulated deltas not yet drained. Used by
debug_assert in log_then_apply_with to catch stale-delta bugs.
Sourcepub fn pending_deltas_since(&self, cursor: usize) -> &[EngineEdgeDelta]
pub fn pending_deltas_since(&self, cursor: usize) -> &[EngineEdgeDelta]
Borrow the slice of deltas accumulated since cursor without
consuming them. cursor should be the value returned by
pending_delta_count() before an engine call.
The returned slice is valid until the next call to drain_deltas().
T1’s drain discipline is preserved: these deltas are still in the
buffer and will be drained by log_then_apply_with after apply
returns.
Sourcepub fn to_persist(
&self,
) -> (Vec<RuleDef>, BTreeMap<String, BTreeSet<(u32, u32, u32)>>, BTreeMap<String, bool>, BTreeMap<String, u64>)
pub fn to_persist( &self, ) -> (Vec<RuleDef>, BTreeMap<String, BTreeSet<(u32, u32, u32)>>, BTreeMap<String, bool>, BTreeMap<String, u64>)
Snapshot support: definitions + provenance + tripped/fires. Candidate
indexes and the by_node reverse index are NOT included (derived:
reindex_all / rebuild_by_node on open).
Sourcepub fn from_persist(
rules: Vec<RuleDef>,
prov: BTreeMap<String, BTreeSet<(u32, u32, u32)>>,
tripped: BTreeMap<String, bool>,
fires: BTreeMap<String, u64>,
) -> Self
pub fn from_persist( rules: Vec<RuleDef>, prov: BTreeMap<String, BTreeSet<(u32, u32, u32)>>, tripped: BTreeMap<String, bool>, fires: BTreeMap<String, u64>, ) -> Self
Reconstruct engine from a snapshot. Caller must call reindex_all after.
Sourcepub fn set_emit_deltas(&mut self, emit: bool)
pub fn set_emit_deltas(&mut self, emit: bool)
Enable or disable delta accumulation.
Set to true before the first subscriber or view is added.
Set to false when the last subscriber and last view are removed.
See the emit_deltas field doc for the safety invariant.
Sourcepub fn emit_deltas(&self) -> bool
pub fn emit_deltas(&self) -> bool
Whether delta accumulation is currently enabled.
Sourcepub fn take_rebuild_needed(&mut self) -> Vec<String>
pub fn take_rebuild_needed(&mut self) -> Vec<String>
Drain rule names that exceeded the IVF dst-drift rebuild threshold
during the most recent on_node_changed / on_node_removed.
Sourcepub fn queue_rebuild_needed(&mut self, name: String)
pub fn queue_rebuild_needed(&mut self, name: String)
Re-queue name so a later write can issue RebuildRule.
Used when auto-rebuild WAL IO fails after a durable user op.
Sourcepub fn export_ivf_state(&self) -> BTreeMap<String, RuleIvfExport>
pub fn export_ivf_state(&self) -> BTreeMap<String, RuleIvfExport>
Export IVF state for all approximate rules. Passed to snapshot() in
core-api and stored in the V4 snapshot so open() can restore cluster
assignments without re-fitting k-means.
Sourcepub fn reindex_all(
&mut self,
ids: &IdMap,
syms: &Interner,
labels: &[u32],
props: ColumnsView<'_>,
)
pub fn reindex_all( &mut self, ids: &IdMap, syms: &Interner, labels: &[u32], props: ColumnsView<'_>, )
Rebuild all candidate indexes by scanning every node. Call on open.
Sourcepub fn reindex_all_load_ivf(
&mut self,
ids: &IdMap,
syms: &Interner,
labels: &[u32],
props: ColumnsView<'_>,
ivf_state: BTreeMap<String, RuleIvfExport>,
)
pub fn reindex_all_load_ivf( &mut self, ids: &IdMap, syms: &Interner, labels: &[u32], props: ColumnsView<'_>, ivf_state: BTreeMap<String, RuleIvfExport>, )
Like reindex_all but LOADS persisted IVF state for approximate rules
instead of re-fitting k-means. This eliminates the cold-start re-fit
cost when opening a V4 snapshot.
ivf_state: map from rule name to (src_export, dst_export) as
produced by export_ivf_state / stored in the V4 snapshot.
For approximate rules absent from ivf_state (e.g. a rule added
after the snapshot), falls back to fit_ivf_clusters.
Sourcepub fn store_snapshot_state(
&self,
hnsw_blobs: BTreeMap<String, (Vec<u8>, Vec<u8>)>,
ivf_bytes: Vec<u8>,
)
pub fn store_snapshot_state( &self, hnsw_blobs: BTreeMap<String, (Vec<u8>, Vec<u8>)>, ivf_bytes: Vec<u8>, )
Store HNSW blobs and raw IVF bytes from a snapshot without deserializing.
Called from restore_snapshot_state in db.rs. Neither the HNSW graphs
nor the IVF centroids are materialized here; they are consumed lazily:
consume_retained_state_eager(WAL-present open, before WAL replay)- The mutation-hook lazy-init guard (clean open, first-write cost)
ensure_hnsw_loaded(first ANN query on a clean open)
Sourcepub fn store_provenance_bytes(&self, bytes: Vec<u8>)
pub fn store_provenance_bytes(&self, bytes: Vec<u8>)
Store raw rkyv provenance bytes retained from a V8 snapshot.
Called from restore_v8_base in db.rs after open. Provenance is not
decoded here; it is materialized lazily — either by the &self read path
(ensure_provenance_loaded) for stats/explain, or by the &mut self
write path (ensure_provenance_loaded_mut) on the first mutation.
Sourcepub fn ensure_provenance_loaded(&self)
pub fn ensure_provenance_loaded(&self)
Populate lazy_provenance from retained bytes for &self read paths.
Uses OnceLock for exactly-once initialization. The retained bytes are
NOT consumed here; ensure_provenance_loaded_mut still has access to them
for the write path. After the first mutation, retained_provenance_bytes
is None and callers switch to the live self.provenance field instead.
Sourcepub fn ensure_provenance_loaded_mut(&mut self)
pub fn ensure_provenance_loaded_mut(&mut self)
Decode and install retained provenance bytes into the live mutable fields.
No-op if bytes have already been consumed or were never stored.
Must be called under &mut self before any operation that reads or
diffs against self.provenance, self.owned, or self.by_node.
Sourcepub fn consume_retained_state_eager(
&mut self,
ids: &IdMap,
syms: &Interner,
labels: &[u32],
props: ColumnsView<'_>,
)
pub fn consume_retained_state_eager( &mut self, ids: &IdMap, syms: &Interner, labels: &[u32], props: ColumnsView<'_>, )
Eagerly consume retained snapshot state before WAL replay.
Call this in open_with when the WAL has records. Runs the O(n) node
scan + restores persisted IVF centroids and HNSW blobs so that WAL
replay finds fully-populated indexes. Marks indexes_populated = true.
Sourcepub fn ensure_hnsw_loaded(&self)
pub fn ensure_hnsw_loaded(&self)
Deserialize retained HNSW blobs into lazy_hnsw for the clean-open ANN
read path. Takes &self so it can be called from find_similar_vector
and search_hybrid under a shared (db.read()) lock.
Uses OnceLock to guarantee exactly-once initialization even under
concurrent shared access. The retained blobs are borrowed (not consumed)
so that a subsequent first-mutation call to consume_retained_state_eager
can still load the persisted HNSW graphs into self.indexes.
Called before the first ANN query on a clean-open (no WAL) store.
Sourcepub fn indexes_populated(&self) -> bool
pub fn indexes_populated(&self) -> bool
Returns true if candidate indexes have been built (either eagerly or
via the lazy mutation-hook trigger).
Sourcepub fn export_hnsw_state(&self) -> BTreeMap<String, (Vec<u8>, Vec<u8>)>
pub fn export_hnsw_state(&self) -> BTreeMap<String, (Vec<u8>, Vec<u8>)>
Export HNSW graphs for all approximate rules as opaque bincoded blobs.
Returns a map from rule name to (src_blob, dst_blob). An empty Vec
means the corresponding side has no initialized HNSW graph.
Sourcepub fn export_hnsw_state_passthrough(
&self,
) -> BTreeMap<String, (Vec<u8>, Vec<u8>)>
pub fn export_hnsw_state_passthrough( &self, ) -> BTreeMap<String, (Vec<u8>, Vec<u8>)>
Returns HNSW state for snapshotting. When indexes are not yet populated (clean open with no mutation), returns the retained raw blobs directly so that a migrate/snapshot does not silently drop fitted indexes.
Sourcepub fn retained_ivf_bytes_clone(&self) -> Option<Vec<u8>>
pub fn retained_ivf_bytes_clone(&self) -> Option<Vec<u8>>
Returns a clone of the retained raw IVF bincode bytes.
Returns None if no bytes are retained (fresh store or indexes already
consumed by a mutation). Used by snapshot_with for passthrough when
indexes have not yet been populated.
Sourcepub fn load_hnsw_state(&mut self, blobs: BTreeMap<String, (Vec<u8>, Vec<u8>)>)
pub fn load_hnsw_state(&mut self, blobs: BTreeMap<String, (Vec<u8>, Vec<u8>)>)
Restore HNSW graphs from bincoded blobs (overrides any incrementally built
graphs produced during reindex_all_load_ivf).
Called from restore_snapshot_state in db.rs after reindex.
Sourcepub fn hnsw_search_dst(
&self,
field: &str,
dst_label: &str,
q: &[f64],
k: usize,
) -> Option<Vec<(u32, f64)>>
pub fn hnsw_search_dst( &self, field: &str, dst_label: &str, q: &[f64], k: usize, ) -> Option<Vec<(u32, f64)>>
Find approximate nearest-neighbor ids on the dst side of the first
approximate VectorSimilar rule covering (dst_label, field).
Returns None when no matching rule or HNSW index exists.
Sourcepub fn hnsw_has_rule(&self, field: &str) -> bool
pub fn hnsw_has_rule(&self, field: &str) -> bool
Returns true if any approximate VectorSimilar rule covers field.
Use as a capability probe before calling hnsw_search_dst or
hnsw_search_any_dst — presence of the rule guarantees the native Rust
path will be used (HNSW when the index is populated, Rust brute-force
otherwise); it does NOT guarantee a populated HNSW index.
Sourcepub fn hnsw_search_any_dst(
&self,
field: &str,
q: &[f64],
k: usize,
) -> Option<Vec<(u32, f64)>>
pub fn hnsw_search_any_dst( &self, field: &str, q: &[f64], k: usize, ) -> Option<Vec<(u32, f64)>>
Like hnsw_search_dst but searches across all dst_labels that have
an approximate VectorSimilar rule covering field.
Results from multiple rules are merged by node id (keeping the maximum
score for any id that appears in more than one rule’s index), then
sorted descending and truncated to k.
Returns None when no applicable rule has a populated HNSW index
(same sentinel convention as hnsw_search_dst).
Sourcepub fn create_rule(
&mut self,
def: RuleDef,
g: &mut GraphMut<'_>,
) -> Result<(), String>
pub fn create_rule( &mut self, def: RuleDef, g: &mut GraphMut<'_>, ) -> Result<(), String>
Register a rule and backfill existing nodes. Returns Err on failed validate() or duplicate name.
Sourcepub fn delete_rule(
&mut self,
name: &str,
g: &mut GraphMut<'_>,
) -> Result<(), String>
pub fn delete_rule( &mut self, name: &str, g: &mut GraphMut<'_>, ) -> Result<(), String>
Remove the rule and exactly its owned edges. Returns Err if unknown.
Sourcepub fn on_node_changed(
&mut self,
n: u32,
changed: Option<(&str, Option<Value>)>,
g: &mut GraphMut<'_>,
)
pub fn on_node_changed( &mut self, n: u32, changed: Option<(&str, Option<Value>)>, g: &mut GraphMut<'_>, )
Called when node n is inserted (changed=None) or a field is updated.
- None: all rules where n’s label matches either side fire; index gains n.
- Some((field, old_value)): only rules watching
fieldfire; index is updated using old_value for removal so stale buckets are cleaned.
For via-hop rules (def.via_label.is_some()), also fires when n carries
the via-label: finds all srcs that route through n and recomputes their
derived edges. Via-hop rules bypass the candidate index and use
compute_desired_via instead.
Sourcepub fn on_edge_changed(
&mut self,
etype_str: &str,
src_id: u32,
dst_id: u32,
g: &mut GraphMut<'_>,
)
pub fn on_edge_changed( &mut self, etype_str: &str, src_id: u32, dst_id: u32, g: &mut GraphMut<'_>, )
Called when a user edge (etype_str, src_id, dst_id) is inserted or
deleted (not a derived edge — those are managed by provenance, not here).
For any via-hop rule where via_edge == etype_str and src_id carries
src_label, the src_id’s desired derived-edge set may have changed:
a new WORKS_AT edge makes a new Org reachable as a via-node, and a
deleted WORKS_AT removes a previously reachable Org.
This is the only hook the engine exposes for topology changes. It is
called from db.rs on WalRecord::InsertEdge and WalRecord::DeleteEdge
immediately after the topo is updated (so g.topo already reflects the
new state).
Sourcepub fn on_node_removed(&mut self, n: u32, g: &mut GraphMut<'_>)
pub fn on_node_removed(&mut self, n: u32, g: &mut GraphMut<'_>)
Retract every provenance edge touching n across all rules and drop
n from every rule index using its current props.
Caller must invoke this while labels/props are still intact (before tombstone). Rules are walked in BTree name order; touching edges in BTree triple order. A second call on an already-retracted node is a no-op (crash-window replay / absent state).
Sourcepub fn rebuild(
&mut self,
name: &str,
g: &mut GraphMut<'_>,
) -> Result<(), String>
pub fn rebuild( &mut self, name: &str, g: &mut GraphMut<'_>, ) -> Result<(), String>
Recompute one rule from scratch. Only exit from the tripped latch.
If the full desired set fits in the budget, it is applied completely
and tripped is cleared. If it still exceeds the budget, existing
provenance is left completely untouched and tripped stays true
(rebuild-is-noop for at/over-cap rules). Always counts as a fire
evaluation per participating node. Returns Err if unknown.
Trait Implementations§
Source§impl Debug for RuleEngine
impl Debug for RuleEngine
Source§impl Default for RuleEngine
impl Default for RuleEngine
Source§fn default() -> RuleEngine
fn default() -> RuleEngine
Auto Trait Implementations§
impl !Freeze for RuleEngine
impl RefUnwindSafe for RuleEngine
impl Send for RuleEngine
impl Sync for RuleEngine
impl Unpin for RuleEngine
impl UnsafeUnpin for RuleEngine
impl UnwindSafe for RuleEngine
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
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
Source§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.