consciousness/src/hippocampus/store/view.rs

106 lines
3.7 KiB
Rust
Raw Normal View History

// Read-only access abstraction for the memory store
use super::{capnp, index, types::*};
use super::Store;
// ---------------------------------------------------------------------------
// StoreView: read-only access trait for search and graph code.
// ---------------------------------------------------------------------------
pub trait StoreView {
/// Iterate all nodes. Callback receives (key, content, weight).
fn for_each_node<F: FnMut(&str, &str, f32)>(&self, f: F);
/// Iterate all nodes with metadata. Callback receives (key, node_type, timestamp).
fn for_each_node_meta<F: FnMut(&str, NodeType, i64)>(&self, f: F);
/// Iterate all relations. Callback receives (source_key, target_key, strength, rel_type).
fn for_each_relation<F: FnMut(&str, &str, f32, RelationType)>(&self, f: F);
/// Node weight by key, or the default weight if missing.
fn node_weight(&self, key: &str) -> f64;
}
impl StoreView for Store {
fn for_each_node<F: FnMut(&str, &str, f32)>(&self, mut f: F) {
let db = match self.db.as_ref() {
Some(db) => db,
None => return,
};
let keys = match index::all_keys(db) {
Ok(keys) => keys,
Err(_) => return,
};
for key in keys {
if let Ok(Some(offset)) = index::get_offset(db, &key) {
if let Ok(node) = capnp::read_node_at_offset(offset) {
f(&key, &node.content, node.weight);
}
}
}
}
fn for_each_node_meta<F: FnMut(&str, NodeType, i64)>(&self, mut f: F) {
let db = match self.db.as_ref() {
Some(db) => db,
None => return,
};
let keys = match index::all_keys(db) {
Ok(keys) => keys,
Err(_) => return,
};
for key in keys {
if let Ok(Some(offset)) = index::get_offset(db, &key) {
if let Ok(node) = capnp::read_node_at_offset(offset) {
f(&key, node.node_type, node.timestamp);
}
}
}
}
fn for_each_relation<F: FnMut(&str, &str, f32, RelationType)>(&self, mut f: F) {
let db = match self.db.as_ref() {
Some(db) => db,
None => return,
};
// Build uuid ↔ key maps in one pass
let keys = match index::all_keys(db) {
Ok(keys) => keys,
Err(_) => return,
};
let mut uuid_to_key: std::collections::HashMap<[u8; 16], String> = std::collections::HashMap::new();
let mut key_to_uuid: std::collections::HashMap<String, [u8; 16]> = std::collections::HashMap::new();
for key in &keys {
if let Ok(Some(uuid)) = index::get_uuid_for_key(db, key) {
uuid_to_key.insert(uuid, key.clone());
key_to_uuid.insert(key.clone(), uuid);
}
}
// Iterate edges: only process outgoing to avoid duplicates
for (key, uuid) in &key_to_uuid {
let edges = match index::edges_for_node(db, uuid) {
Ok(e) => e,
Err(_) => continue,
};
for (other_uuid, strength, rel_type_byte, is_outgoing) in edges {
if !is_outgoing { continue; }
let target_key = match uuid_to_key.get(&other_uuid) {
Some(k) => k,
None => continue,
};
f(key, target_key, strength, RelationType::from_u8(rel_type_byte));
}
}
}
fn node_weight(&self, key: &str) -> f64 {
let cfg = crate::config::get();
self.get_node(key)
.ok()
.flatten()
.map(|n| n.weight as f64)
.unwrap_or(cfg.default_node_weight)
}
}