store: wire up RELS index for relations

Complete redb schema with bidirectional relation indexing:
- RELS multimap: uuid → packed(other_uuid, strength, rel_type, is_outgoing)
- Each edge stored twice (once per endpoint) with direction bit
- pack_rel/unpack_rel for 22-byte packed format

Wired up:
- replay_relations indexes all relations on load
- add_relation indexes new relations
- for_each_relation reads from index (graph building)
- add_link uses index for existence check
- set_link_strength finds/updates edges via index
- cap_degree uses index for degree counting and pruning
- rename_node finds edges by uuid

Vec<Relation> still maintained for remaining uses (normalize_strengths,
graph_health diagnostics). To be removed in follow-up.

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

View file

@ -362,6 +362,13 @@ impl Store {
self.relations = by_uuid.into_values()
.filter(|r| !r.deleted)
.collect();
// Index relations in redb
if let Some(db) = &self.db {
for rel in &self.relations {
index::index_relation(db, &rel.source, &rel.target, rel.strength, rel.rel_type as u8)?;
}
}
Ok(())
}
@ -629,13 +636,16 @@ fn rebuild_index(db_path: &Path, capnp_path: &Path) -> Result<redb::Database> {
let txn = database.begin_write()?;
{
let mut nodes_table = txn.open_table(index::NODES)?;
let mut uuid_table = txn.open_table(index::UUID_TO_KEY)?;
let mut key_uuid_table = txn.open_table(index::KEY_TO_UUID)?;
let mut uuid_offsets = txn.open_multimap_table(index::UUID_OFFSETS)?;
for (key, (offset, uuid, _, deleted)) in latest {
if !deleted {
nodes_table.insert(key.as_str(), offset)?;
uuid_table.insert(uuid.as_slice(), key.as_str())?;
key_uuid_table.insert(key.as_str(), uuid.as_slice())?;
}
// Always record offset in UUID history (even for deleted)
uuid_offsets.insert(uuid.as_slice(), offset)?;
}
}
txn.commit()?;