actix_cloud/memorydb/
default.rs1use std::{
2 cmp::{max, Reverse},
3 collections::HashMap,
4 sync::Arc,
5 time::Duration,
6};
7
8use anyhow::bail;
9use async_trait::async_trait;
10use chrono::Utc;
11use glob::Pattern;
12use parking_lot::{RwLock, RwLockWriteGuard};
13use priority_queue::PriorityQueue;
14
15use super::interface::MemoryDB;
16use crate::Result;
17
18struct Data(String, Option<i64>);
20
21impl Data {
22 fn now() -> i64 {
23 Utc::now().timestamp_millis()
24 }
25
26 fn parse_ttl(ttl: Option<i64>) -> Option<i64> {
27 ttl.map(|x| Self::now().saturating_add(x))
28 }
29
30 fn new<S>(value: S, ttl: Option<i64>) -> Self
31 where
32 S: Into<String>,
33 {
34 Self(value.into(), Self::parse_ttl(ttl))
35 }
36
37 fn set_ttl(&mut self, ttl: Option<i64>) {
38 self.1 = Self::parse_ttl(ttl);
39 }
40
41 fn get_ttl(&self) -> Option<i64> {
42 self.1.map(|x| x.saturating_sub(Self::now()))
43 }
44
45 fn valid(&self) -> bool {
46 if let Some(x) = self.1 {
47 x > Self::now()
48 } else {
49 true
50 }
51 }
52}
53
54#[derive(Clone)]
69pub struct DefaultBackend {
70 data: Arc<RwLock<HashMap<String, Data>>>,
71 capacity: Option<usize>,
72}
73
74impl DefaultBackend {
75 pub fn new(capacity: Option<usize>) -> Self {
80 Self {
81 data: Default::default(),
82 capacity,
83 }
84 }
85
86 fn gc(&self, wlock: &mut RwLockWriteGuard<HashMap<String, Data>>, num: usize) -> usize {
91 let mut queue = PriorityQueue::new();
92 let mut delete = Vec::new();
93 for (k, v) in wlock.iter() {
94 if !v.valid() {
95 delete.push(k.to_owned());
96 } else if let Some(x) = v.1 {
97 queue.push(k.to_owned(), Reverse(x));
98 }
99 }
100 for i in &delete {
101 wlock.remove(i);
102 }
103 let mut ret = delete.len();
104 if ret < num {
105 let remain = num - ret;
106 for _ in 0..remain {
107 if let Some(k) = queue.pop() {
108 wlock.remove(&k.0);
109 ret += 1;
110 } else {
111 return ret;
112 }
113 }
114 }
115 ret
116 }
117}
118
119impl Default for DefaultBackend {
120 fn default() -> Self {
121 Self::new(None)
122 }
123}
124
125#[async_trait]
126impl MemoryDB for DefaultBackend {
127 async fn set(&self, key: &str, value: &str) -> Result<()> {
128 let mut wlock = self.data.write();
129 if let Some(x) = self.capacity {
131 if x >= wlock.len()
132 && self.gc(&mut wlock, max(x / 10, 1)) == 0
133 && wlock.get(key).is_none()
134 {
135 bail!("Capacity is full");
136 }
137 }
138 wlock.insert(key.to_owned(), Data::new(value, None));
139 Ok(())
140 }
141
142 async fn get(&self, key: &str) -> Result<Option<String>> {
143 let rlock = self.data.read();
144 if let Some(v) = rlock.get(key) {
145 if v.valid() {
146 Ok(Some(v.0.to_owned()))
147 } else {
148 drop(rlock);
149 self.data.write().remove(key);
150 Ok(None)
151 }
152 } else {
153 Ok(None)
154 }
155 }
156
157 async fn get_del(&self, key: &str) -> Result<Option<String>> {
158 let v = self.data.write().remove(key);
159 if let Some(v) = v {
160 if v.valid() {
161 return Ok(Some(v.0));
162 }
163 }
164 Ok(None)
165 }
166
167 async fn get_ex(&self, key: &str, ttl: &Duration) -> Result<Option<String>> {
168 let mut wlock = self.data.write();
169 if let Some(v) = wlock.get_mut(key) {
170 if v.valid() {
171 let ret = v.0.to_owned();
172 let ms = ttl.as_millis();
173 if ms == 0 {
174 wlock.remove(key);
175 } else {
176 v.set_ttl(Some(ms.try_into()?));
177 }
178 Ok(Some(ret))
179 } else {
180 wlock.remove(key);
181 Ok(None)
182 }
183 } else {
184 Ok(None)
185 }
186 }
187
188 async fn set_ex(&self, key: &str, value: &str, ttl: &Duration) -> Result<()> {
189 let ms = ttl.as_millis();
190 if ms == 0 {
191 return self.del(key).await.map(|_| ());
192 }
193 let mut wlock = self.data.write();
194 if let Some(x) = self.capacity {
196 if x >= wlock.len()
197 && self.gc(&mut wlock, max(x / 10, 1)) == 0
198 && wlock.get(key).is_none()
199 {
200 bail!("Capacity is full");
201 }
202 }
203 wlock.insert(key.to_owned(), Data::new(value, Some(ms.try_into()?)));
204 Ok(())
205 }
206
207 async fn del(&self, key: &str) -> Result<bool> {
208 Ok(self.data.write().remove(key).is_some())
209 }
210
211 async fn expire(&self, key: &str, ttl: &Duration) -> Result<bool> {
212 let ms = ttl.as_millis();
213 if ms == 0 {
214 self.del(key).await
215 } else {
216 let mut wlock = self.data.write();
217 if let Some(v) = wlock.get_mut(key) {
218 if v.valid() {
219 v.set_ttl(Some(ms.try_into()?));
220 Ok(true)
221 } else {
222 wlock.remove(key);
223 Ok(false)
224 }
225 } else {
226 Ok(false)
227 }
228 }
229 }
230
231 async fn flush(&self) -> Result<()> {
232 self.data.write().clear();
233 Ok(())
234 }
235
236 async fn keys(&self, key: &str) -> Result<Vec<String>> {
237 let mut ret = Vec::new();
238 let p = Pattern::new(key)?;
239 for (k, v) in self.data.read().iter() {
240 if v.valid() && p.matches(k) {
241 ret.push(k.to_owned());
242 }
243 }
244 Ok(ret)
245 }
246
247 async fn dels(&self, keys: &[String]) -> Result<u64> {
248 let mut wlock = self.data.write();
249 let mut sum = 0;
250 for i in keys {
251 if wlock.remove(i).is_some() {
252 sum += 1;
253 }
254 }
255 Ok(sum)
256 }
257
258 async fn ttl(&self, key: &str) -> Result<Option<Duration>> {
259 let rlock = self.data.read();
260 if let Some(v) = rlock.get(key) {
261 if v.valid() {
262 v.get_ttl()
263 .map(|x| Ok(Duration::from_millis(x.try_into()?)))
264 .transpose()
265 } else {
266 drop(rlock);
267 self.data.write().remove(key);
268 Ok(None)
269 }
270 } else {
271 Ok(None)
272 }
273 }
274}