1use async_trait::async_trait;
3use ecat_errors::{Error, ErrorCode};
4use std::time::Duration;
5
6#[async_trait]
7pub trait Cache: Send + Sync {
8 async fn get(&self, key: &str) -> Result<Option<Vec<u8>>, Error>;
9 async fn set(&self, key: &str, value: &[u8], ttl: Duration) -> Result<(), Error>;
10 async fn delete(&self, key: &str) -> Result<(), Error>;
11
12 async fn increment(&self, _key: &str, _delta: i64) -> Result<i64, Error> {
15 Err(Error::new(
16 ErrorCode::Internal,
17 "cache",
18 "increment not supported by this backend",
19 ))
20 }
21
22 async fn ttl(&self, _key: &str) -> Result<Option<Duration>, Error> {
24 Err(Error::new(
25 ErrorCode::Internal,
26 "cache",
27 "ttl not supported by this backend",
28 ))
29 }
30
31 async fn multi_get(&self, _keys: &[&str]) -> Result<Vec<Option<Vec<u8>>>, Error> {
33 Err(Error::new(
34 ErrorCode::Internal,
35 "cache",
36 "multi_get not supported by this backend",
37 ))
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 struct MinimalCache;
47
48 #[async_trait]
49 impl Cache for MinimalCache {
50 async fn get(&self, _key: &str) -> Result<Option<Vec<u8>>, Error> {
51 Ok(None)
52 }
53 async fn set(&self, _key: &str, _value: &[u8], _ttl: Duration) -> Result<(), Error> {
54 Ok(())
55 }
56 async fn delete(&self, _key: &str) -> Result<(), Error> {
57 Ok(())
58 }
59 }
60
61 #[tokio::test]
62 async fn optional_ops_default_to_not_supported_error() {
63 let cache = MinimalCache;
64 let err = cache.increment("k", 1).await.unwrap_err();
65 assert!(
66 err.to_string().contains("increment not supported"),
67 "got: {err}"
68 );
69 let err = cache.ttl("k").await.unwrap_err();
70 assert!(err.to_string().contains("ttl not supported"), "got: {err}");
71 let err = cache.multi_get(&["a", "b"]).await.unwrap_err();
72 assert!(
73 err.to_string().contains("multi_get not supported"),
74 "got: {err}"
75 );
76 }
77}