Storage Backends¶
Implement custom storage backends for specialized use cases.
Storage Backend Trait¶
pub trait StorageBackend: Send + Sync {
fn name(&self) -> &str;
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()>;
fn delete(&mut self, key: &[u8]) -> Result<()>;
fn scan(&self, start: &[u8], end: &[u8]) -> Result<Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)>>>;
fn flush(&mut self) -> Result<()>;
fn close(&mut self) -> Result<()>;
}
Built-in Backends¶
| Backend | Description |
|---|---|
MemoryBackend | In-memory storage |
FileBackend | File-based persistent storage |
WalBackend | Write-ahead log for durability |
Custom Backend Example¶
use grafeo_adapters::storage::StorageBackend;
pub struct RedisBackend {
client: redis::Client,
}
impl StorageBackend for RedisBackend {
fn name(&self) -> &str {
"redis"
}
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
let mut conn = self.client.get_connection()?;
let result: Option<Vec<u8>> = redis::cmd("GET")
.arg(key)
.query(&mut conn)?;
Ok(result)
}
fn put(&mut self, key: &[u8], value: &[u8]) -> Result<()> {
let mut conn = self.client.get_connection()?;
redis::cmd("SET")
.arg(key)
.arg(value)
.execute(&mut conn);
Ok(())
}
fn delete(&mut self, key: &[u8]) -> Result<()> {
let mut conn = self.client.get_connection()?;
redis::cmd("DEL")
.arg(key)
.execute(&mut conn);
Ok(())
}
// ... implement remaining methods
}
Using Custom Backend¶
use grafeo::{Database, Config};
let backend = Box::new(RedisBackend::new("redis://localhost")?);
let config = Config::builder()
.storage_backend(backend)
.build()?;
let db = Database::open_with_config("my_graph", config)?;
Backend Requirements¶
- Thread Safety - Must be
Send + Sync - Durability - Implement
flush()for persistence - Atomicity - Ensure atomic operations where needed
- Error Handling - Use
Resultfor all fallible operations