store: convert more callers to use RELS index

Convert remaining Vec users to index-based access:
- memory.rs: MemoryNode::from_store uses Store::neighbors()
- graph.rs: orphan detection uses for_each_relation
- local.rs: normalize_strengths uses for_each_relation + set_link_strength

Add Store::neighbors() method and index::get_offsets_for_uuid().

Cleanup:
- for_each_relation: build both uuid↔key maps in one pass
- cap_degree: consolidate key/uuid/degree collection

Remaining Vec uses: admin.rs (fsck, dedup), capnp.rs (load path).

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2026-04-13 21:19:47 -04:00
parent 5fe51fbfda
commit 5832e57970
8 changed files with 109 additions and 81 deletions

View file

@ -882,18 +882,18 @@ pub fn health_report(graph: &Graph, store: &Store) -> String {
.count();
// Orphan edges: relations referencing non-existent nodes
// With index-based lookup, we count edges where endpoints don't resolve
let mut orphan_edges = 0usize;
let mut missing_nodes: HashSet<String> = HashSet::new();
for rel in &store.relations {
if rel.deleted { continue; }
let s_missing = !store.contains_key(&rel.source_key).unwrap_or(false);
let t_missing = !store.contains_key(&rel.target_key).unwrap_or(false);
store.for_each_relation(|source, target, _, _| {
let s_missing = !store.contains_key(source).unwrap_or(false);
let t_missing = !store.contains_key(target).unwrap_or(false);
if s_missing || t_missing {
orphan_edges += 1;
if s_missing { missing_nodes.insert(rel.source_key.clone()); }
if t_missing { missing_nodes.insert(rel.target_key.clone()); }
if s_missing { missing_nodes.insert(source.to_string()); }
if t_missing { missing_nodes.insert(target.to_string()); }
}
}
});
// NodeType breakdown
let mut type_counts: HashMap<&str, usize> = HashMap::new();