inferadb_ledger_state/
engine.rs1use std::{path::Path, sync::Arc};
8
9use inferadb_ledger_store::{Database, FileBackend, InMemoryBackend};
10use snafu::{ResultExt, Snafu};
11
12#[derive(Debug, Snafu)]
14#[snafu(visibility(pub(crate)))]
15pub enum EngineError {
16 #[snafu(display("Failed to open database at {path}: {source}"))]
18 Open {
19 path: String,
20 source: inferadb_ledger_store::Error,
21 #[snafu(implicit)]
22 location: snafu::Location,
23 },
24
25 #[snafu(display("Storage operation failed: {source}"))]
27 Storage {
28 source: inferadb_ledger_store::Error,
29 #[snafu(implicit)]
30 location: snafu::Location,
31 },
32}
33
34pub struct StorageEngine {
40 db: Arc<Database<FileBackend>>,
41}
42
43#[allow(clippy::result_large_err)]
44impl StorageEngine {
45 pub fn open(path: impl AsRef<Path>) -> std::result::Result<Self, EngineError> {
51 let path = path.as_ref();
52 let db = if path.exists() { Database::open(path) } else { Database::create(path) }
53 .context(OpenSnafu { path: path.display().to_string() })?;
54
55 Ok(Self { db: Arc::new(db) })
56 }
57
58 pub fn db(&self) -> Arc<Database<FileBackend>> {
60 Arc::clone(&self.db)
61 }
62}
63
64impl Clone for StorageEngine {
65 fn clone(&self) -> Self {
66 Self { db: Arc::clone(&self.db) }
67 }
68}
69
70pub struct InMemoryStorageEngine {
76 db: Arc<Database<InMemoryBackend>>,
77}
78
79#[allow(clippy::result_large_err)]
80impl InMemoryStorageEngine {
81 pub fn open() -> std::result::Result<Self, EngineError> {
87 let db = Database::open_in_memory().context(OpenSnafu { path: ":memory:".to_string() })?;
88
89 Ok(Self { db: Arc::new(db) })
90 }
91
92 pub fn db(&self) -> Arc<Database<InMemoryBackend>> {
94 Arc::clone(&self.db)
95 }
96}
97
98impl Clone for InMemoryStorageEngine {
99 fn clone(&self) -> Self {
100 Self { db: Arc::clone(&self.db) }
101 }
102}
103
104#[cfg(test)]
105#[allow(clippy::unwrap_used, clippy::expect_used, clippy::disallowed_methods, unused_mut)]
106mod tests {
107 use inferadb_ledger_store::tables;
108
109 use super::*;
110
111 #[test]
112 fn test_open_in_memory() {
113 let engine = InMemoryStorageEngine::open().expect("should open");
114 let db = engine.db();
115 let _read = db.read().expect("should begin read");
116 let _write = db.write().expect("should begin write");
117 }
118
119 #[test]
120 fn test_write_and_read() {
121 let engine = InMemoryStorageEngine::open().expect("should open");
122 let db = engine.db();
123
124 {
126 let mut txn = db.write().expect("should begin write");
127 txn.insert::<tables::Entities>(&b"test_key".to_vec(), &b"test_value".to_vec())
128 .expect("insert");
129 txn.commit().expect("commit");
130 }
131
132 {
134 let txn = db.read().expect("should begin read");
135 let value = txn.get::<tables::Entities>(&b"test_key".to_vec()).expect("get");
136 assert!(value.is_some());
137 assert_eq!(value.unwrap(), b"test_value");
138 }
139 }
140}