1use async_trait::async_trait;
2use std::collections::HashMap;
3use std::time::Duration;
4
5use crate::data::cache::{CacheConfig, CacheError, CacheResult, CacheService, CacheStats, CacheType};
6use crate::ipc::send_request;
7use crate::ipc_types::{
8 ServiceOperation, ServiceOperationResult, ServiceRequest, ServiceResponse, ServiceType,
9};
10use base64::{Engine as _, engine::general_purpose::STANDARD};
11
12pub struct ProxyCacheService {
14 connection_id: String,
15 cache_type: CacheType,
16 default_ttl: Duration,
17}
18
19impl ProxyCacheService {
20 pub async fn connect(config: &CacheConfig) -> CacheResult<Self> {
21 let request_id = format!("cache_request_{}", uuid::Uuid::new_v4());
23
24 let request = ServiceRequest {
26 id: request_id.clone(),
27 service_type: ServiceType::Cache,
28 config: Some(serde_json::to_value(config).map_err(|e| {
29 CacheError::Configuration(format!("Failed to serialize cache config: {}", e))
30 })?),
31 };
32
33 let response = send_request(&request)
35 .await
36 .map_err(|e| CacheError::Connection(format!("Failed to send request: {}", e)))?;
37
38 let service_response: ServiceResponse = serde_json::from_str(&response)
40 .map_err(|e| CacheError::Connection(format!("Failed to parse response: {}", e)))?;
41
42 if !service_response.success {
44 return Err(CacheError::Connection(
45 service_response
46 .error
47 .unwrap_or_else(|| "Unknown connection error".to_string()),
48 ));
49 }
50
51 let connection_id = service_response
53 .connection_id
54 .ok_or_else(|| CacheError::Connection("No connection ID returned".to_string()))?;
55
56 Ok(Self {
57 connection_id,
58 cache_type: match config.cache_type {
59 CacheType::Redis => CacheType::Redis,
60 CacheType::Memcached => CacheType::Memcached,
61 CacheType::InMemory => CacheType::InMemory,
62 CacheType::File => CacheType::File,
63 },
64 default_ttl: config.get_default_ttl(),
65 })
66 }
67}
68
69#[async_trait]
70impl CacheService for ProxyCacheService {
71 async fn get(&self, key: &str) -> CacheResult<Option<Vec<u8>>> {
72 let operation = ServiceOperation {
73 connection_id: self.connection_id.clone(),
74 service_type: ServiceType::Cache,
75 operation: "get".to_string(),
76 params: serde_json::json!({
77 "key": key,
78 }),
79 };
80
81 let result = send_operation(operation).await?;
82 match result.result {
83 Some(value) => {
84 if value.is_null() {
85 return Ok(None);
86 }
87
88 if let Some(s) = value.as_str() {
89 match STANDARD.decode(s) {
91 Ok(bytes) => Ok(Some(bytes)),
92 Err(e) => Err(CacheError::Serialization(format!("Invalid base64: {}", e))),
93 }
94 } else if let Some(array) = value.as_array() {
95 let bytes: Result<Vec<u8>, _> = array
97 .iter()
98 .map(|v| {
99 if let Some(n) = v.as_u64() {
100 if n <= 255 {
101 Ok(n as u8)
102 } else {
103 Err(CacheError::Serialization(format!(
104 "Invalid byte value: {}",
105 n
106 )))
107 }
108 } else {
109 Err(CacheError::Serialization("Invalid byte value".to_string()))
110 }
111 })
112 .collect();
113
114 Ok(Some(bytes?))
115 } else {
116 Err(CacheError::Serialization(
117 "Invalid value format".to_string(),
118 ))
119 }
120 }
121 None => Ok(None),
122 }
123 }
124
125 async fn set(&self, key: &str, value: &[u8], ttl: Option<Duration>) -> CacheResult<()> {
126 let value_base64 = STANDARD.encode(value);
128
129 let ttl_seconds = ttl.map(|d| d.as_secs());
131
132 let operation = ServiceOperation {
133 connection_id: self.connection_id.clone(),
134 service_type: ServiceType::Cache,
135 operation: "set".to_string(),
136 params: serde_json::json!({
137 "key": key,
138 "value": value_base64,
139 "ttl_seconds": ttl_seconds,
140 }),
141 };
142
143 let result = send_operation(operation).await?;
144 if result.success {
145 Ok(())
146 } else {
147 Err(CacheError::Operation(
148 result
149 .error
150 .unwrap_or_else(|| "Set operation failed".to_string()),
151 ))
152 }
153 }
154
155 async fn delete(&self, key: &str) -> CacheResult<bool> {
156 let operation = ServiceOperation {
157 connection_id: self.connection_id.clone(),
158 service_type: ServiceType::Cache,
159 operation: "delete".to_string(),
160 params: serde_json::json!({
161 "key": key,
162 }),
163 };
164
165 let result = send_operation(operation).await?;
166 match result.result {
167 Some(value) => {
168 if let Some(success) = value.as_bool() {
169 Ok(success)
170 } else {
171 Err(CacheError::Operation("Invalid delete result".to_string()))
172 }
173 }
174 None => Ok(false), }
176 }
177
178 async fn exists(&self, key: &str) -> CacheResult<bool> {
179 let operation = ServiceOperation {
180 connection_id: self.connection_id.clone(),
181 service_type: ServiceType::Cache,
182 operation: "exists".to_string(),
183 params: serde_json::json!({
184 "key": key,
185 }),
186 };
187
188 let result = send_operation(operation).await?;
189 match result.result {
190 Some(value) => {
191 if let Some(exists) = value.as_bool() {
192 Ok(exists)
193 } else {
194 Err(CacheError::Operation("Invalid exists result".to_string()))
195 }
196 }
197 None => Ok(false), }
199 }
200
201 async fn set_nx(&self, key: &str, value: &[u8], ttl: Option<Duration>) -> CacheResult<bool> {
202 let value_base64 = STANDARD.encode(value);
204
205 let ttl_seconds = ttl.map(|d| d.as_secs());
207
208 let operation = ServiceOperation {
209 connection_id: self.connection_id.clone(),
210 service_type: ServiceType::Cache,
211 operation: "set_nx".to_string(),
212 params: serde_json::json!({
213 "key": key,
214 "value": value_base64,
215 "ttl_seconds": ttl_seconds,
216 }),
217 };
218
219 let result = send_operation(operation).await?;
220 match result.result {
221 Some(value) => {
222 if let Some(success) = value.as_bool() {
223 Ok(success)
224 } else {
225 Err(CacheError::Operation("Invalid set_nx result".to_string()))
226 }
227 }
228 None => Ok(false), }
230 }
231
232 async fn get_set(&self, key: &str, value: &[u8]) -> CacheResult<Option<Vec<u8>>> {
233 let value_base64 = STANDARD.encode(value);
235
236 let operation = ServiceOperation {
237 connection_id: self.connection_id.clone(),
238 service_type: ServiceType::Cache,
239 operation: "get_set".to_string(),
240 params: serde_json::json!({
241 "key": key,
242 "value": value_base64,
243 }),
244 };
245
246 let result = send_operation(operation).await?;
247 match result.result {
248 Some(value) => {
249 if value.is_null() {
250 return Ok(None);
251 }
252
253 if let Some(s) = value.as_str() {
254 match STANDARD.decode(s) {
256 Ok(bytes) => Ok(Some(bytes)),
257 Err(e) => Err(CacheError::Serialization(format!("Invalid base64: {}", e))),
258 }
259 } else {
260 Err(CacheError::Serialization(
261 "Invalid value format".to_string(),
262 ))
263 }
264 }
265 None => Ok(None),
266 }
267 }
268
269 async fn increment(&self, key: &str, delta: i64) -> CacheResult<i64> {
270 let operation = ServiceOperation {
271 connection_id: self.connection_id.clone(),
272 service_type: ServiceType::Cache,
273 operation: "increment".to_string(),
274 params: serde_json::json!({
275 "key": key,
276 "delta": delta,
277 }),
278 };
279
280 let result = send_operation(operation).await?;
281 match result.result {
282 Some(value) => {
283 if let Some(n) = value.as_i64() {
284 Ok(n)
285 } else {
286 Err(CacheError::Operation(
287 "Invalid increment result".to_string(),
288 ))
289 }
290 }
291 None => Err(CacheError::Operation(
292 "No result from increment operation".to_string(),
293 )),
294 }
295 }
296
297 async fn set_many(
298 &self,
299 items: &HashMap<String, Vec<u8>>,
300 ttl: Option<Duration>,
301 ) -> CacheResult<()> {
302 let mut items_base64 = HashMap::new();
304 for (key, value) in items {
305 items_base64.insert(key.clone(), STANDARD.encode(value));
306 }
307
308 let ttl_seconds = ttl.map(|d| d.as_secs());
310
311 let operation = ServiceOperation {
312 connection_id: self.connection_id.clone(),
313 service_type: ServiceType::Cache,
314 operation: "set_many".to_string(),
315 params: serde_json::json!({
316 "items": items_base64,
317 "ttl_seconds": ttl_seconds,
318 }),
319 };
320
321 let result = send_operation(operation).await?;
322 if result.success {
323 Ok(())
324 } else {
325 Err(CacheError::Operation(
326 result
327 .error
328 .unwrap_or_else(|| "Set many operation failed".to_string()),
329 ))
330 }
331 }
332
333 async fn get_many(&self, keys: &[String]) -> CacheResult<HashMap<String, Vec<u8>>> {
334 let operation = ServiceOperation {
335 connection_id: self.connection_id.clone(),
336 service_type: ServiceType::Cache,
337 operation: "get_many".to_string(),
338 params: serde_json::json!({
339 "keys": keys,
340 }),
341 };
342
343 let result = send_operation(operation).await?;
344 match result.result {
345 Some(value) => {
346 let map: HashMap<String, String> = serde_json::from_value(value).map_err(|e| {
347 CacheError::Serialization(format!("Failed to deserialize result: {}", e))
348 })?;
349
350 let mut result_map = HashMap::new();
351 for (key, value_base64) in map {
352 match STANDARD.decode(&value_base64) {
353 Ok(bytes) => {
354 result_map.insert(key, bytes);
355 }
356 Err(e) => {
357 return Err(CacheError::Serialization(format!(
358 "Invalid base64: {}",
359 e
360 )));
361 }
362 }
363 }
364
365 Ok(result_map)
366 }
367 None => Ok(HashMap::new()), }
369 }
370
371 async fn delete_many(&self, keys: &[String]) -> CacheResult<u64> {
372 let operation = ServiceOperation {
373 connection_id: self.connection_id.clone(),
374 service_type: ServiceType::Cache,
375 operation: "delete_many".to_string(),
376 params: serde_json::json!({
377 "keys": keys,
378 }),
379 };
380
381 let result = send_operation(operation).await?;
382 match result.result {
383 Some(value) => {
384 if let Some(n) = value.as_u64() {
385 Ok(n)
386 } else {
387 Err(CacheError::Operation(
388 "Invalid delete_many result".to_string(),
389 ))
390 }
391 }
392 None => Ok(0), }
394 }
395
396 async fn clear(&self, namespace: Option<&str>) -> CacheResult<()> {
397 let operation = ServiceOperation {
398 connection_id: self.connection_id.clone(),
399 service_type: ServiceType::Cache,
400 operation: "clear".to_string(),
401 params: serde_json::json!({
402 "namespace": namespace,
403 }),
404 };
405
406 let result = send_operation(operation).await?;
407 if result.success {
408 Ok(())
409 } else {
410 Err(CacheError::Operation(
411 result
412 .error
413 .unwrap_or_else(|| "Clear operation failed".to_string()),
414 ))
415 }
416 }
417
418 async fn lock(&self, key: &str, ttl: Duration) -> CacheResult<Option<String>> {
419 let operation = ServiceOperation {
420 connection_id: self.connection_id.clone(),
421 service_type: ServiceType::Cache,
422 operation: "lock".to_string(),
423 params: serde_json::json!({
424 "key": key,
425 "ttl_seconds": ttl.as_secs(),
426 }),
427 };
428
429 let result = send_operation(operation).await?;
430 match result.result {
431 Some(value) => {
432 if value.is_null() {
433 return Ok(None);
434 }
435
436 if let Some(s) = value.as_str() {
437 Ok(Some(s.to_string()))
438 } else {
439 Err(CacheError::Operation(
440 "Invalid lock token format".to_string(),
441 ))
442 }
443 }
444 None => Ok(None), }
446 }
447
448 async fn unlock(&self, key: &str, lock_token: &str) -> CacheResult<bool> {
449 let operation = ServiceOperation {
450 connection_id: self.connection_id.clone(),
451 service_type: ServiceType::Cache,
452 operation: "unlock".to_string(),
453 params: serde_json::json!({
454 "key": key,
455 "lock_token": lock_token,
456 }),
457 };
458
459 let result = send_operation(operation).await?;
460 match result.result {
461 Some(value) => {
462 if let Some(success) = value.as_bool() {
463 Ok(success)
464 } else {
465 Err(CacheError::Operation("Invalid unlock result".to_string()))
466 }
467 }
468 None => Ok(false), }
470 }
471
472 fn get_cache_type(&self) -> CacheType {
473 self.cache_type
474 }
475
476 async fn ping(&self) -> CacheResult<()> {
477 let operation = ServiceOperation {
478 connection_id: self.connection_id.clone(),
479 service_type: ServiceType::Cache,
480 operation: "ping".to_string(),
481 params: serde_json::json!({}),
482 };
483
484 let result = send_operation(operation).await?;
485 if result.success {
486 Ok(())
487 } else {
488 Err(CacheError::Connection(
489 result.error.unwrap_or_else(|| "Ping failed".to_string()),
490 ))
491 }
492 }
493
494 async fn close(&self) -> CacheResult<()> {
495 let operation = ServiceOperation {
496 connection_id: self.connection_id.clone(),
497 service_type: ServiceType::Cache,
498 operation: "close".to_string(),
499 params: serde_json::json!({}),
500 };
501
502 let result = send_operation(operation).await?;
503 if result.success {
504 Ok(())
505 } else {
506 Err(CacheError::Connection(
507 result.error.unwrap_or_else(|| "Close failed".to_string()),
508 ))
509 }
510 }
511
512 fn get_default_ttl(&self) -> Duration {
513 self.default_ttl
514 }
515
516 async fn stats(&self) -> CacheResult<CacheStats> {
517 let operation = ServiceOperation {
518 connection_id: self.connection_id.clone(),
519 service_type: ServiceType::Cache,
520 operation: "stats".to_string(),
521 params: serde_json::json!({}),
522 };
523
524 let result = send_operation(operation).await?;
525 match result.result {
526 Some(value) => serde_json::from_value(value).map_err(|e| {
527 CacheError::Serialization(format!("Failed to deserialize stats: {}", e))
528 }),
529 None => Err(CacheError::Operation("No stats available".to_string())),
530 }
531 }
532
533 async fn flush(&self) -> CacheResult<()> {
534 let operation = ServiceOperation {
535 connection_id: self.connection_id.clone(),
536 service_type: ServiceType::Cache,
537 operation: "flush".to_string(),
538 params: serde_json::json!({}),
539 };
540
541 let result = send_operation(operation).await?;
542 if result.success {
543 Ok(())
544 } else {
545 Err(CacheError::Operation(
546 result
547 .error
548 .unwrap_or_else(|| "Flush operation failed".to_string()),
549 ))
550 }
551 }
552}
553
554async fn send_operation(operation: ServiceOperation) -> CacheResult<ServiceOperationResult> {
556 let response = send_request(&operation)
557 .await
558 .map_err(|e| CacheError::Operation(format!("Failed to send operation: {}", e)))?;
559
560 let result: ServiceOperationResult = serde_json::from_str(&response)
561 .map_err(|e| CacheError::Operation(format!("Failed to parse response: {}", e)))?;
562
563 if !result.success {
564 let error_msg = result.error.unwrap_or_else(|| "Unknown error".to_string());
565 return Err(CacheError::Operation(error_msg));
566 }
567
568 Ok(result)
569}
570
571impl From<String> for CacheError {
573 fn from(error: String) -> Self {
574 CacheError::Connection(format!("IPC error: {}", error))
575 }
576}