diff --git a/Cargo.toml b/Cargo.toml index e369a23..d1ff208 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,19 @@ async = ["futures", "tokio", "async-trait"] async_tokio_rt_multi_thread = ["async", "tokio/rt-multi-thread"] redis_store = ["redis", "r2d2", "serde", "serde_json"] redis_connection_manager = ["redis_store", "redis/connection-manager"] -redis_async_std = ["redis_store", "async", "redis/aio", "redis/async-std-comp", "redis/tls", "redis/async-std-tls-comp"] -redis_tokio = ["redis_store", "async", "redis/aio", "redis/tokio-comp", "redis/tls", "redis/tokio-native-tls-comp"] +redis_smol = [ + "redis_store", + "async", + "redis/smol-native-tls-comp", +] +redis_tokio = [ + "redis_store", + "async", + "redis/tokio-native-tls-comp", +] +redis_async_cache = [ + "redis/cache-aio", +] redis_ahash = ["redis_store", "redis/ahash"] disk_store = ["sled", "serde", "rmp-serde", "directories"] wasm = [] @@ -65,7 +76,7 @@ version = "0.1" optional = true [dependencies.redis] -version = "0.32" +version = "1.0" features = ["r2d2"] optional = true diff --git a/README.md b/README.md index a1b881a..f8609c6 100644 --- a/README.md +++ b/README.md @@ -28,14 +28,14 @@ of un-cached arguments, specify `#[cached(sync_writes = "default")]` / `#[once(s - `async`: Include support for async functions and async cache stores - `async_tokio_rt_multi_thread`: Enable `tokio`'s optional `rt-multi-thread` feature. - `redis_store`: Include Redis cache store -- `redis_async_std`: Include async Redis support using `async-std` and `async-std` tls support, implies `redis_store` and `async` +- `redis_smol`: Include async Redis support using `smol` and `smol` tls support, implies `redis_store` and `async` - `redis_tokio`: Include async Redis support using `tokio` and `tokio` tls support, implies `redis_store` and `async` - `redis_connection_manager`: Enable the optional `connection-manager` feature of `redis`. Any async redis caches created will use a connection manager instead of a `MultiplexedConnection` - `redis_ahash`: Enable the optional `ahash` feature of `redis` - `disk_store`: Include disk cache store - `wasm`: Enable WASM support. Note that this feature is incompatible with `tokio`'s multi-thread - runtime (`async_tokio_rt_multi_thread`) and all Redis features (`redis_store`, `redis_async_std`, `redis_tokio`, `redis_ahash`) + runtime (`async_tokio_rt_multi_thread`) and all Redis features (`redis_store`, `redis_smol`, `redis_tokio`, `redis_ahash`) The procedural macros (`#[cached]`, `#[once]`, `#[io_cached]`) offer more features, including async support. See the [`proc_macro`](crate::proc_macro) and [`macros`](crate::macros) modules for more samples, and the diff --git a/src/lib.rs b/src/lib.rs index a11f0e8..adcb050 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,14 +27,14 @@ of un-cached arguments, specify `#[cached(sync_writes = "default")]` / `#[once(s - `async`: Include support for async functions and async cache stores - `async_tokio_rt_multi_thread`: Enable `tokio`'s optional `rt-multi-thread` feature. - `redis_store`: Include Redis cache store -- `redis_async_std`: Include async Redis support using `async-std` and `async-std` tls support, implies `redis_store` and `async` +- `redis_smol`: Include async Redis support using `smol` and `smol` tls support, implies `redis_store` and `async` - `redis_tokio`: Include async Redis support using `tokio` and `tokio` tls support, implies `redis_store` and `async` - `redis_connection_manager`: Enable the optional `connection-manager` feature of `redis`. Any async redis caches created will use a connection manager instead of a `MultiplexedConnection` - `redis_ahash`: Enable the optional `ahash` feature of `redis` - `disk_store`: Include disk cache store - `wasm`: Enable WASM support. Note that this feature is incompatible with `tokio`'s multi-thread - runtime (`async_tokio_rt_multi_thread`) and all Redis features (`redis_store`, `redis_async_std`, `redis_tokio`, `redis_ahash`) + runtime (`async_tokio_rt_multi_thread`) and all Redis features (`redis_store`, `redis_smol`, `redis_tokio`, `redis_ahash`) The procedural macros (`#[cached]`, `#[once]`, `#[io_cached]`) offer more features, including async support. See the [`proc_macro`](crate::proc_macro) and [`macros`](crate::macros) modules for more samples, and the @@ -226,11 +226,8 @@ use std::time::Duration; #[cfg(feature = "proc_macro")] #[cfg_attr(docsrs, doc(cfg(feature = "proc_macro")))] pub use proc_macro::Return; -#[cfg(any(feature = "redis_async_std", feature = "redis_tokio"))] -#[cfg_attr( - docsrs, - doc(cfg(any(feature = "redis_async_std", feature = "redis_tokio"))) -)] +#[cfg(any(feature = "redis_smol", feature = "redis_tokio"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "redis_smol", feature = "redis_tokio"))))] pub use stores::AsyncRedisCache; pub use stores::{ CanExpire, ExpiringValueCache, SizedCache, TimedCache, TimedSizedCache, UnboundCache, diff --git a/src/stores/mod.rs b/src/stores/mod.rs index d0f7f3a..43fdc88 100644 --- a/src/stores/mod.rs +++ b/src/stores/mod.rs @@ -35,14 +35,14 @@ pub use unbound::UnboundCache; #[cfg(all( feature = "async", feature = "redis_store", - any(feature = "redis_async_std", feature = "redis_tokio") + any(feature = "redis_smol", feature = "redis_tokio") ))] #[cfg_attr( docsrs, doc(cfg(all( feature = "async", feature = "redis_store", - any(feature = "redis_async_std", feature = "redis_tokio") + any(feature = "redis_smol", feature = "redis_tokio") ))) )] pub use crate::stores::redis::{AsyncRedisCache, AsyncRedisCacheBuilder}; diff --git a/src/stores/redis.rs b/src/stores/redis.rs index ce57658..2a75a07 100644 --- a/src/stores/redis.rs +++ b/src/stores/redis.rs @@ -360,7 +360,7 @@ where #[cfg(all( feature = "async", - any(feature = "redis_async_std", feature = "redis_tokio") + any(feature = "redis_smol", feature = "redis_tokio") ))] mod async_redis { use std::time::Duration; @@ -369,6 +369,8 @@ mod async_redis { CachedRedisValue, DeserializeOwned, Display, PhantomData, RedisCacheBuildError, RedisCacheError, Serialize, DEFAULT_NAMESPACE, ENV_KEY, }; + #[cfg(feature = "redis_async_cache")] + use redis::IntoConnectionInfo; use {crate::IOCachedAsync, async_trait::async_trait}; pub struct AsyncRedisCacheBuilder { @@ -377,6 +379,8 @@ mod async_redis { namespace: String, prefix: String, connection_string: Option, + #[cfg(feature = "redis_async_cache")] + client_side_caching: bool, _phantom: PhantomData<(K, V)>, } @@ -393,6 +397,8 @@ mod async_redis { namespace: DEFAULT_NAMESPACE.to_string(), prefix: prefix.as_ref().to_string(), connection_string: None, + #[cfg(feature = "redis_async_cache")] + client_side_caching: false, _phantom: PhantomData, } } @@ -438,6 +444,14 @@ mod async_redis { self } + /// Enable client-side caching using RESP3 protocol + #[cfg(feature = "redis_async_cache")] + #[must_use] + pub fn set_client_side_caching(mut self, enable: bool) -> Self { + self.client_side_caching = enable; + self + } + /// Return the current connection string or load from the env var: `CACHED_REDIS_CONNECTION_STRING` /// /// # Errors @@ -462,6 +476,25 @@ mod async_redis { &self, ) -> Result { let s = self.connection_string()?; + + #[cfg(feature = "redis_async_cache")] + if self.client_side_caching { + let mut connection_info = s.into_connection_info()?; + + let mut config = redis::AsyncConnectionConfig::default(); + let redis_settings = connection_info + .redis_settings() + .clone() + .set_protocol(redis::ProtocolVersion::RESP3); + connection_info = connection_info.set_redis_settings(redis_settings); + config = config.set_cache_config(redis::caching::CacheConfig::default()); + let client = redis::Client::open(connection_info)?; + let conn = client + .get_multiplexed_async_connection_with_config(&config) + .await?; + return Ok(conn); + } + let client = redis::Client::open(s)?; let conn = client.get_multiplexed_async_connection().await?; Ok(conn) @@ -475,6 +508,24 @@ mod async_redis { &self, ) -> Result { let s = self.connection_string()?; + #[cfg(feature = "redis_async_cache")] + if self.client_side_caching { + let mut connection_info = s.into_connection_info()?; + + let mut config = redis::aio::ConnectionManagerConfig::default(); + if self.client_side_caching { + let redis_settings = connection_info + .redis_settings() + .clone() + .set_protocol(redis::ProtocolVersion::RESP3); + connection_info = connection_info.set_redis_settings(redis_settings); + config = config.set_cache_config(redis::caching::CacheConfig::new()); + } + let client = redis::Client::open(connection_info)?; + let conn = redis::aio::ConnectionManager::new_with_config(client, config).await?; + return Ok(conn); + } + let client = redis::Client::open(s)?; let conn = redis::aio::ConnectionManager::new(client).await?; Ok(conn) @@ -698,13 +749,13 @@ mod async_redis { #[cfg(all( feature = "async", - any(feature = "redis_async_std", feature = "redis_tokio") + any(feature = "redis_smol", feature = "redis_tokio") ))] #[cfg_attr( docsrs, doc(cfg(all( feature = "async", - any(feature = "redis_async_std", feature = "redis_tokio") + any(feature = "redis_smol", feature = "redis_tokio") ))) )] pub use async_redis::{AsyncRedisCache, AsyncRedisCacheBuilder}; diff --git a/tests/cached.rs b/tests/cached.rs index 4509c52..3fd0fae 100644 --- a/tests/cached.rs +++ b/tests/cached.rs @@ -1486,7 +1486,7 @@ mod redis_tests { assert_eq!(cached_redis_cache_create(6), Err(TestError::Count(6))); } - #[cfg(any(feature = "redis_async_std", feature = "redis_tokio"))] + #[cfg(any(feature = "redis_smol", feature = "redis_tokio"))] mod async_redis_tests { use super::*;