9. Storage trait for dependency injection
Date: 2026-04-22
Status
Accepted
Context
Collectors need to read files and access git/OpenCode databases. Collectors must support testing without real filesystems.
Decision
Cerebro defines traits for dependency injection:
#![allow(unused)]
fn main() {
pub trait Storage: Send + Sync {
async fn exists(&self, path: &Path) -> bool;
async fn read_to_string(&self, path: &Path) -> Result<String>;
// ...
}
pub trait Git: Send + Sync {
async fn commits(&self, repo_path: &Path) -> Result<Vec<GitCommit>>;
async fn modified_files(&self, repo_path: &Path) -> Result<Vec<FileChange>>;
}
}
Implementations:
TokioStorage: Uses tokio for async file I/OGit2: Usesgit2crate for git operations, with commits limited to 20 per projectSqlxDb: Usessqlxfor OpenCode SQLite queries
Consequences
Pros
- Testable without real filesystem
- Swap implementations, such as mock storage for tests
- Clear abstraction boundaries
Cons
- Trait indirection overhead
- More complex DI setup
Notes
See cerebro-core/src/storage.rs.