Convert store and CLI to anyhow::Result for cleaner error handling

Replace Result<_, String> with anyhow::Result throughout:
- hippocampus/store module (persist, ops, types, view, mod)
- CLI modules (admin, agent, graph, journal, node)
- Run trait in main.rs

Use .context() and .with_context() instead of .map_err(|e| format!(...))
patterns. Add bail!() for early error returns.

Add access_local() helper in hippocampus/mod.rs that returns
Result<Arc<Mutex<Store>>> for direct local store access.

Fix store access patterns to properly lock Arc<Mutex<Store>> before
accessing fields in mind/unconscious.rs, mind/mod.rs, subconscious/learn.rs,
and hippocampus/memory.rs.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-13 18:05:04 -04:00
parent 5db00e083f
commit b8db8754be
17 changed files with 282 additions and 295 deletions

View file

@ -22,6 +22,7 @@ use std::fs;
use std::io::{BufReader, BufWriter};
use std::path::Path;
use anyhow::{bail, Context, Result};
use capnp::message;
use capnp::serialize;
@ -29,17 +30,17 @@ use consciousness::memory_capnp;
use consciousness::store::Node;
/// Read all node entries from a capnp log file, preserving order.
fn read_all_entries(path: &Path) -> Result<Vec<Node>, String> {
fn read_all_entries(path: &Path) -> Result<Vec<Node>> {
let file = fs::File::open(path)
.map_err(|e| format!("open {}: {}", path.display(), e))?;
.with_context(|| format!("open {}", path.display()))?;
let mut reader = BufReader::new(file);
let mut entries = Vec::new();
while let Ok(msg) = serialize::read_message(&mut reader, message::ReaderOptions::new()) {
let log = msg.get_root::<memory_capnp::node_log::Reader>()
.map_err(|e| format!("read log from {}: {}", path.display(), e))?;
.with_context(|| format!("read log from {}", path.display()))?;
for node_reader in log.get_nodes()
.map_err(|e| format!("get nodes from {}: {}", path.display(), e))? {
.with_context(|| format!("get nodes from {}", path.display()))? {
let node = Node::from_capnp_migrate(node_reader)?;
entries.push(node);
}
@ -49,9 +50,9 @@ fn read_all_entries(path: &Path) -> Result<Vec<Node>, String> {
}
/// Write node entries to a new capnp log file in chunks.
fn write_entries(path: &Path, entries: &[Node]) -> Result<(), String> {
fn write_entries(path: &Path, entries: &[Node]) -> Result<()> {
let file = fs::File::create(path)
.map_err(|e| format!("create {}: {}", path.display(), e))?;
.with_context(|| format!("create {}", path.display()))?;
let mut writer = BufWriter::new(file);
for chunk in entries.chunks(100) {
@ -64,13 +65,13 @@ fn write_entries(path: &Path, entries: &[Node]) -> Result<(), String> {
}
}
serialize::write_message(&mut writer, &msg)
.map_err(|e| format!("write: {}", e))?;
.context("write message")?;
}
Ok(())
}
fn main() -> Result<(), String> {
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
if args.len() != 4 {
eprintln!("Usage: merge-logs <old_log> <current_log> <output_dir>");
@ -87,19 +88,18 @@ fn main() -> Result<(), String> {
// Validate inputs exist
if !old_path.exists() {
return Err(format!("old log not found: {}", old_path.display()));
bail!("old log not found: {}", old_path.display());
}
if !current_path.exists() {
return Err(format!("current log not found: {}", current_path.display()));
bail!("current log not found: {}", current_path.display());
}
// Create output directory (must not already contain nodes.capnp)
fs::create_dir_all(output_dir)
.map_err(|e| format!("create output dir: {}", e))?;
.context("create output dir")?;
let output_path = output_dir.join("nodes.capnp");
if output_path.exists() {
return Err(format!("output already exists: {} — refusing to overwrite",
output_path.display()));
bail!("output already exists: {} — refusing to overwrite", output_path.display());
}
eprintln!("Reading old log: {} ...", old_path.display());
@ -190,8 +190,8 @@ fn main() -> Result<(), String> {
eprintln!(" Replay produces {} live nodes", final_nodes.len());
if verify_entries.len() != merged.len() {
return Err(format!("Verification failed: wrote {} but read back {}",
merged.len(), verify_entries.len()));
bail!("Verification failed: wrote {} but read back {}",
merged.len(), verify_entries.len());
}
eprintln!();