Skip to main content

CacheStore

Trait CacheStore 

Source
pub trait CacheStore: Send + Sync {
Show 24 methods // Required methods fn get_json<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<Option<String>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn set_json<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, value: String, ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn delete<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn exists<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<bool>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn clear<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn ttl<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<Option<Duration>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn expire<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ttl: Duration, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn increment<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, delta: i64, ) -> Pin<Box<dyn Future<Output = CacheResult<i64>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn decrement<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, delta: i64, ) -> Pin<Box<dyn Future<Output = CacheResult<i64>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; // Provided methods fn set_json_forever<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, value: String, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn mget<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<Option<String>>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn mset<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, items: &'life1 [(&'life2 str, String)], ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn mdel<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn get_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<Option<String>>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn set_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, items: &'life1 [(&'life2 str, String)], ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn delete_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn exists_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<bool>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn ttl_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<Option<Duration>>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn supports_atomic_sets(&self) -> bool { ... } fn set_add<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, set_key: &'life1 str, member: &'life2 str, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn set_remove<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, set_key: &'life1 str, member: &'life2 str, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn set_add_many<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, set_key: &'life1 str, members: &'life2 [&'life3 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn set_remove_many<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, set_key: &'life1 str, members: &'life2 [&'life3 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn set_members<'life0, 'life1, 'async_trait>( &'life0 self, set_key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<String>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... }
}
Expand description

Cache store trait for different cache backends.

Required Methods§

Source

fn get_json<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<Option<String>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Get a JSON value from the cache.

§Arguments
  • key - The cache key
§Returns

Returns Ok(Some(value)) if the key exists, Ok(None) if not found, or an error if the operation fails.

Source

fn set_json<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, value: String, ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Set a JSON value in the cache.

§Arguments
  • key - The cache key
  • value - The JSON string value
  • ttl - Optional time-to-live duration
§None means “unspecified”, not “forever”

Backends configured with a CacheConfig::default_ttl treat ttl: None as “no TTL was specified for this write” and fall back to that default. To store an entry that genuinely never expires — bypassing default_ttl — use Self::set_json_forever.

Source

fn delete<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Delete a key from the cache.

§Arguments
  • key - The cache key to delete
Source

fn exists<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Check if a key exists in the cache.

§Arguments
  • key - The cache key to check
Source

fn clear<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Clear all keys from the cache.

Warning: This operation may be destructive and affect all keys.

Source

fn ttl<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<Option<Duration>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Get the TTL (time-to-live) of a key.

§Arguments
  • key - The cache key
§Returns

Returns Ok(Some(duration)) if the key has a TTL, Ok(None) if the key has no expiration or doesn’t exist.

Source

fn expire<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, ttl: Duration, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Set or update the expiration time for a key.

§Arguments
  • key - The cache key
  • ttl - The new time-to-live duration
Source

fn increment<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, delta: i64, ) -> Pin<Box<dyn Future<Output = CacheResult<i64>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Increment a numeric value.

§Arguments
  • key - The cache key
  • delta - The amount to increment by
§Returns

Returns the new value after incrementing.

Source

fn decrement<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, delta: i64, ) -> Pin<Box<dyn Future<Output = CacheResult<i64>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Decrement a numeric value.

§Arguments
  • key - The cache key
  • delta - The amount to decrement by
§Returns

Returns the new value after decrementing.

Provided Methods§

Source

fn set_json_forever<'life0, 'life1, 'async_trait>( &'life0 self, key: &'life1 str, value: String, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Set a JSON value that never expires, explicitly bypassing any configured CacheConfig::default_ttl.

This exists because Self::set_json cannot express the difference between “the caller did not specify a TTL” and “the caller wants no expiry at all” — both are None, and backends resolve None against default_ttl. On a store built with .with_default_ttl(..) that made a non-expiring entry unobtainable, so “remember forever” silently became “remember for the default TTL”. Callers that mean forever must come through here.

The default implementation forwards to set_json(key, value, None), which is already correct for any backend that has no default_ttl concept (e.g. crate::tiered::InMemoryCache). Backends that resolve None against a configured default must override this.

§Arguments
  • key - The cache key
  • value - The JSON string value
Source

fn mget<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<Option<String>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Get multiple keys in a single batch operation.

Returns a vector of Option<String> in the same order as keys; None indicates a missing key.

The default implementation issues one get_json per key concurrently; backends should override this with a native multi-get (e.g. MGET).

Source

fn mset<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, items: &'life1 [(&'life2 str, String)], ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Set multiple key/value pairs in a single batch operation.

The default implementation issues one set_json per pair concurrently; backends should override this with a native multi-set (e.g. MSET, or a pipeline of SET ... EX when a TTL is required).

Source

fn mdel<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Delete multiple keys in a single batch operation.

The default implementation issues one delete per key concurrently; backends should override this with a variadic DEL/UNLINK.

Source

fn get_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<Option<String>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Get multiple keys in parallel.

This operation fetches multiple cache keys concurrently, significantly reducing total latency compared to sequential gets.

§Arguments
  • keys - Slice of cache keys to fetch
§Returns

Returns a vector of Option<String> in the same order as the input keys. None indicates the key was not found.

§Performance
  • Sequential: O(n * network_latency)
  • Parallel: O(max(network_latencies)) ≈ O(network_latency)
  • Speedup: 10-100x for network-bound operations
