Skip to main content

gestalt/
cache_provider.rs

1use std::collections::{BTreeMap, BTreeSet};
2use std::time::Duration;
3
4use tonic::codegen::async_trait;
5
6use crate::api::RuntimeMetadata;
7use crate::error::Result;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10/// One cache entry written through [`CacheProvider::set_many`].
11pub struct CacheEntry {
12    /// Cache key to store.
13    pub key: String,
14    /// Cache value bytes.
15    pub value: Vec<u8>,
16}
17
18#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
19/// Options applied to cache writes.
20pub struct CacheSetOptions {
21    /// Optional time-to-live for the stored value.
22    pub ttl: Option<Duration>,
23}
24
25#[async_trait]
26/// Lifecycle and RPC contract for cache providers.
27pub trait CacheProvider: Send + Sync + 'static {
28    /// Configures the provider before it starts serving requests.
29    async fn configure(
30        &self,
31        _name: &str,
32        _config: serde_json::Map<String, serde_json::Value>,
33    ) -> Result<()> {
34        Ok(())
35    }
36
37    /// Returns runtime metadata that should augment the static manifest.
38    fn metadata(&self) -> Option<RuntimeMetadata> {
39        None
40    }
41
42    /// Returns non-fatal warnings the host should surface to users.
43    fn warnings(&self) -> Vec<String> {
44        Vec::new()
45    }
46
47    /// Performs an optional health check.
48    async fn health_check(&self) -> Result<()> {
49        Ok(())
50    }
51
52    /// Starts provider-owned background work after configuration.
53    async fn start(&self) -> Result<()> {
54        Ok(())
55    }
56
57    /// Shuts the provider down before the runtime exits.
58    async fn close(&self) -> Result<()> {
59        Ok(())
60    }
61
62    /// Loads one cache value.
63    async fn get(&self, key: &str) -> Result<Option<Vec<u8>>>;
64
65    /// Loads many cache values, defaulting to repeated [`CacheProvider::get`]
66    /// calls.
67    async fn get_many(&self, keys: &[String]) -> Result<BTreeMap<String, Vec<u8>>> {
68        let mut values = BTreeMap::new();
69        for key in keys {
70            if let Some(value) = self.get(key).await? {
71                values.insert(key.clone(), value);
72            }
73        }
74        Ok(values)
75    }
76
77    /// Stores one cache value.
78    async fn set(&self, key: &str, value: &[u8], options: CacheSetOptions) -> Result<()>;
79
80    /// Stores many cache values, defaulting to repeated [`CacheProvider::set`]
81    /// calls.
82    async fn set_many(&self, entries: &[CacheEntry], options: CacheSetOptions) -> Result<()> {
83        for entry in entries {
84            self.set(&entry.key, &entry.value, options).await?;
85        }
86        Ok(())
87    }
88
89    /// Deletes one cache key.
90    async fn delete(&self, key: &str) -> Result<bool>;
91
92    /// Deletes many cache keys, defaulting to repeated
93    /// [`CacheProvider::delete`] calls.
94    async fn delete_many(&self, keys: &[String]) -> Result<i64> {
95        let mut deleted = 0_i64;
96        let mut seen = BTreeSet::new();
97        for key in keys {
98            if !seen.insert(key.as_str()) {
99                continue;
100            }
101            if self.delete(key).await? {
102                deleted += 1;
103            }
104        }
105        Ok(deleted)
106    }
107
108    /// Updates the TTL for one cache key.
109    async fn touch(&self, key: &str, ttl: Duration) -> Result<bool>;
110}