kora_lib/
cache.rs

1use super::KoraError;
2use deadpool_redis::{Config, Pool, Runtime};
3use redis::AsyncCommands;
4use solana_sdk::pubkey::Pubkey;
5use std::str::FromStr;
6
7const TOKEN_ACCOUNT_CACHE_TTL: u64 = 3600 * 24; // 1 day in seconds
8
9#[derive(Clone)]
10pub struct TokenAccountCache {
11    pool: Pool,
12}
13
14impl TokenAccountCache {
15    pub fn new(redis_url: &str) -> Result<Self, KoraError> {
16        let cfg = Config::from_url(redis_url);
17        let pool = cfg.create_pool(Some(Runtime::Tokio1)).map_err(|e| {
18            KoraError::InternalServerError(format!("Failed to create Redis pool: {}", e))
19        })?;
20
21        Ok(Self { pool })
22    }
23
24    pub async fn get_token_account(
25        &self,
26        user: &Pubkey,
27        mint: &Pubkey,
28    ) -> Result<Option<Pubkey>, KoraError> {
29        let key = format!("token_account:{}:{}", user, mint);
30        let mut conn = self.pool.get().await.map_err(|e| {
31            KoraError::InternalServerError(format!("Failed to get Redis connection: {}", e))
32        })?;
33
34        let result: Option<String> = conn.get(&key).await.map_err(|e| {
35            KoraError::InternalServerError(format!("Failed to get from Redis: {}", e))
36        })?;
37
38        match result {
39            Some(pubkey_str) => {
40                let pubkey = Pubkey::from_str(&pubkey_str).map_err(|e| {
41                    KoraError::InternalServerError(format!("Invalid pubkey in cache: {}", e))
42                })?;
43                Ok(Some(pubkey))
44            }
45            None => Ok(None),
46        }
47    }
48
49    pub async fn set_token_account(
50        &self,
51        user: &Pubkey,
52        mint: &Pubkey,
53        token_account: &Pubkey,
54    ) -> Result<(), KoraError> {
55        let key = format!("token_account:{}:{}", user, mint);
56        let mut conn = self.pool.get().await.map_err(|e| {
57            KoraError::InternalServerError(format!("Failed to get Redis connection: {}", e))
58        })?;
59
60        conn.set_ex::<_, _, ()>(&key, token_account.to_string(), TOKEN_ACCOUNT_CACHE_TTL)
61            .await
62            .map_err(|e| {
63                KoraError::InternalServerError(format!("Failed to set in Redis: {}", e))
64            })?;
65
66        Ok(())
67    }
68
69    pub async fn _invalidate_token_account(
70        &self,
71        user: &Pubkey,
72        mint: &Pubkey,
73    ) -> Result<(), KoraError> {
74        let key = format!("token_account:{}:{}", user, mint);
75        let mut conn = self.pool.get().await.map_err(|e| {
76            KoraError::InternalServerError(format!("Failed to get Redis connection: {}", e))
77        })?;
78
79        conn.del::<_, ()>(&key).await.map_err(|e| {
80            KoraError::InternalServerError(format!("Failed to delete from Redis: {}", e))
81        })?;
82
83        Ok(())
84    }
85}