pub struct ParallelCacheOps;Expand description
Parallel batch operations for cache stores.
This module provides high-performance batch operations that execute multiple cache operations concurrently, significantly reducing total latency.
§Performance
- get_many: 10-100x faster than sequential gets (depending on network latency)
- set_many: 10-100x faster than sequential sets
- delete_many: Similar performance gains
§Examples
use armature_cache::*;
use armature_cache::parallel::*;
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
// Get multiple keys in parallel
let keys = vec!["user:1", "user:2", "user:3"];
let values = get_many_json(&cache, &keys).await?;
// Set multiple keys in parallel
let items = vec![
("key1", "value1".to_string()),
("key2", "value2".to_string()),
];
set_many_json(&cache, &items, None).await?;Implementations§
Source§impl ParallelCacheOps
impl ParallelCacheOps
Sourcepub async fn get_many_json<S: CacheStore>(
store: &S,
keys: &[&str],
) -> CacheResult<Vec<Option<String>>>
pub async fn get_many_json<S: CacheStore>( store: &S, keys: &[&str], ) -> CacheResult<Vec<Option<String>>>
Get multiple JSON values in parallel.
§Arguments
store- The cache storekeys- Slice of keys to fetch
§Returns
A vector of optional values in the same order as keys.
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let keys = vec!["key1", "key2", "key3"];
let values = ParallelCacheOps::get_many_json(&cache, &keys).await?;
for (key, value) in keys.iter().zip(values.iter()) {
println!("{}: {:?}", key, value);
}Sourcepub async fn get_many<S: CacheStore, T: DeserializeOwned>(
store: &S,
keys: &[&str],
) -> CacheResult<Vec<Option<T>>>
pub async fn get_many<S: CacheStore, T: DeserializeOwned>( store: &S, keys: &[&str], ) -> CacheResult<Vec<Option<T>>>
Get multiple typed values in parallel.
§Type Parameters
T- The type to deserialize into
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct User {
id: u64,
name: String,
}
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let keys = vec!["user:1", "user:2", "user:3"];
let users: Vec<Option<User>> = ParallelCacheOps::get_many(&cache, &keys).await?;Sourcepub async fn set_many_json<S: CacheStore>(
store: &S,
items: &[(&str, String)],
ttl: Option<Duration>,
) -> CacheResult<()>
pub async fn set_many_json<S: CacheStore>( store: &S, items: &[(&str, String)], ttl: Option<Duration>, ) -> CacheResult<()>
Set multiple JSON values in parallel.
§Arguments
store- The cache storeitems- Slice of (key, value) tuplesttl- Optional time-to-live for all items
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
use std::time::Duration;
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let items = vec![
("key1", r#"{"value": 1}"#.to_string()),
("key2", r#"{"value": 2}"#.to_string()),
];
ParallelCacheOps::set_many_json(&cache, &items, Some(Duration::from_secs(3600))).await?;Sourcepub async fn set_many<S: CacheStore, T: Serialize>(
store: &S,
items: &[(&str, T)],
ttl: Option<Duration>,
) -> CacheResult<()>
pub async fn set_many<S: CacheStore, T: Serialize>( store: &S, items: &[(&str, T)], ttl: Option<Duration>, ) -> CacheResult<()>
Set multiple typed values in parallel.
§Type Parameters
T- The type to serialize from
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct Counter {
count: u64,
}
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let items = vec![
("counter:1", Counter { count: 10 }),
("counter:2", Counter { count: 20 }),
];
ParallelCacheOps::set_many(&cache, &items, None).await?;Sourcepub async fn delete_many<S: CacheStore>(
store: &S,
keys: &[&str],
) -> CacheResult<()>
pub async fn delete_many<S: CacheStore>( store: &S, keys: &[&str], ) -> CacheResult<()>
Delete multiple keys in parallel.
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let keys = vec!["key1", "key2", "key3"];
ParallelCacheOps::delete_many(&cache, &keys).await?;Sourcepub async fn exists_many<S: CacheStore>(
store: &S,
keys: &[&str],
) -> CacheResult<Vec<bool>>
pub async fn exists_many<S: CacheStore>( store: &S, keys: &[&str], ) -> CacheResult<Vec<bool>>
Check if multiple keys exist in parallel.
§Returns
A vector of booleans indicating existence, in the same order as keys.
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let keys = vec!["key1", "key2", "key3"];
let exists = ParallelCacheOps::exists_many(&cache, &keys).await?;
for (key, exists) in keys.iter().zip(exists.iter()) {
println!("{}: {}", key, exists);
}Sourcepub async fn ttl_many<S: CacheStore>(
store: &S,
keys: &[&str],
) -> CacheResult<Vec<Option<Duration>>>
pub async fn ttl_many<S: CacheStore>( store: &S, keys: &[&str], ) -> CacheResult<Vec<Option<Duration>>>
Get TTL for multiple keys in parallel.
§Returns
A vector of optional durations, in the same order as keys.
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let keys = vec!["key1", "key2", "key3"];
let ttls = ParallelCacheOps::ttl_many(&cache, &keys).await?;
for (key, ttl) in keys.iter().zip(ttls.iter()) {
println!("{}: {:?}", key, ttl);
}Sourcepub async fn warm_cache<S, T, F, Fut>(
store: &S,
keys: &[&str],
ttl: Option<Duration>,
factory: F,
) -> CacheResult<()>
pub async fn warm_cache<S, T, F, Fut>( store: &S, keys: &[&str], ttl: Option<Duration>, factory: F, ) -> CacheResult<()>
Cache warming: preload multiple keys into cache.
§Concurrency
At most DEFAULT_WARM_CONCURRENCY factories run at a time. The
factory is the caller’s loader (usually a DB fetch), so warming a large
key set without a bound would fire one query per key simultaneously.
Use Self::warm_cache_with_concurrency to choose the limit.
§Type Parameters
T- The type to serializeF- Factory function that returns data for a given key
§Examples
use armature_cache::*;
use armature_cache::parallel::ParallelCacheOps;
use std::time::Duration;
let cache = RedisCache::new(CacheConfig::redis("redis://localhost:6379")?).await?;
let keys = vec!["user:1", "user:2", "user:3"];
ParallelCacheOps::warm_cache(
&cache,
&keys,
Some(Duration::from_secs(3600)),
|key: &str| async move {
// Fetch from database
let data = format!("Data for {}", key);
Ok::<String, CacheError>(data)
},
).await?;Sourcepub async fn warm_cache_with_concurrency<S, T, F, Fut>(
store: &S,
keys: &[&str],
ttl: Option<Duration>,
max_concurrent: usize,
factory: F,
) -> CacheResult<()>
pub async fn warm_cache_with_concurrency<S, T, F, Fut>( store: &S, keys: &[&str], ttl: Option<Duration>, max_concurrent: usize, factory: F, ) -> CacheResult<()>
Cache warming with an explicit cap on concurrent factory invocations.
max_concurrent is the number of factories (and their follow-up
writes) allowed to be in flight at once; 0 is treated as 1. See
DEFAULT_WARM_CONCURRENCY for why the fan-out is bounded at all.
The first error aborts the warm-up: keys already written stay written, and the remaining ones are not attempted.