citadel_sdk/backend_kv_store.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
//! Connection-Specific Key-Value Storage
//!
//! This module provides a trait for persistent key-value storage that is unique to each
//! connection in the Citadel Protocol. It allows applications to store and retrieve
//! arbitrary data associated with specific peer connections.
//!
//! # Features
//! - Connection-scoped storage (unique per session and peer)
//! - Basic key-value operations (get, set, remove)
//! - Bulk operations for managing multiple key-value pairs
//! - Automatic error handling and conversion
//!
//! # Example
//! ```rust
//! use citadel_sdk::prelude::*;
//!
//! async fn store_data<T: BackendHandler<R>, R: Ratchet>(handler: &T) -> Result<(), NetworkError> {
//! // Store a value
//! handler.set("my_key", b"my_value".to_vec()).await?;
//!
//! // Retrieve the value
//! if let Some(value) = handler.get("my_key").await? {
//! println!("Retrieved value: {:?}", value);
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! # Important Notes
//! - Storage is tied to the connection's session and peer IDs
//! - All operations are asynchronous and may fail
//! - Values are stored as raw bytes (Vec<u8>)
//!
//! # Related Components
//! - [`TargetLockedRemote`]: Trait for accessing connection-specific information
//! - [`PersistenceHandler`]: Backend storage implementation
//!
//! [`TargetLockedRemote`]: crate::prelude::TargetLockedRemote
//! [`PersistenceHandler`]: crate::prelude::PersistenceHandler
use crate::prelude::*;
use std::collections::HashMap;
const DATA_MAP_KEY: &str = "_INTERNAL_DATA_MAP";
#[async_trait]
/// Contains a trait for persisting application-level data in a K,V store that is unique
/// for this particular connection
pub trait BackendHandler<R: Ratchet>: TargetLockedRemote<R> {
/// Gets a value from the backend
async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, NetworkError> {
let (session_cid, peer_cid) = self.get_cids();
self.remote()
.account_manager()
.get_persistence_handler()
.get_byte_map_value(session_cid, peer_cid, DATA_MAP_KEY, key)
.await
.map_err(|err| NetworkError::msg(err.into_string()))
}
/// Removes a value from the backend, returning the previous value
async fn remove(&self, key: &str) -> Result<Option<Vec<u8>>, NetworkError> {
let (session_cid, peer_cid) = self.get_cids();
self.remote()
.account_manager()
.get_persistence_handler()
.remove_byte_map_value(session_cid, peer_cid, DATA_MAP_KEY, key)
.await
.map_err(|err| NetworkError::msg(err.into_string()))
}
/// Stores a value in the backend, either creating or overwriting any pre-existing value
async fn set(&self, key: &str, value: Vec<u8>) -> Result<Option<Vec<u8>>, NetworkError> {
let (session_cid, peer_cid) = self.get_cids();
self.remote()
.account_manager()
.get_persistence_handler()
.store_byte_map_value(session_cid, peer_cid, DATA_MAP_KEY, key, value)
.await
.map_err(|err| NetworkError::msg(err.into_string()))
}
/// Obtains the K,V map for this application
async fn get_all(&self) -> Result<HashMap<String, Vec<u8>>, NetworkError> {
let (session_cid, peer_cid) = self.get_cids();
self.remote()
.account_manager()
.get_persistence_handler()
.get_byte_map_values_by_key(session_cid, peer_cid, DATA_MAP_KEY)
.await
.map_err(|err| NetworkError::msg(err.into_string()))
}
/// Obtains a list of K,V pairs such that `needle` is a subset of the K value
async fn remove_all(&self) -> Result<HashMap<String, Vec<u8>>, NetworkError> {
let (session_cid, peer_cid) = self.get_cids();
self.remote()
.account_manager()
.get_persistence_handler()
.remove_byte_map_values_by_key(session_cid, peer_cid, DATA_MAP_KEY)
.await
.map_err(|err| NetworkError::msg(err.into_string()))
}
#[doc(hidden)]
fn get_cids(&self) -> (u64, u64) {
(self.user().get_session_cid(), self.user().get_target_cid())
}
}
impl<T: TargetLockedRemote<R>, R: Ratchet> BackendHandler<R> for T {}