1use 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#[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 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>>;