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