diff --git a/src/database/database.rs b/src/database/database.rs index 6b76732..3e28285 100644 --- a/src/database/database.rs +++ b/src/database/database.rs @@ -1,10 +1,19 @@ -use rocksdb::{ColumnFamilyDescriptor, Options, DB}; +use rocksdb::{ColumnFamilyDescriptor, IteratorMode, Options, DB}; use serde::{Deserialize, Serialize}; use std::io::{self, ErrorKind}; use std::path::Path; +use std::sync::Arc; pub struct Database { - db: DB, + db: Arc, +} + +impl Clone for Database { + fn clone(&self) -> Self { + Self { + db: Arc::clone(&self.db), + } + } } impl Database { @@ -27,8 +36,27 @@ impl Database { let db = DB::open_cf_descriptors(&opts, path, cfs_vec) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; - Ok(Self { db }) + Ok(Self { db: db.into() }) } + + pub fn list_all_keys(&self, cf: &str) -> Result, io::Error> { + let cf_handle = self.db.cf_handle(cf).ok_or_else(|| { + io::Error::new( + ErrorKind::NotFound, + format!("Column family {} not found", cf), + ) + })?; + let mut keys = Vec::new(); + let iter = self.db.iterator_cf(cf_handle, IteratorMode::Start); + for item in iter { + let (key, _) = item.map_err(|e| io::Error::new(ErrorKind::Other, e.to_string()))?; + let key_str = String::from_utf8(key.to_vec()) + .map_err(|e| io::Error::new(ErrorKind::Other, e.to_string()))?; + keys.push(key_str); + } + Ok(keys) + } + pub fn insert(&self, cf: &str, key: &str, value: &V) -> Result<(), io::Error> { let cf_handle = self.db.cf_handle(cf).ok_or_else(|| { io::Error::new( @@ -96,7 +124,4 @@ impl Database { Ok(()) } - pub fn close(self) { - drop(self); - } } diff --git a/src/repository/mod.rs b/src/repository/mod.rs new file mode 100644 index 0000000..a0cb07f --- /dev/null +++ b/src/repository/mod.rs @@ -0,0 +1 @@ +pub mod namespace; diff --git a/src/repository/namespace.rs b/src/repository/namespace.rs new file mode 100644 index 0000000..32f4959 --- /dev/null +++ b/src/repository/namespace.rs @@ -0,0 +1,59 @@ +use crate::database::database::Database; +use crate::dto::namespace_data::NamespaceData; +use serde_json::{json, Value}; +use std::io; +use std::sync::Arc; + +pub struct NamespaceRepository { + db: Arc, +} + +impl NamespaceRepository { + pub fn new(db: Arc) -> Self { + Self { db } + } + + pub fn list_all_namespaces(&self) -> io::Result> { + self.db + .list_all_keys("NamespaceData") + .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) + } + + pub fn create_namespace(&self, name: &str, properties: Option) -> io::Result<()> { + let namespace_data = NamespaceData { + name: name.to_string(), + properties: properties.unwrap_or_else(|| json!({"last_modified_time": current_time()})), + }; + self.db.insert("NamespaceData", name, &namespace_data) + } + + pub fn load_namespace(&self, name: &str) -> io::Result> { + self.db.get("NamespaceData", name) + } + + pub fn namespace_exists(&self, name: &str) -> io::Result { + self.db + .get::("NamespaceData", name) + .map(|data| data.is_some()) + } + + pub fn delete_namespace(&self, name: &str) -> io::Result<()> { + self.db.delete("NamespaceData", name) + } + + pub fn set_namespace_properties(&self, name: &str, properties: Value) -> io::Result<()> { + if let Some(mut namespace_data) = self.load_namespace(name)? { + namespace_data.properties = properties; + self.db.update("NamespaceData", name, &namespace_data) + } else { + Err(io::Error::new( + io::ErrorKind::NotFound, + "Namespace not found", + )) + } + } +} + +fn current_time() -> String { + "current_time".to_string() +}