78 lines
2.0 KiB
Rust
78 lines
2.0 KiB
Rust
use {
|
|
solana_rpc_client_api::{config::RpcLargestAccountsFilter, response::RpcAccountBalance},
|
|
std::{
|
|
collections::HashMap,
|
|
time::{Duration, SystemTime},
|
|
},
|
|
};
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct LargestAccountsCache {
|
|
duration: u64,
|
|
cache: HashMap<Option<RpcLargestAccountsFilter>, LargestAccountsCacheValue>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
struct LargestAccountsCacheValue {
|
|
accounts: Vec<RpcAccountBalance>,
|
|
slot: u64,
|
|
cached_time: SystemTime,
|
|
}
|
|
|
|
impl LargestAccountsCache {
|
|
pub(crate) fn new(duration: u64) -> Self {
|
|
Self {
|
|
duration,
|
|
cache: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn get_largest_accounts(
|
|
&self,
|
|
filter: &Option<RpcLargestAccountsFilter>,
|
|
) -> Option<(u64, Vec<RpcAccountBalance>)> {
|
|
self.cache.get(filter).and_then(|value| {
|
|
if let Ok(elapsed) = value.cached_time.elapsed() {
|
|
if elapsed < Duration::from_secs(self.duration) {
|
|
return Some((value.slot, value.accounts.clone()));
|
|
}
|
|
}
|
|
None
|
|
})
|
|
}
|
|
|
|
pub(crate) fn set_largest_accounts(
|
|
&mut self,
|
|
filter: &Option<RpcLargestAccountsFilter>,
|
|
slot: u64,
|
|
accounts: &[RpcAccountBalance],
|
|
) {
|
|
self.cache.insert(
|
|
filter.clone(),
|
|
LargestAccountsCacheValue {
|
|
accounts: accounts.to_owned(),
|
|
slot,
|
|
cached_time: SystemTime::now(),
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_old_entries_expire() {
|
|
let mut cache = LargestAccountsCache::new(1);
|
|
|
|
let filter = Some(RpcLargestAccountsFilter::Circulating);
|
|
|
|
let accounts: Vec<RpcAccountBalance> = Vec::new();
|
|
|
|
cache.set_largest_accounts(&filter, 1000, &accounts);
|
|
std::thread::sleep(Duration::from_secs(1));
|
|
assert_eq!(cache.get_largest_accounts(&filter), None);
|
|
}
|
|
}
|