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