tetrio_api/http/caches/
moka.rs

1#![cfg(feature = "in_memory_cache")]
2use std::{convert::Infallible, fmt::Debug, sync::Arc};
3
4use async_trait::async_trait;
5use moka::{future::Cache, Expiry};
6use serde::{de::DeserializeOwned, Serialize};
7
8use crate::{http::error::Error, models::packet::{Packet, SuccessPacket}};
9
10use super::cache::CacheHandler;
11
12
13
14/// A struct used to automatically remove the cache entries when their expiration date has passed.
15/// It is based around the cached_until field sent by the TETR.IO api, ensuring that the cache is always respected.
16pub struct CacheExpiration;
17
18impl<K, T> Expiry<K, Arc<SuccessPacket<T>>> for CacheExpiration {
19    fn expire_after_create(&self, _key: &K, value: &Arc<SuccessPacket<T>>, _current_time: std::time::Instant) -> Option<std::time::Duration> {
20         Some(value.cache.time_until_elapsed())
21    }
22}
23
24/// A cache implementation that uses the moka crate to automatically remove the cache entries when their expiration date has passed.
25pub struct MokaCache {
26    cache: Cache<String, Arc<SuccessPacket<serde_json::Value>>>,
27}
28
29impl Default for MokaCache {
30    fn default() -> Self {
31        MokaCache {  
32            cache: Cache::builder().expire_after(CacheExpiration).build()
33        }
34    }
35}
36
37#[async_trait]
38impl<ErrorT: std::error::Error + Sync + Send + Debug> CacheHandler<ErrorT> for MokaCache {
39    type CachingError = Infallible;
40    async fn try_get_cache<T: DeserializeOwned + Serialize>(&self, cache_key: &str) -> Result<Option<Packet<T>>, Error<ErrorT, Self::CachingError>>
41    {
42        // Get cached value
43
44        if let Some(json_value) = self.cache.get(cache_key).await {
45            // Parse cache value
46            let result = serde_json::from_value::<T>(json_value.data.clone()).map_err(Error::CacheConversionError);
47                match result {
48                    Ok(r) => {
49                        // Return cached value
50                        return Ok(Some(Packet {
51                            success: json_value.success,
52                            cache: Some(json_value.cache.clone()),
53                            data: Some(r),
54                            error: None
55                        }));
56                    },
57                    Err(err) => {
58                        return Err(err);
59                    }
60                }
61        }
62
63        Ok(None)
64    }
65
66    async fn cache_value<T: DeserializeOwned + Serialize + Send + Sync>(&self, cache_key: &str, cache_value: SuccessPacket<T>) -> Result<(), Error<ErrorT, Self::CachingError>> {
67        let SuccessPacket { success, cache, data } = cache_value;
68        self.cache.insert(cache_key.to_string(), Arc::new(SuccessPacket {
69            success,
70            cache,
71            data: serde_json::to_value(data).map_err(|err| Error::SerdeError(err))?
72        })).await;
73
74        Ok(())
75    }
76
77}