| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- use std::time::Duration;
- use redis::AsyncCommands;
- use serde::{Deserialize, Serialize};
- use crate::cache::{HttpCacheKey, HttpCacheStorage};
- /// Redis cache storage for the HTTP cache.
- ///
- /// This cache storage backend uses Redis to store the cache.
- pub struct HttpCacheRedis {
- cache_ttl: Duration,
- prefix: Option<Vec<u8>>,
- client: redis::Client,
- }
- impl std::fmt::Debug for HttpCacheRedis {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("HttpCacheRedis")
- .field("cache_ttl", &self.cache_ttl)
- .field("prefix", &self.prefix)
- .finish_non_exhaustive()
- }
- }
- /// Configuration for the Redis cache storage.
- #[derive(Debug, Clone, Serialize, Deserialize, Default)]
- pub struct Config {
- /// Commong key prefix
- pub key_prefix: Option<String>,
- /// Connection string to the Redis server.
- pub connection_string: String,
- }
- impl HttpCacheRedis {
- /// Create a new Redis cache.
- pub fn new(client: redis::Client) -> Self {
- Self {
- client,
- prefix: None,
- cache_ttl: Duration::from_secs(60),
- }
- }
- /// Set a prefix for the cache keys.
- ///
- /// This is useful to have all the HTTP cache keys under a common prefix,
- /// some sort of namespace, to make management of the database easier.
- pub fn set_prefix(mut self, prefix: Vec<u8>) -> Self {
- self.prefix = Some(prefix);
- self
- }
- }
- #[async_trait::async_trait]
- impl HttpCacheStorage for HttpCacheRedis {
- fn set_expiration_times(&mut self, cache_ttl: Duration, _cache_tti: Duration) {
- self.cache_ttl = cache_ttl;
- }
- async fn get(&self, key: &HttpCacheKey) -> Option<Vec<u8>> {
- let mut conn = self
- .client
- .get_multiplexed_tokio_connection()
- .await
- .map_err(|err| {
- tracing::error!("Failed to get redis connection: {:?}", err);
- err
- })
- .ok()?;
- let mut db_key = self.prefix.clone().unwrap_or_default();
- db_key.extend(&**key);
- conn.get(db_key)
- .await
- .map_err(|err| {
- tracing::error!("Failed to get value from redis: {:?}", err);
- err
- })
- .ok()?
- }
- async fn set(&self, key: HttpCacheKey, value: Vec<u8>) {
- let mut db_key = self.prefix.clone().unwrap_or_default();
- db_key.extend(&*key);
- let mut conn = match self.client.get_multiplexed_tokio_connection().await {
- Ok(conn) => conn,
- Err(err) => {
- tracing::error!("Failed to get redis connection: {:?}", err);
- return;
- }
- };
- let _: Result<(), _> = conn
- .set_ex(db_key, value, self.cache_ttl.as_secs())
- .await
- .map_err(|err| {
- tracing::error!("Failed to set value in redis: {:?}", err);
- err
- });
- }
- }
|