Files
nym/explorer-api/src/ping/models.rs
T

81 lines
2.3 KiB
Rust

use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use nym_mixnet_contract_common::MixId;
use serde::Deserialize;
use serde::Serialize;
use tokio::sync::RwLock;
pub(crate) type PingCache = HashMap<MixId, PingCacheItem>;
const PING_TTL: Duration = Duration::from_secs(60 * 5); // 5 mins, before port check will be re-tried (only while pending)
const CACHE_TTL: Duration = Duration::from_secs(60 * 60); // 1 hour, to cache result from port check
#[derive(Clone)]
pub(crate) struct ThreadsafePingCache {
inner: Arc<RwLock<PingCache>>,
}
impl ThreadsafePingCache {
pub(crate) fn new() -> Self {
ThreadsafePingCache {
inner: Arc::new(RwLock::new(PingCache::new())),
}
}
pub(crate) async fn get(&self, mix_id: MixId) -> Option<PingResponse> {
self.inner
.read()
.await
.get(&mix_id)
.filter(|cache_item| cache_item.valid_until > SystemTime::now())
.map(|cache_item| {
if cache_item.pending {
return PingResponse {
pending: true,
ports: None,
};
}
PingResponse {
pending: false,
ports: cache_item.ports.clone(),
}
})
}
pub(crate) async fn set_pending(&self, mix_id: MixId) {
self.inner.write().await.insert(
mix_id,
PingCacheItem {
pending: true,
valid_until: SystemTime::now() + PING_TTL,
ports: None,
},
);
}
pub(crate) async fn set(&self, mix_id: MixId, item: PingResponse) {
self.inner.write().await.insert(
mix_id,
PingCacheItem {
pending: false,
valid_until: SystemTime::now() + CACHE_TTL,
ports: item.ports,
},
);
}
}
#[derive(Deserialize, Serialize, JsonSchema, Clone)]
pub(crate) struct PingResponse {
pub(crate) pending: bool,
pub(crate) ports: Option<HashMap<u16, bool>>,
}
pub(crate) struct PingCacheItem {
pub(crate) pending: bool,
pub(crate) ports: Option<HashMap<u16, bool>>,
pub(crate) valid_until: std::time::SystemTime,
}