Skip to main content

claw10_store/
namespaced.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4
5use crate::{Store, StoreError};
6
7/// `NamespacedStore` membungkus store apapun dan menambahkan prefix namespace ke setiap key.
8/// Consumer store tidak perlu sadar tentang namespace — semua operasi key transparan.
9/// 
10/// Contoh: namespace `"ws:a3f9b2c1:"` + key `"agent:xxx"` → disimpan sebagai `"ws:a3f9b2c1:agent:xxx"`.
11/// Saat scan/read, namespace di-strip dari key yang dikembalikan ke consumer.
12#[derive(Clone)]
13pub struct NamespacedStore {
14    inner: Arc<dyn Store>,
15    namespace: String,
16    namespace_len: usize,
17}
18
19impl NamespacedStore {
20    pub fn new(inner: Arc<dyn Store>, namespace: impl Into<String>) -> Self {
21        let namespace = namespace.into();
22        let namespace_len = namespace.len();
23        Self {
24            inner,
25            namespace,
26            namespace_len,
27        }
28    }
29
30    fn ns_key(&self, key: &str) -> String {
31        let mut out = String::with_capacity(self.namespace_len + key.len());
32        out.push_str(&self.namespace);
33        out.push_str(key);
34        out
35    }
36
37    fn strip_ns<'a>(&self, key: &'a str) -> &'a str {
38        // Aman karena key yang di-scan pasti diawali namespace
39        &key[self.namespace_len..]
40    }
41}
42
43#[async_trait]
44impl Store for NamespacedStore {
45    async fn get_raw(&self, key: &str) -> Result<Option<Vec<u8>>, StoreError> {
46        self.inner.get_raw(&self.ns_key(key)).await
47    }
48
49    async fn set_raw(&self, key: &str, value: Vec<u8>) -> Result<(), StoreError> {
50        self.inner.set_raw(&self.ns_key(key), value).await
51    }
52
53    async fn delete(&self, key: &str) -> Result<(), StoreError> {
54        self.inner.delete(&self.ns_key(key)).await
55    }
56
57    async fn exists(&self, key: &str) -> Result<bool, StoreError> {
58        self.inner.exists(&self.ns_key(key)).await
59    }
60
61    async fn scan_prefix_raw(&self, prefix: &str) -> Result<Vec<(String, Vec<u8>)>, StoreError> {
62        let ns_prefix = self.ns_key(prefix);
63        let raw = self.inner.scan_prefix_raw(&ns_prefix).await?;
64        Ok(raw
65            .into_iter()
66            .map(|(key, value)| (self.strip_ns(&key).to_string(), value))
67            .collect())
68    }
69
70    async fn list_keys(&self, prefix: &str) -> Result<Vec<String>, StoreError> {
71        let ns_prefix = self.ns_key(prefix);
72        let keys = self.inner.list_keys(&ns_prefix).await?;
73        Ok(keys
74            .into_iter()
75            .map(|k| self.strip_ns(&k).to_string())
76            .collect())
77    }
78
79    /// Hanya menghapus key yang berawalan namespace ini — tidak menghapus seluruh database.
80    async fn clear(&self) -> Result<(), StoreError> {
81        let keys = self.inner.list_keys(&self.namespace).await?;
82        for key in keys {
83            self.inner.delete(&key).await?;
84        }
85        Ok(())
86    }
87}