...
This commit is contained in:
@@ -38,6 +38,9 @@ pub struct DocTree {
|
||||
/// Redis storage backend
|
||||
storage: RedisStorage,
|
||||
|
||||
/// Name of the doctree (used as prefix for Redis keys)
|
||||
pub doctree_name: String,
|
||||
|
||||
/// For backward compatibility
|
||||
pub name: String,
|
||||
|
||||
@@ -56,6 +59,9 @@ pub struct DocTreeBuilder {
|
||||
/// Redis storage backend
|
||||
storage: Option<RedisStorage>,
|
||||
|
||||
/// Name of the doctree (used as prefix for Redis keys)
|
||||
doctree_name: Option<String>,
|
||||
|
||||
/// For backward compatibility
|
||||
name: Option<String>,
|
||||
|
||||
@@ -74,6 +80,7 @@ impl DocTree {
|
||||
collections: HashMap::new(),
|
||||
default_collection: None,
|
||||
storage: None,
|
||||
doctree_name: Some("default".to_string()),
|
||||
name: None,
|
||||
path: None,
|
||||
}
|
||||
@@ -92,8 +99,12 @@ impl DocTree {
|
||||
pub fn add_collection<P: AsRef<Path>>(&mut self, path: P, name: &str) -> Result<&Collection> {
|
||||
// Create a new collection
|
||||
let namefixed = name_fix(name);
|
||||
// Clone the storage and set the doctree name
|
||||
let mut storage = self.storage.clone();
|
||||
storage.set_doctree_name(&self.doctree_name);
|
||||
|
||||
let collection = Collection::builder(path, &namefixed)
|
||||
.with_storage(self.storage.clone())
|
||||
.with_storage(storage)
|
||||
.build()?;
|
||||
|
||||
// Scan the collection
|
||||
@@ -531,6 +542,20 @@ impl DocTreeBuilder {
|
||||
/// # Returns
|
||||
///
|
||||
/// Self for method chaining
|
||||
/// Set the doctree name
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `name` - Name of the doctree
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Self for method chaining
|
||||
pub fn with_doctree_name(mut self, name: &str) -> Self {
|
||||
self.doctree_name = Some(name.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_storage(mut self, storage: RedisStorage) -> Self {
|
||||
self.storage = Some(storage);
|
||||
self
|
||||
@@ -552,10 +577,18 @@ impl DocTreeBuilder {
|
||||
DocTreeError::MissingParameter("storage".to_string())
|
||||
})?;
|
||||
|
||||
// Get the doctree name
|
||||
let doctree_name = self.doctree_name.clone().unwrap_or_else(|| "default".to_string());
|
||||
|
||||
// Create a new collection
|
||||
let namefixed = name_fix(name);
|
||||
|
||||
// Clone the storage and set the doctree name
|
||||
let mut storage_clone = storage.clone();
|
||||
storage_clone.set_doctree_name(&doctree_name);
|
||||
|
||||
let collection = Collection::builder(path.as_ref(), &namefixed)
|
||||
.with_storage(storage.clone())
|
||||
.with_storage(storage_clone)
|
||||
.build()?;
|
||||
|
||||
// Scan the collection
|
||||
@@ -604,11 +637,19 @@ impl DocTreeBuilder {
|
||||
DocTreeError::MissingParameter("storage".to_string())
|
||||
})?;
|
||||
|
||||
// Get the doctree name
|
||||
let doctree_name = self.doctree_name.clone().unwrap_or_else(|| "default".to_string());
|
||||
|
||||
// Clone the storage and set the doctree name
|
||||
let mut storage_clone = storage.clone();
|
||||
storage_clone.set_doctree_name(&doctree_name);
|
||||
|
||||
// Create a temporary DocTree to scan collections
|
||||
let mut temp_doctree = DocTree {
|
||||
collections: HashMap::new(),
|
||||
default_collection: None,
|
||||
storage: storage.clone(),
|
||||
storage: storage_clone,
|
||||
doctree_name: doctree_name,
|
||||
name: self.name.clone().unwrap_or_default(),
|
||||
path: self.path.clone().unwrap_or_else(|| PathBuf::from("")),
|
||||
};
|
||||
@@ -641,11 +682,19 @@ impl DocTreeBuilder {
|
||||
DocTreeError::MissingParameter("storage".to_string())
|
||||
})?;
|
||||
|
||||
// Get the doctree name
|
||||
let doctree_name = self.doctree_name.unwrap_or_else(|| "default".to_string());
|
||||
|
||||
// Set the doctree name in the storage
|
||||
let mut storage_clone = storage.clone();
|
||||
storage_clone.set_doctree_name(&doctree_name);
|
||||
|
||||
// Create the DocTree
|
||||
let mut doctree = DocTree {
|
||||
collections: self.collections,
|
||||
default_collection: self.default_collection,
|
||||
storage: storage.clone(),
|
||||
storage: storage_clone,
|
||||
doctree_name,
|
||||
name: self.name.unwrap_or_default(),
|
||||
path: self.path.unwrap_or_else(|| PathBuf::from("")),
|
||||
};
|
||||
@@ -684,6 +733,12 @@ pub fn new<P: AsRef<Path>>(args: &[&str]) -> Result<DocTree> {
|
||||
|
||||
let mut builder = DocTree::builder().with_storage(storage);
|
||||
|
||||
// If the first argument is a doctree name, use it
|
||||
if args.len() >= 1 && args[0].starts_with("--doctree=") {
|
||||
let doctree_name = args[0].trim_start_matches("--doctree=");
|
||||
builder = builder.with_doctree_name(doctree_name);
|
||||
}
|
||||
|
||||
// For backward compatibility with existing code
|
||||
if args.len() == 2 {
|
||||
let path = args[0];
|
||||
@@ -707,15 +762,20 @@ pub fn new<P: AsRef<Path>>(args: &[&str]) -> Result<DocTree> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `root_path` - The root path to scan for collections
|
||||
/// * `doctree_name` - Optional name for the doctree (default: "default")
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A new DocTree or an error
|
||||
pub fn from_directory<P: AsRef<Path>>(root_path: P) -> Result<DocTree> {
|
||||
pub fn from_directory<P: AsRef<Path>>(root_path: P, doctree_name: Option<&str>) -> Result<DocTree> {
|
||||
let storage = RedisStorage::new("redis://localhost:6379")?;
|
||||
|
||||
DocTree::builder()
|
||||
.with_storage(storage)
|
||||
.scan_collections(root_path)?
|
||||
.build()
|
||||
let mut builder = DocTree::builder().with_storage(storage);
|
||||
|
||||
// Set the doctree name if provided
|
||||
if let Some(name) = doctree_name {
|
||||
builder = builder.with_doctree_name(name);
|
||||
}
|
||||
|
||||
builder.scan_collections(root_path)?.build()
|
||||
}
|
@@ -8,6 +8,8 @@ pub struct RedisStorage {
|
||||
client: Client,
|
||||
// Connection pool
|
||||
connection: Arc<Mutex<Connection>>,
|
||||
// Doctree name for key prefixing
|
||||
doctree_name: Arc<Mutex<String>>,
|
||||
}
|
||||
|
||||
impl RedisStorage {
|
||||
@@ -31,9 +33,30 @@ impl RedisStorage {
|
||||
Ok(Self {
|
||||
client,
|
||||
connection: Arc::new(Mutex::new(connection)),
|
||||
doctree_name: Arc::new(Mutex::new("default".to_string())),
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the doctree name for key prefixing
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `name` - Doctree name
|
||||
pub fn set_doctree_name(&self, name: &str) {
|
||||
let mut doctree_name = self.doctree_name.lock().unwrap();
|
||||
*doctree_name = name.to_string();
|
||||
}
|
||||
|
||||
/// Get the doctree name
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The doctree name
|
||||
pub fn get_doctree_name(&self) -> String {
|
||||
let doctree_name = self.doctree_name.lock().unwrap();
|
||||
doctree_name.clone()
|
||||
}
|
||||
|
||||
/// Store a collection entry
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -46,7 +69,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// Ok(()) on success or an error
|
||||
pub fn store_collection_entry(&self, collection: &str, key: &str, value: &str) -> Result<()> {
|
||||
let redis_key = format!("collections:{}", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let redis_key = format!("{}:collections:{}", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - HSET {} {} {}", redis_key, key, value);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -76,7 +100,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// The entry value or an error
|
||||
pub fn get_collection_entry(&self, collection: &str, key: &str) -> Result<String> {
|
||||
let collection_key = format!("collections:{}", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let collection_key = format!("{}:collections:{}", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - HGET {} {}", collection_key, key);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -115,7 +140,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// Ok(()) on success or an error
|
||||
pub fn delete_collection_entry(&self, collection: &str, key: &str) -> Result<()> {
|
||||
let collection_key = format!("collections:{}", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let collection_key = format!("{}:collections:{}", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - HDEL {} {}", collection_key, key);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -153,7 +179,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// A vector of entry keys or an error
|
||||
pub fn list_collection_entries(&self, collection: &str) -> Result<Vec<String>> {
|
||||
let collection_key = format!("collections:{}", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let collection_key = format!("{}:collections:{}", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - HKEYS {}", collection_key);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -191,7 +218,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// Ok(()) on success or an error
|
||||
pub fn delete_collection(&self, collection: &str) -> Result<()> {
|
||||
let redis_key = format!("collections:{}", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let redis_key = format!("{}:collections:{}", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - DEL {}", redis_key);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -217,7 +245,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// true if the collection exists, false otherwise
|
||||
pub fn collection_exists(&self, collection: &str) -> Result<bool> {
|
||||
let collection_key = format!("collections:{}", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let collection_key = format!("{}:collections:{}", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - EXISTS {}", collection_key);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -241,22 +270,27 @@ impl RedisStorage {
|
||||
///
|
||||
/// A vector of collection names or an error
|
||||
pub fn list_all_collections(&self) -> Result<Vec<String>> {
|
||||
println!("DEBUG: Redis operation - KEYS collections:*");
|
||||
let doctree_name = self.get_doctree_name();
|
||||
println!("DEBUG: Redis operation - KEYS {}:collections:*", doctree_name);
|
||||
|
||||
// Get a connection from the pool
|
||||
let mut conn = self.connection.lock().unwrap();
|
||||
|
||||
// Get all collection keys
|
||||
let pattern = format!("{}:collections:*", doctree_name);
|
||||
let keys: Vec<String> = redis::cmd("KEYS")
|
||||
.arg("collections:*")
|
||||
.arg(&pattern)
|
||||
.query(&mut *conn)
|
||||
.map_err(|e| DocTreeError::RedisError(format!("Redis error: {}", e)))?;
|
||||
|
||||
// Extract collection names from keys (remove the "collections:" prefix)
|
||||
// Extract collection names from keys (remove the "{doctree_name}:collections:" prefix)
|
||||
let prefix = format!("{}:collections:", doctree_name);
|
||||
let prefix_len = prefix.len();
|
||||
|
||||
let collections = keys.iter()
|
||||
.filter_map(|key| {
|
||||
if key.starts_with("collections:") {
|
||||
Some(key[12..].to_string())
|
||||
if key.starts_with(&prefix) {
|
||||
Some(key[prefix_len..].to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -274,14 +308,16 @@ impl RedisStorage {
|
||||
///
|
||||
/// Ok(()) on success or an error
|
||||
pub fn delete_all_collections(&self) -> Result<()> {
|
||||
println!("DEBUG: Redis operation - KEYS collections:*");
|
||||
let doctree_name = self.get_doctree_name();
|
||||
println!("DEBUG: Redis operation - KEYS {}:collections:*", doctree_name);
|
||||
|
||||
// Get a connection from the pool
|
||||
let mut conn = self.connection.lock().unwrap();
|
||||
|
||||
// Get all collection keys
|
||||
let pattern = format!("{}:collections:*", doctree_name);
|
||||
let keys: Vec<String> = redis::cmd("KEYS")
|
||||
.arg("collections:*")
|
||||
.arg(&pattern)
|
||||
.query(&mut *conn)
|
||||
.map_err(|e| DocTreeError::RedisError(format!("Redis error: {}", e)))?;
|
||||
|
||||
@@ -298,6 +334,7 @@ impl RedisStorage {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Store a collection's path
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -309,7 +346,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// Ok(()) on success or an error
|
||||
pub fn store_collection_path(&self, collection: &str, path: &str) -> Result<()> {
|
||||
let redis_key = format!("collections:{}:path", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let redis_key = format!("{}:collections:{}:path", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - SET {} {}", redis_key, path);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -337,7 +375,8 @@ impl RedisStorage {
|
||||
///
|
||||
/// The collection path or an error
|
||||
pub fn get_collection_path(&self, collection: &str) -> Result<String> {
|
||||
let redis_key = format!("collections:{}:path", collection);
|
||||
let doctree_name = self.get_doctree_name();
|
||||
let redis_key = format!("{}:collections:{}:path", doctree_name, collection);
|
||||
println!("DEBUG: Redis operation - GET {}", redis_key);
|
||||
|
||||
// Get a connection from the pool
|
||||
@@ -375,6 +414,7 @@ impl Clone for RedisStorage {
|
||||
Self {
|
||||
client: self.client.clone(),
|
||||
connection: Arc::new(Mutex::new(connection)),
|
||||
doctree_name: self.doctree_name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user