sa_token_adapter/
storage.rs1use async_trait::async_trait;
6use std::time::Duration;
7use thiserror::Error;
8
9pub type StorageResult<T> = Result<T, StorageError>;
11
12#[derive(Debug, Error)]
14pub enum StorageError {
15 #[error("Storage operation failed: {0}")]
17 OperationFailed(String),
18
19 #[error("Key not found: {0}")]
21 KeyNotFound(String),
22
23 #[error("Serialization error: {0}")]
25 SerializationError(String),
26
27 #[error("Connection error: {0}")]
29 ConnectionError(String),
30
31 #[error("Internal error: {0}")]
33 InternalError(String),
34
35 #[error("Unsupported operation '{0}' on this storage backend")]
37 Unsupported(&'static str),
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct ScanPage {
43 pub keys: Vec<String>,
45 pub next_cursor: u64,
47}
48
49#[async_trait]
60pub trait SaStorage: Send + Sync {
61 async fn get(&self, key: &str) -> StorageResult<Option<String>>;
63 async fn set(&self, key: &str, value: &str, ttl: Option<Duration>) -> StorageResult<()>;
65 async fn delete(&self, key: &str) -> StorageResult<()>;
67 async fn exists(&self, key: &str) -> StorageResult<bool>;
69 async fn expire(&self, key: &str, ttl: Duration) -> StorageResult<()>;
71 async fn ttl(&self, key: &str) -> StorageResult<Option<Duration>>;
73
74 async fn mget(&self, keys: &[&str]) -> StorageResult<Vec<Option<String>>> {
76 let mut results = Vec::with_capacity(keys.len());
77 for key in keys {
78 results.push(self.get(key).await?);
79 }
80 Ok(results)
81 }
82
83 async fn mset(&self, items: &[(&str, &str)], ttl: Option<Duration>) -> StorageResult<()> {
85 for (key, value) in items {
86 self.set(key, value, ttl).await?;
87 }
88 Ok(())
89 }
90
91 async fn mdel(&self, keys: &[&str]) -> StorageResult<()> {
93 for key in keys {
94 self.delete(key).await?;
95 }
96 Ok(())
97 }
98
99 async fn incr(&self, key: &str) -> StorageResult<i64> {
103 let current = self
104 .get(key)
105 .await?
106 .and_then(|v| v.parse::<i64>().ok())
107 .unwrap_or(0);
108 let new_value = current + 1;
109 self.set(key, &new_value.to_string(), None).await?;
110 Ok(new_value)
111 }
112
113 async fn decr(&self, key: &str) -> StorageResult<i64> {
117 let current = self
118 .get(key)
119 .await?
120 .and_then(|v| v.parse::<i64>().ok())
121 .unwrap_or(0);
122 let new_value = current - 1;
123 self.set(key, &new_value.to_string(), None).await?;
124 Ok(new_value)
125 }
126
127 async fn clear(&self) -> StorageResult<()>;
129
130 async fn set_if_absent(
134 &self,
135 key: &str,
136 value: &str,
137 ttl: Option<Duration>,
138 ) -> StorageResult<bool>;
139
140 async fn get_del(&self, key: &str) -> StorageResult<Option<String>>;
144
145 async fn compare_and_swap(
155 &self,
156 key: &str,
157 expected: Option<&str>,
158 new_value: &str,
159 ttl: Option<Duration>,
160 ) -> StorageResult<bool>;
161
162 async fn compare_and_delete(&self, key: &str, expected: &str) -> StorageResult<bool>;
166
167 async fn list_push(
173 &self,
174 key: &str,
175 member: &str,
176 unique: bool,
177 ttl: Option<Duration>,
178 ) -> StorageResult<usize>;
179
180 async fn list_remove(&self, key: &str, member: &str) -> StorageResult<bool>;
182
183 async fn list_range(
187 &self,
188 key: &str,
189 start: usize,
190 limit: Option<usize>,
191 ) -> StorageResult<Vec<String>>;
192
193 async fn list_len(&self, key: &str) -> StorageResult<usize>;
197
198 async fn scan(&self, pattern: &str, cursor: u64, limit: usize) -> StorageResult<ScanPage>;
215}
216
217pub async fn scan_all_keys(
222 storage: &dyn SaStorage,
223 pattern: &str,
224 page_size: usize,
225) -> StorageResult<Vec<String>> {
226 let mut cursor = 0u64;
227 let mut all = Vec::new();
228 loop {
229 let page = storage.scan(pattern, cursor, page_size).await?;
230 all.extend(page.keys);
231 if page.next_cursor == 0 {
232 break;
233 }
234 cursor = page.next_cursor;
235 }
236 Ok(all)
237}
238
239pub async fn scan_all_keys_dedup(
243 storage: &dyn SaStorage,
244 pattern: &str,
245 page_size: usize,
246) -> StorageResult<Vec<String>> {
247 use std::collections::HashSet;
248 let all = scan_all_keys(storage, pattern, page_size).await?;
249 let deduped: Vec<String> = all
250 .into_iter()
251 .collect::<HashSet<_>>()
252 .into_iter()
253 .collect();
254 Ok(deduped)
255}