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 {}