§Examples
// Fetch 100 user profiles in parallel
let keys: Vec<String> = (1..=100).map(|i| format!("user:{}", i)).collect();
let key_refs: Vec<&str> = keys.iter().map(|s| s.as_str()).collect();
let profiles = cache.get_many(&key_refs).await?;

// Sequential: ~1000ms (10ms * 100)
// Parallel:   ~15ms (max of all parallel requests)
Source

fn set_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, items: &'life1 [(&'life2 str, String)], ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Set multiple key-value pairs in parallel.

§Arguments
  • items - Slice of (key, value) tuples
  • ttl - Optional time-to-live for all keys
§Performance

10-100x faster than sequential sets for network-bound operations.

§Examples
use std::time::Duration;

let items = vec![
    ("user:1", r#"{"name":"Alice"}"#.to_string()),
    ("user:2", r#"{"name":"Bob"}"#.to_string()),
];

cache.set_many(&items, Some(Duration::from_secs(3600))).await?;
Source

fn delete_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Delete multiple keys in parallel.

§Arguments
  • keys - Slice of cache keys to delete
§Performance

10-100x faster than sequential deletes.

§Examples
// Bulk cache invalidation
let keys = vec!["session:1", "session:2", "session:3"];
cache.delete_many(&keys).await?;
Source

fn exists_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<bool>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Check existence of multiple keys in parallel.

§Arguments
  • keys - Slice of cache keys to check
§Returns

Returns a vector of booleans in the same order as input keys.

§Examples
let keys = vec!["user:1", "user:2", "user:3"];
let exists = cache.exists_many(&keys).await?;

for (key, exists) in keys.iter().zip(exists.iter()) {
    println!("{}: {}", key, exists);
}
Source

fn ttl_many<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, keys: &'life1 [&'life2 str], ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<Option<Duration>>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Get TTL for multiple keys in parallel.

§Arguments
  • keys - Slice of cache keys
§Returns

Returns a vector of Option<Duration> for each key.

§Examples
let keys = vec!["session:1", "session:2"];
let ttls = cache.ttl_many(&keys).await?;

for (key, ttl) in keys.iter().zip(ttls.iter()) {
    match ttl {
        Some(duration) => println!("{}: expires in {:?}", key, duration),
        None => println!("{}: no expiration", key),
    }
}
Source

fn supports_atomic_sets(&self) -> bool

Whether this backend’s Self::set_add/Self::set_remove/ Self::set_members are backed by a native, atomic set type rather than the trait’s default non-atomic read-modify-write.

RedisCache overrides this to return true (its implementations use SADD/SREM/SMEMBERS). Every other backend — including InMemoryCache and MemcachedCache — keeps this default false, since they inherit the default set primitives above.

crate::invalidation::TaggedCache::new checks this capability and logs a warning once, at construction time, when the backing store answers false — giving operators a runtime signal (not just a doc comment) that concurrent tag-index updates against that deployment can race and silently lose an update.

Source

fn set_add<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, set_key: &'life1 str, member: &'life2 str, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Add member to the persistent string set stored at set_key.

A no-op if member is already present.

§Examples
// Build a persisted set of member keys under "tag:users".
cache.set_add("tag:users", "user:1").await?;
cache.set_add("tag:users", "user:2").await?;
cache.set_add("tag:users", "user:1").await?; // duplicate: no-op

let members = cache.set_members("tag:users").await?;
assert_eq!(members.len(), 2);
Source

fn set_remove<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, set_key: &'life1 str, member: &'life2 str, ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Remove member from the persistent string set stored at set_key.

A no-op if set_key or member doesn’t exist. Deletes set_key entirely once its last member is removed, so an emptied set doesn’t linger as a zero-length entry.

§Examples
cache.set_add("tag:users", "user:1").await?;
cache.set_remove("tag:users", "user:1").await?;

// The set is now empty; `set_key` itself is removed rather than left
// behind as a zero-length entry.
assert!(cache.set_members("tag:users").await?.is_empty());
Source

fn set_add_many<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, set_key: &'life1 str, members: &'life2 [&'life3 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Add every member of members to the set stored at set_key.

Backends with a native set type should override this with a single variadic command (SADD key m1 m2 ...), turning N round-trips into one; RedisCache does.

The default implementation applies Self::set_add sequentially, not concurrently: the default set_add is a read-modify-write against the same set_key, so issuing those concurrently would race with itself and drop members.

Source

fn set_remove_many<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, set_key: &'life1 str, members: &'life2 [&'life3 str], ) -> Pin<Box<dyn Future<Output = CacheResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Remove every member of members from the set stored at set_key.

The variadic counterpart to Self::set_remove; see Self::set_add_many for why the default implementation is sequential.

Source

fn set_members<'life0, 'life1, 'async_trait>( &'life0 self, set_key: &'life1 str, ) -> Pin<Box<dyn Future<Output = CacheResult<Vec<String>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Read every member of the persistent string set stored at set_key.

Returns an empty Vec if set_key doesn’t exist.

§Examples
cache.set_add("tag:users", "user:1").await?;
cache.set_add("tag:users", "user:2").await?;

let mut members = cache.set_members("tag:users").await?;
members.sort();
assert_eq!(members, vec!["user:1".to_string(), "user:2".to_string()]);

// A set_key that was never written returns an empty Vec.
assert!(cache.set_members("tag:unused").await?.is_empty());

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§