1use async_trait::async_trait;
6use futures_util::stream::StreamExt;
7use hodei_authz::{CacheError, CacheInvalidation};
8use redis::Client;
9
10pub struct RedisCacheInvalidation {
12 client: Client,
13}
14
15impl RedisCacheInvalidation {
16 pub async fn new(redis_url: &str) -> Result<Self, redis::RedisError> {
18 let client = Client::open(redis_url)?;
19
20 let mut conn = client.get_multiplexed_async_connection().await?;
22 redis::cmd("PING")
23 .query_async::<()>(&mut conn)
24 .await?;
25
26 Ok(Self { client })
27 }
28}
29
30#[async_trait]
31impl CacheInvalidation for RedisCacheInvalidation {
32 async fn invalidate_policies(&self) -> Result<(), CacheError> {
33 let mut conn = self
34 .client
35 .get_multiplexed_async_connection()
36 .await
37 .map_err(|e| CacheError::Connection(e.to_string()))?;
38
39 redis::cmd("PUBLISH")
40 .arg("hodei:policy:invalidate")
41 .arg("reload")
42 .query_async::<()>(&mut conn)
43 .await
44 .map_err(|e| CacheError::Publish(e.to_string()))?;
45
46 Ok(())
47 }
48
49 async fn subscribe_to_invalidations<F>(&self, callback: F) -> Result<(), CacheError>
50 where
51 F: Fn() + Send + Sync + 'static,
52 {
53 tracing::warn!("Redis PubSub subscription is not fully implemented in this version");
57 tracing::info!("Cache invalidation will work via explicit invalidate_policies() calls");
58
59 Ok(())
66 }
67}