tower_cache/
lru.rs

1//! # LRU cache provider
2//!
3//! This is an implementation of a [`CacheLayer`] provider using [`lru::LruCache`].
4
5use crate::{ProviderRequest, ProviderResponse};
6use lru::LruCache;
7use std::{
8    convert::Infallible,
9    future::{ready, Future},
10    hash::Hash,
11    marker::PhantomData,
12    pin::Pin,
13    sync::{Arc, Mutex},
14    task::{Context, Poll},
15};
16use tower::Service;
17
18/// Local LRU cache provider
19#[derive(Debug, Clone)]
20pub struct LruProvider<'a, K, V>
21where
22    K: Eq + Hash,
23{
24    inner: Arc<Mutex<LruCache<K, V>>>,
25    _phantom: PhantomData<&'a ()>,
26}
27
28impl<'a, K, V> LruProvider<'a, K, V>
29where
30    K: Eq + Hash,
31{
32    /// Create a new LRU cache provider with the desired capacity
33    pub fn new(capacity: usize) -> Self {
34        Self {
35            inner: Arc::new(Mutex::new(LruCache::new(capacity))),
36            _phantom: PhantomData,
37        }
38    }
39}
40
41impl<'a, K, V> Service<ProviderRequest<K, V>> for LruProvider<'a, K, V>
42where
43    K: Eq + Hash,
44    V: Clone + Send + 'a,
45{
46    type Response = ProviderResponse<V>;
47    type Error = Infallible;
48    type Future = ProviderFuture<'a, V>;
49
50    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
51        Poll::Ready(Ok(()))
52    }
53
54    fn call(&mut self, request: ProviderRequest<K, V>) -> Self::Future {
55        Box::pin(ready(Ok(match request {
56            ProviderRequest::Get(key) => match self.inner.lock().unwrap().get(&key) {
57                Some(value) => ProviderResponse::Found(value.clone()),
58                None => ProviderResponse::NotFound,
59            },
60            ProviderRequest::Insert(key, value) => {
61                self.inner.lock().unwrap().put(key, value.clone());
62                ProviderResponse::Found(value)
63            }
64        })))
65    }
66}
67
68type ProviderFuture<'a, V> =
69    Pin<Box<dyn Future<Output = Result<ProviderResponse<V>, Infallible>> + Send + 'a>>;