citadel_sdk/
backend_kv_store.rs

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