use anyhow::{Context, Result};
use rocksdb::{ColumnFamilyDescriptor, Options, DB};
use std::path::Path;
const CF_MEMORIES: &str = "memories";
const CF_BY_TAG: &str = "by_tag";
const CF_DELETED: &str = "deleted";
const CF_IMPORTANCE: &str = "importance";
const CF_PROJECTS: &str = "projects";
const CF_CONFIG: &str = "config";
const CF_FACETS: &str = "facets";
const CF_MEMORY_FACETS: &str = "memory_facets";
const CF_EDGES: &str = "edges";
const CF_NODE_EDGES_OUT: &str = "node_edges_out";
const CF_NODE_EDGES_IN: &str = "node_edges_in";
const CF_PROPAGATION_DELTAS: &str = "propagation_deltas";
const CF_PENDING_PROPAGATIONS: &str = "pending_propagations";
const CF_APPLIED_PROPAGATIONS: &str = "applied_propagations";
const CF_RULES: &str = "rules";
const CF_RULE_STATS: &str = "rule_stats";
const CF_MEMORY_SUMMARIES: &str = "memory_summaries";
const CF_MEMORY_KEYWORDS: &str = "memory_keywords";
pub struct RocksDBStore {
db: DB,
}
impl RocksDBStore {
pub fn open(path: &Path) -> Result<Self> {
let mut options = Options::default();
options.create_if_missing(true);
options.create_missing_column_families(true);
let cfs = vec![
ColumnFamilyDescriptor::new(CF_MEMORIES, Options::default()),
ColumnFamilyDescriptor::new(CF_BY_TAG, Options::default()),
ColumnFamilyDescriptor::new(CF_DELETED, Options::default()),
ColumnFamilyDescriptor::new(CF_IMPORTANCE, Options::default()),
ColumnFamilyDescriptor::new(CF_PROJECTS, Options::default()),
ColumnFamilyDescriptor::new(CF_CONFIG, Options::default()),
ColumnFamilyDescriptor::new(CF_FACETS, Options::default()),
ColumnFamilyDescriptor::new(CF_MEMORY_FACETS, Options::default()),
ColumnFamilyDescriptor::new(CF_EDGES, Options::default()),
ColumnFamilyDescriptor::new(CF_NODE_EDGES_OUT, Options::default()),
ColumnFamilyDescriptor::new(CF_NODE_EDGES_IN, Options::default()),
ColumnFamilyDescriptor::new(CF_PROPAGATION_DELTAS, Options::default()),
ColumnFamilyDescriptor::new(CF_PENDING_PROPAGATIONS, Options::default()),
ColumnFamilyDescriptor::new(CF_APPLIED_PROPAGATIONS, Options::default()),
ColumnFamilyDescriptor::new(CF_RULES, Options::default()),
ColumnFamilyDescriptor::new(CF_RULE_STATS, Options::default()),
ColumnFamilyDescriptor::new(CF_MEMORY_SUMMARIES, Options::default()),
ColumnFamilyDescriptor::new(CF_MEMORY_KEYWORDS, Options::default()),
];
let db = DB::open_cf_descriptors(&options, path, cfs).context("Failed to open RocksDB")?;
Ok(Self { db })
}
pub fn cf_memories(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_MEMORIES)
.context("Column family 'memories' not found")
}
pub fn cf_by_tag(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_BY_TAG)
.context("Column family 'by_tag' not found")
}
pub fn cf_deleted(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_DELETED)
.context("Column family 'deleted' not found")
}
pub fn cf_importance(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_IMPORTANCE)
.context("Column family 'importance' not found")
}
pub fn cf_projects(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_PROJECTS)
.context("Column family 'projects' not found")
}
pub fn cf_config(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_CONFIG)
.context("Column family 'config' not found")
}
pub fn cf_facets(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_FACETS)
.context("Column family 'facets' not found")
}
pub fn cf_memory_facets(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_MEMORY_FACETS)
.context("Column family 'memory_facets' not found")
}
pub fn cf_edges(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_EDGES)
.context("Column family 'edges' not found")
}
pub fn cf_node_edges_out(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_NODE_EDGES_OUT)
.context("Column family 'node_edges_out' not found")
}
pub fn cf_node_edges_in(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_NODE_EDGES_IN)
.context("Column family 'node_edges_in' not found")
}
pub fn cf_propagation_deltas(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_PROPAGATION_DELTAS)
.context("Column family 'propagation_deltas' not found")
}
pub fn cf_pending_propagations(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_PENDING_PROPAGATIONS)
.context("Column family 'pending_propagations' not found")
}
pub fn cf_applied_propagations(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_APPLIED_PROPAGATIONS)
.context("Column family 'applied_propagations' not found")
}
pub fn cf_rules(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_RULES)
.context("Column family 'rules' not found")
}
pub fn cf_rule_stats(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_RULE_STATS)
.context("Column family 'rule_stats' not found")
}
pub fn cf_memory_summaries(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_MEMORY_SUMMARIES)
.context("Column family 'memory_summaries' not found")
}
pub fn cf_memory_keywords(&self) -> Result<&rocksdb::ColumnFamily> {
self.db
.cf_handle(CF_MEMORY_KEYWORDS)
.context("Column family 'memory_keywords' not found")
}
pub fn put_cf(&self, cf: &rocksdb::ColumnFamily, key: &[u8], value: &[u8]) -> Result<()> {
self.db
.put_cf(cf, key, value)
.context("Failed to put value")
}
pub fn get_cf(&self, cf: &rocksdb::ColumnFamily, key: &[u8]) -> Result<Option<Vec<u8>>> {
self.db.get_cf(cf, key).context("Failed to get value")
}
pub fn delete_cf(&self, cf: &rocksdb::ColumnFamily, key: &[u8]) -> Result<()> {
self.db.delete_cf(cf, key).context("Failed to delete value")
}
pub fn iter_cf(&self, cf: &rocksdb::ColumnFamily) -> rocksdb::DBRawIterator<'_> {
self.db.raw_iterator_cf(cf)
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn test_rocksdb_open() {
let dir = tempdir().unwrap();
let store = RocksDBStore::open(dir.path()).unwrap();
assert!(store.cf_memories().is_ok());
}
#[test]
fn test_rocksdb_put_get() {
let dir = tempdir().unwrap();
let store = RocksDBStore::open(dir.path()).unwrap();
let cf = store.cf_memories().unwrap();
store.put_cf(cf, b"test_key", b"test_value").unwrap();
let value = store.get_cf(cf, b"test_key").unwrap();
assert_eq!(value, Some(b"test_value".to_vec()));
}
}