redis.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. use super::{HttpCacheKey, HttpCacheStorage};
  2. use redis::AsyncCommands;
  3. use std::time::Duration;
  4. /// Redis cache storage for the HTTP cache.
  5. ///
  6. /// This cache storage backend uses Redis to store the cache.
  7. pub struct HttpCacheRedis {
  8. cache_ttl: Duration,
  9. prefix: Option<Vec<u8>>,
  10. client: Option<redis::Client>,
  11. }
  12. impl HttpCacheRedis {
  13. /// Create a new Redis cache.
  14. pub fn set_client(mut self, client: redis::Client) -> Self {
  15. self.client = Some(client);
  16. self
  17. }
  18. /// Set a prefix for the cache keys.
  19. ///
  20. /// This is useful to have all the HTTP cache keys under a common prefix,
  21. /// some sort of namespace, to make managment of the database easier.
  22. pub fn set_prefix(mut self, prefix: Vec<u8>) -> Self {
  23. self.prefix = Some(prefix);
  24. self
  25. }
  26. }
  27. #[async_trait::async_trait]
  28. impl HttpCacheStorage for HttpCacheRedis {
  29. fn new(cache_ttl: Duration, _cache_tti: Duration) -> Self {
  30. Self {
  31. cache_ttl,
  32. prefix: None,
  33. client: None,
  34. }
  35. }
  36. async fn get(&self, key: &HttpCacheKey) -> Option<Vec<u8>> {
  37. let mut con = match self
  38. .client
  39. .as_ref()
  40. .expect("A client must be set with set_client()")
  41. .get_multiplexed_tokio_connection()
  42. .await
  43. {
  44. Ok(con) => con,
  45. Err(err) => {
  46. tracing::error!("Failed to get redis connection: {:?}", err);
  47. return None;
  48. }
  49. };
  50. let mut db_key = self.prefix.clone().unwrap_or_default();
  51. db_key.extend(&**key);
  52. con.get(db_key)
  53. .await
  54. .map_err(|err| {
  55. tracing::error!("Failed to get value from redis: {:?}", err);
  56. err
  57. })
  58. .ok()
  59. }
  60. async fn set(&self, key: HttpCacheKey, value: Vec<u8>) {
  61. let mut db_key = self.prefix.clone().unwrap_or_default();
  62. db_key.extend(&*key);
  63. let mut con = match self
  64. .client
  65. .as_ref()
  66. .expect("A client must be set with set_client()")
  67. .get_multiplexed_tokio_connection()
  68. .await
  69. {
  70. Ok(con) => con,
  71. Err(err) => {
  72. tracing::error!("Failed to get redis connection: {:?}", err);
  73. return;
  74. }
  75. };
  76. let _: Result<(), _> = con
  77. .set_ex(db_key, value, self.cache_ttl.as_secs() as usize)
  78. .await;
  79. }
  80. }