1use serde::{de::DeserializeOwned, Serialize};
2use std::collections::hash_map::DefaultHasher;
3use std::future::Future;
4use std::hash::{Hash, Hasher};
5
6use crate::client::WorkerClient;
7use crate::error::CacheError;
8use crate::options::CacheOptions;
9
10pub struct Cache {
11 client: WorkerClient,
12}
13
14type CacheFuture<R> = Box<dyn Future<Output = Result<R, CacheError>> + Send + 'static>;
15impl Cache {
16 pub fn new(options: CacheOptions) -> Self {
17 Self {
18 client: WorkerClient::new(options),
19 }
20 }
21
22 pub async fn invalidate_by_tag(&self, tags: Vec<String>) -> Result<(), CacheError> {
23 self.client.invalidate_tags(&tags).await
24 }
25
26 pub fn cache<F, Fut, Args, R>(
27 &self,
28 func: F,
29 tags: Vec<String>,
30 options: Option<CacheOptions>,
31 ) -> impl Fn(Args) -> CacheFuture<R>
32 where
33 F: Fn(Args) -> Fut + Clone + Send + 'static,
34 Fut: Future<Output = R> + Send + 'static,
35 Args: Clone + Serialize + Send + 'static,
36 R: Serialize + DeserializeOwned + Send + Sync + 'static,
37 {
38 let client = self.client.clone();
39 let mut cache_options = options.unwrap_or_else(|| CacheOptions::default());
40 cache_options.tags = tags;
41
42 move |args: Args| {
43 let func = func.clone();
44 let args_clone = args.clone();
45 let client = client.clone();
46 let options = cache_options.clone();
47
48 Box::new(async move {
49 let mut hasher = DefaultHasher::new();
50 let args_serialized =
51 serde_json::to_string(&args_clone).map_err(CacheError::Serialization)?;
52 args_serialized.hash(&mut hasher);
53
54 let key = format!("{:x}", hasher.finish());
55 if let Some(cached_result) = client.get::<R>(&key).await? {
56 return Ok(cached_result);
57 }
58
59 let result = func(args).await;
60 let should_cache = options.should_cache.unwrap_or(true);
61 if should_cache {
62 client.set(&key, &result).await?;
63 }
64
65 Ok(result)
66 })
67 }
68 }
69}