1use std::collections::BTreeMap;
2use std::ops::Bound;
3use std::sync::RwLock;
4
5use anyhow::Result;
6use async_trait::async_trait;
7
8#[async_trait]
9pub trait KVStore: Send + Sync {
10 async fn get(&self, key: String) -> Result<Option<surrealdb_types::Value>>;
11 async fn set(&self, key: String, value: surrealdb_types::Value) -> Result<()>;
12 async fn del(&self, key: String) -> Result<()>;
13 async fn exists(&self, key: String) -> Result<bool>;
14
15 async fn del_rng(&self, start: Bound<String>, end: Bound<String>) -> Result<()>;
16
17 async fn get_batch(&self, keys: Vec<String>) -> Result<Vec<Option<surrealdb_types::Value>>>;
18 async fn set_batch(&self, entries: Vec<(String, surrealdb_types::Value)>) -> Result<()>;
19 async fn del_batch(&self, keys: Vec<String>) -> Result<()>;
20
21 async fn keys(&self, start: Bound<String>, end: Bound<String>) -> Result<Vec<String>>;
22 async fn values(
23 &self,
24 start: Bound<String>,
25 end: Bound<String>,
26 ) -> Result<Vec<surrealdb_types::Value>>;
27 async fn entries(
28 &self,
29 start: Bound<String>,
30 end: Bound<String>,
31 ) -> Result<Vec<(String, surrealdb_types::Value)>>;
32 async fn count(&self, start: Bound<String>, end: Bound<String>) -> Result<u64>;
33}
34
35pub struct BTreeMapStore {
37 inner: RwLock<BTreeMap<String, surrealdb_types::Value>>,
38}
39
40impl BTreeMapStore {
41 pub fn new() -> Self {
43 Self {
44 inner: RwLock::new(BTreeMap::new()),
45 }
46 }
47
48 pub fn with_capacity(_capacity: usize) -> Self {
50 Self {
52 inner: RwLock::new(BTreeMap::new()),
53 }
54 }
55
56 fn in_range(&self, key: &str, start: &Bound<String>, end: &Bound<String>) -> bool {
58 match start {
59 Bound::Included(start_key) => {
60 if key < start_key.as_str() {
61 return false;
62 }
63 }
64 Bound::Excluded(start_key) => {
65 if key <= start_key.as_str() {
66 return false;
67 }
68 }
69 Bound::Unbounded => {}
70 }
71
72 match end {
73 Bound::Included(end_key) => {
74 if key > end_key.as_str() {
75 return false;
76 }
77 }
78 Bound::Excluded(end_key) => {
79 if key >= end_key.as_str() {
80 return false;
81 }
82 }
83 Bound::Unbounded => {}
84 }
85 true
86 }
87}
88
89impl Default for BTreeMapStore {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95#[async_trait]
96impl KVStore for BTreeMapStore {
97 async fn get(&self, key: String) -> Result<Option<surrealdb_types::Value>> {
98 let map = self
99 .inner
100 .read()
101 .map_err(|_| anyhow::anyhow!("Failed to get from KV store: Could not acquire lock"))?;
102 Ok(map.get(&key).cloned())
103 }
104
105 async fn set(&self, key: String, value: surrealdb_types::Value) -> Result<()> {
106 let mut map = self
107 .inner
108 .write()
109 .map_err(|_| anyhow::anyhow!("Failed to set in KV store: Could not acquire lock"))?;
110 map.insert(key, value);
111 Ok(())
112 }
113
114 async fn del(&self, key: String) -> Result<()> {
115 let mut map = self.inner.write().map_err(|_| {
116 anyhow::anyhow!("Failed to delete from KV store: Could not acquire lock")
117 })?;
118 map.remove(&key);
119 Ok(())
120 }
121
122 async fn exists(&self, key: String) -> Result<bool> {
123 let map = self.inner.read().map_err(|_| {
124 anyhow::anyhow!("Failed to check if key exists in KV store: Could not acquire lock")
125 })?;
126 Ok(map.contains_key(&key))
127 }
128
129 async fn del_rng(&self, start: Bound<String>, end: Bound<String>) -> Result<()> {
130 let mut map = self.inner.write().map_err(|_| {
131 anyhow::anyhow!("Failed to delete range from KV store: Could not acquire lock")
132 })?;
133 let keys_to_remove: Vec<String> =
134 map.keys().filter(|key| self.in_range(key, &start, &end)).cloned().collect();
135 for key in keys_to_remove {
136 map.remove(&key);
137 }
138 Ok(())
139 }
140
141 async fn get_batch(&self, keys: Vec<String>) -> Result<Vec<Option<surrealdb_types::Value>>> {
142 let map = self.inner.read().map_err(|_| {
143 anyhow::anyhow!("Failed to get batch from KV store: Could not acquire lock")
144 })?;
145 let mut results = Vec::with_capacity(keys.len());
146 for key in keys {
147 results.push(map.get(&key).cloned());
148 }
149 Ok(results)
150 }
151
152 async fn set_batch(&self, entries: Vec<(String, surrealdb_types::Value)>) -> Result<()> {
153 let mut map = self.inner.write().map_err(|_| {
154 anyhow::anyhow!("Failed to set batch in KV store: Could not acquire lock")
155 })?;
156 for (key, value) in entries {
157 map.insert(key, value);
158 }
159 Ok(())
160 }
161
162 async fn del_batch(&self, keys: Vec<String>) -> Result<()> {
163 let mut map = self.inner.write().map_err(|_| {
164 anyhow::anyhow!("Failed to delete batch from KV store: Could not acquire lock")
165 })?;
166 for key in keys {
167 map.remove(&key);
168 }
169 Ok(())
170 }
171
172 async fn keys(&self, start: Bound<String>, end: Bound<String>) -> Result<Vec<String>> {
173 let map = self.inner.read().map_err(|_| {
174 anyhow::anyhow!("Failed to collect keys from KV store: Could not acquire lock")
175 })?;
176 let keys: Vec<String> =
177 map.keys().filter(|key| self.in_range(key, &start, &end)).cloned().collect();
178 Ok(keys)
179 }
180
181 async fn values(
182 &self,
183 start: Bound<String>,
184 end: Bound<String>,
185 ) -> Result<Vec<surrealdb_types::Value>> {
186 let map = self.inner.read().map_err(|_| {
187 anyhow::anyhow!("Failed to collect values from KV store: Could not acquire lock")
188 })?;
189 let values: Vec<surrealdb_types::Value> = map
190 .iter()
191 .filter(|(key, _)| self.in_range(key, &start, &end))
192 .map(|(_, value)| value.clone())
193 .collect();
194 Ok(values)
195 }
196
197 async fn entries(
198 &self,
199 start: Bound<String>,
200 end: Bound<String>,
201 ) -> Result<Vec<(String, surrealdb_types::Value)>> {
202 let map = self.inner.read().map_err(|_| {
203 anyhow::anyhow!("Failed to collect entries from KV store: Could not acquire lock")
204 })?;
205 let entries: Vec<(String, surrealdb_types::Value)> = map
206 .iter()
207 .filter(|(key, _)| self.in_range(key, &start, &end))
208 .map(|(key, value)| (key.clone(), value.clone()))
209 .collect();
210 Ok(entries)
211 }
212
213 async fn count(&self, start: Bound<String>, end: Bound<String>) -> Result<u64> {
214 let map = self.inner.read().map_err(|_| {
215 anyhow::anyhow!("Failed to get count from KV store: Could not acquire lock")
216 })?;
217 let count = map.keys().filter(|key| self.in_range(key, &start, &end)).count();
218 Ok(count as u64)
219 }
220}