Crates.io | rkvs |
lib.rs | rkvs |
version | 0.1.0 |
created_at | 2025-09-18 14:10:10.77945+00 |
updated_at | 2025-09-18 14:10:10.77945+00 |
description | A high-performance, namespace-based key-value storage system with async operations and batch processing |
homepage | |
repository | https://github.com/Tomasz-Bak/rkvs |
max_upload_size | |
id | 1844777 |
size | 147,647 |
A high-performance, namespace-based key-value storage system built in Rust. RKVS provides persistent storage with configurable limits, async operations, and atomic batch processing.
Add RKVS to your Cargo.toml
:
[dependencies]
rkvs = "0.1.0"
tokio = { version = "1.0", features = ["full"] }
use rkvs::{StorageManager, NamespaceConfig, Result};
#[tokio::main]
async fn main() -> Result<()> {
// Create a storage manager
let storage = StorageManager::builder()
.with_persistence("/tmp/rkvs_data".into())
.build();
// Initialize the storage
storage.initialize().await?;
// Create a namespace with configuration
let config = NamespaceConfig {
max_keys: Some(1000),
max_value_size: Some(1024 * 1024), // 1MB
};
let ns_hash = storage.create_namespace("my_app", Some(config)).await?;
// Get the namespace handle
let namespace = storage.namespace(ns_hash).await?;
// Store data
namespace.set("user:123".to_string(), b"John Doe".to_vec()).await?;
// Retrieve data
if let Some(data) = namespace.get("user:123").await {
println!("User: {}", String::from_utf8_lossy(&data));
}
// Atomic consume (get and delete)
if let Some(data) = namespace.consume("user:123").await {
println!("Consumed: {}", String::from_utf8_lossy(&data));
// Key is now deleted
}
Ok(())
}
RKVS supports efficient batch operations for processing multiple key-value pairs:
use rkvs::{Namespace, BatchResult};
async fn batch_example(namespace: &Namespace) -> Result<()> {
// Batch set multiple items
let items = vec![
("key1".to_string(), b"value1".to_vec()),
("key2".to_string(), b"value2".to_vec()),
("key3".to_string(), b"value3".to_vec()),
];
let result = namespace.set_multiple(items).await;
if result.is_success() {
println!("Set {} items successfully", result.total_processed);
} else {
println!("Errors: {:?}", result.errors);
}
// Batch get multiple items
let keys = vec!["key1".to_string(), "key2".to_string(), "key3".to_string()];
let result = namespace.get_multiple(keys).await;
if let Some(data) = result.data {
for (key, value) in data {
println!("{}: {}", key, String::from_utf8_lossy(&value));
}
}
Ok(())
}
Configure storage and namespace limits:
use rkvs::{StorageConfig, NamespaceConfig};
// Global storage configuration
let storage_config = StorageConfig {
max_namespaces: Some(100),
default_max_keys_per_namespace: Some(10000),
default_max_value_size: Some(10 * 1024 * 1024), // 10MB
};
// Per-namespace configuration
let namespace_config = NamespaceConfig {
max_keys: Some(1000),
max_value_size: Some(1024 * 1024), // 1MB
};
let storage = StorageManager::builder()
.with_config(storage_config)
.with_persistence("/data/rkvs".into())
.build();
RKVS is designed for high performance with the following characteristics:
See the benchmark results for detailed performance metrics.
StorageManager
: Main entry point for managing namespacesNamespace
: Handle for working with a specific namespaceNamespaceConfig
: Configuration for namespace limitsStorageConfig
: Global storage configurationBatchResult<T>
: Result of batch operations with metadatacreate_namespace(name, config)
- Create a new namespacenamespace(hash)
- Get a namespace handledelete_namespace(hash)
- Remove a namespacelist_namespaces()
- List all namespacessave()
/ load()
- Persistence operationsset(key, value)
- Store a key-value pairget(key)
- Retrieve a valuedelete(key)
- Remove a keyexists(key)
- Check if key existsconsume(key)
- Atomically get and deleteset_multiple(items)
- Batch set operationget_multiple(keys)
- Batch get operationdelete_multiple(keys)
- Batch delete operationconsume_multiple(keys)
- Batch consume operationRKVS uses a unified error type RkvsError
with the following variants:
Storage
: File I/O and storage-related errorsSerialization
: Data serialization/deserialization errorsInternal
: Internal system errorsuse rkvs::{Result, RkvsError};
async fn error_handling_example() -> Result<()> {
match namespace.set("key".to_string(), b"value".to_vec()).await {
Ok(()) => println!("Success"),
Err(RkvsError::Storage(msg)) => println!("Storage error: {}", msg),
Err(RkvsError::Serialization(msg)) => println!("Serialization error: {}", msg),
Err(RkvsError::Internal(msg)) => println!("Internal error: {}", msg),
}
Ok(())
}
RKVS is fully thread-safe and designed for concurrent access:
RKVS supports optional file-based persistence:
let storage = StorageManager::builder()
.with_persistence("/path/to/data".into())
.build();
// Save all data to disk
storage.save().await?;
// Load data from disk
storage.load().await?;
Data is automatically serialized using bincode
for efficient storage.
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.