cal_redis/cache/
account.rs

1// File: cal-redis/src/cache/account.rs
2
3use crate::cache::CallableCache;
4use crate::local_cache::build_account_identifiers_locally;
5use crate::{get_account_by_id, get_account_by_ident, get_accounts, get_trunk_and_ddi};
6use cal_core::AccountLite;
7use redis::RedisError;
8use std::sync::Arc;
9
10impl CallableCache {
11    /// Retrieves an account by trunk IP and DDI, first checking the local cache and then Redis.
12    ///
13    /// This function:
14    /// 1. Checks if the trunk-DDI combination exists in the local cache
15    /// 2. If found, retrieves the account ID and uses it to look up the account
16    /// 3. If not found in local cache, falls back to Redis lookup
17    /// 4. Caches the result for future use
18    ///
19    /// # Arguments
20    /// * `ddi_id` - DDI identifier (typically a phone number)
21    /// * `trunk_ip` - IP address of the trunk
22    ///
23    /// # Returns
24    /// * `Result<Option<AccountLite>, RedisError>` - Account if found, None if not found, or a Redis error
25    pub async fn get_account_by_trunk_ddi(
26        self,
27        ddi_id: &str,
28        trunk_ip: &str,
29    ) -> Result<Option<Arc<AccountLite>>, RedisError> {
30        println!("[CallableCache::get_account_by_trunk_ddi] Looking up account for DDI: {}, Trunk IP: {}", ddi_id, trunk_ip);
31        // Create a composite key for the trunk-DDI combination
32        let trunk_ddi_key = format!("{}:{}", trunk_ip, ddi_id);
33
34        // Try to get the account ID from the local trunk-DDI cache
35        if let Some(account_id) = self.local_cache.trunk_ddi_idents.get(&trunk_ddi_key) {
36            println!("[CallableCache::get_account_by_trunk_ddi] Found trunk-DDI in local cache, account_id: {}", account_id);
37            // If we have an account ID, try to get the account from the local account cache
38            if let Some(account) = self.local_cache.accounts.get(account_id.as_str()) {
39                println!("[CallableCache::get_account_by_trunk_ddi] Found account in local cache: {}", account.name);
40                return Ok(Some(account.clone()));
41            }
42
43            // If account not in local cache, but we have the ID, fetch from Redis
44            println!("[CallableCache::get_account_by_trunk_ddi] Account not in local cache, fetching from Redis");
45            match get_account_by_id(self.remote_cache.connection.clone(), account_id.as_str())
46                .await?
47            {
48                Some(account) => {
49                    println!("[CallableCache::get_account_by_trunk_ddi] Found account in Redis: {}", account.name);
50                    // Cache the retrieved account for future use
51                    build_account_identifiers_locally(self.local_cache, &account.clone());
52                    Ok(Some(Arc::new(account)))
53                }
54                None => {
55                    println!("[CallableCache::get_account_by_trunk_ddi] Account not found in Redis for id: {}", account_id);
56                    Ok(None)
57                }
58            }
59        } else {
60            // If trunk-DDI combination not in local cache, try Redis
61            println!("[CallableCache::get_account_by_trunk_ddi] Trunk-DDI not in local cache, checking Redis");
62            match get_trunk_and_ddi(self.remote_cache.connection.clone(), ddi_id, trunk_ip).await? {
63                Some(account) => {
64                    println!("[CallableCache::get_account_by_trunk_ddi] Found account in Redis via trunk-DDI lookup: {}", account.name);
65                    // Cache the retrieved account and trunk-DDI mapping for future use
66                    build_account_identifiers_locally(self.local_cache.clone(), &account.clone());
67
68                    // Add the trunk-DDI mapping to local cache
69                    self.local_cache
70                        .trunk_ddi_idents
71                        .insert(trunk_ddi_key, account.id.clone());
72
73                    Ok(Some(Arc::new(account)))
74                }
75                None => {
76                    println!("[CallableCache::get_account_by_trunk_ddi] No account found for trunk-DDI combination");
77                    Ok(None)
78                }
79            }
80        }
81    }
82
83    /// Retrieves an account by its ID, first checking the local cache and then Redis.
84    ///
85    /// # Arguments
86    /// * `id` - Account ID to look up
87    ///
88    /// # Returns
89    /// * `Result<Option<AccountLite>, RedisError>` - Account if found, None if not found, or a Redis error
90    pub async fn get_account_by_id(self, id: &str) -> Result<Option<Arc<AccountLite>>, RedisError> {
91        // Try to get the resolved ID from the local cache
92        if let Some(resolved_id) = self.local_cache.account_idents.get(id) {
93            // If we have a resolved ID, try to get the account from the local cache
94            println!(
95                "CallableCache: get_account_by_id: Found local ident {:?}",
96                resolved_id
97            );
98            if let Some(account) = self.local_cache.accounts.get(resolved_id.as_str()) {
99                println!(
100                    "CallableCache: get_account_by_id: Found local account {:?}",
101                    resolved_id
102                );
103                return Ok(Some(account));
104            }
105
106            // If not in local cache, fetch from Redis using the resolved ID
107            match get_account_by_id(self.remote_cache.connection.clone(), &resolved_id).await? {
108                Some(account) => {
109                    // Cache the retrieved account for future use
110                    println!(
111                        "CallableCache: get_account_by_id: Found remote account {:?}",
112                        resolved_id
113                    );
114                    self.local_cache
115                        .account_idents
116                        .insert(id.to_string(), account.id.to_string());
117                    build_account_identifiers_locally(self.local_cache, &account.clone());
118                    Ok(Some(Arc::new(account)))
119                }
120                None => Ok(None),
121            }
122        } else {
123            // If account identifier not in local cache, try Redis
124            println!(
125                "CallableCache: get_account_by_id: Find remote account ident {:?}",
126                id
127            );
128            match get_account_by_ident(self.remote_cache.connection.clone(), id).await? {
129                Some(account) => {
130                    // Cache the retrieved account for future use
131                    println!(
132                        "CallableCache: get_account_by_id: Found remote account {:?}",
133                        account.name
134                    );
135                    self.local_cache
136                        .accounts
137                        .insert(id.to_string(), Arc::new(account.clone()));
138                    build_account_identifiers_locally(self.local_cache, &account.clone());
139                    Ok(Some(Arc::new(account)))
140                }
141                None => {
142                    println!(
143                        "CallableCache: get_account_by_id: No account ident {:?}",
144                        id
145                    );
146                    Ok(None)
147                }
148            }
149        }
150    }
151
152    /// Retrieves all accounts from Redis.
153    ///
154    /// # Returns
155    /// * `Result<Vec<AccountLite>, RedisError>` - Vec of AccountLite
156    pub async fn get_accounts(self) -> Result<Arc<Vec<AccountLite>>, RedisError> {
157        println!("[CallableCache::get_accounts] Getting all accounts from Redis");
158        let accounts = get_accounts(self.remote_cache.connection).await?;
159        println!("[CallableCache::get_accounts] Retrieved {} accounts from Redis", accounts.len());
160        for account in &accounts {
161            build_account_identifiers_locally(self.local_cache.clone(), account);
162        }
163        Ok(Arc::new(accounts))
164    }
165}