diff --git a/explorer-api/src/mix_node/http.rs b/explorer-api/src/mix_node/http.rs index eeb737b16c..d9cb546c3e 100644 --- a/explorer-api/src/mix_node/http.rs +++ b/explorer-api/src/mix_node/http.rs @@ -34,27 +34,7 @@ pub(crate) struct PrettyMixNodeBondWithLocation { pub(crate) async fn list( state: &State, ) -> Json> { - Json( - state - .inner - .mix_nodes - .get() - .await - .value - .values() - .map(|i| { - let mix_node = i.bond.clone(); - PrettyMixNodeBondWithLocation { - location: i.location.clone(), - bond_amount: mix_node.bond_amount, - total_delegation: mix_node.total_delegation, - owner: mix_node.owner, - layer: mix_node.layer, - mix_node: mix_node.mix_node, - } - }) - .collect::>(), - ) + Json(state.inner.mix_nodes.get_mixnodes_with_location().await) } #[openapi(tag = "mix_node")] diff --git a/explorer-api/src/mix_nodes/mod.rs b/explorer-api/src/mix_nodes/mod.rs index f04a2dbce0..7952c7b0b0 100644 --- a/explorer-api/src/mix_nodes/mod.rs +++ b/explorer-api/src/mix_nodes/mod.rs @@ -7,6 +7,7 @@ use std::time::{Duration, SystemTime}; use rocket::tokio::sync::RwLock; use serde::{Deserialize, Serialize}; +use crate::mix_node::http::PrettyMixNodeBondWithLocation; use crate::mix_nodes::utils::map_2_letter_to_3_letter_country_code; use mixnet_contract::{Delegation, MixNodeBond, RawDelegationData, UnpackedDelegation}; use network_defaults::{ @@ -53,10 +54,6 @@ impl Location { } } -#[derive(Clone, Debug)] -pub(crate) struct MixNodeBondWithLocation { - pub(crate) location: Option, - pub(crate) bond: MixNodeBond, } #[derive(Clone, Debug)] @@ -92,23 +89,28 @@ impl ThreadsafeMixNodesResult { } } + pub(crate) async fn is_location_valid(&self, identity_key: &str) -> bool { + self.inner + .read() + .await + .location_cache + .get(identity_key) + .map(|cache_item| cache_item.valid_until > SystemTime::now()) + .unwrap_or(false) + } + pub(crate) async fn get_location_cache(&self) -> LocationCache { self.inner.read().await.location_cache.clone() } - pub(crate) async fn set_location(&self, identity_key: &str, location: Location) { + pub(crate) async fn set_location(&self, identity_key: &str, location: Option) { let mut guard = self.inner.write().await; // cache the location for this mix node so that it can be used when the mix node list is refreshed - guard - .location_cache - .insert(identity_key.to_string(), location.clone()); - - // add the location to the mix node - guard - .value - .entry(identity_key.to_string()) - .and_modify(|item| item.location = Some(location)); + guard.location_cache.insert( + identity_key.to_string(), + LocationCacheItem::new_from_location(location), + ); } pub(crate) async fn get(&self) -> MixNodesResult { @@ -124,25 +126,34 @@ impl ThreadsafeMixNodesResult { self.inner.read().await.clone() } - pub(crate) async fn refresh_and_get(&self) -> MixNodesResult { - self.refresh().await; - self.inner.read().await.clone() + pub(crate) async fn get_mixnodes_with_location(&self) -> Vec { + let guard = self.inner.read().await; + guard + .value + .values() + .map(|bond| { + let location = guard.location_cache.get(&bond.mix_node.identity_key); + let copy = bond.clone(); + PrettyMixNodeBondWithLocation { + location: location.and_then(|l| l.location.clone()), + bond_amount: copy.bond_amount, + total_delegation: copy.total_delegation, + owner: copy.owner, + layer: copy.layer, + mix_node: copy.mix_node, + } + }) + .collect() } - async fn refresh(&self) { + pub(crate) async fn refresh(&self) { // get mixnodes and cache the new value let value = retrieve_mixnodes().await; let location_cache = self.inner.read().await.location_cache.clone(); *self.inner.write().await = MixNodesResult { value: value .into_iter() - .map(|bond| { - let location = location_cache.get(&bond.mix_node.identity_key).cloned(); // add the location, if we've located this mix node before - ( - bond.mix_node.identity_key.to_string(), - MixNodeBondWithLocation { location, bond }, - ) - }) + .map(|bond| (bond.mix_node.identity_key.to_string(), bond)) .collect(), valid_until: SystemTime::now() + Duration::from_secs(60 * 10), // valid for 10 minutes location_cache, diff --git a/explorer-api/src/state.rs b/explorer-api/src/state.rs index 7f7862eb68..2be0a42f5d 100644 --- a/explorer-api/src/state.rs +++ b/explorer-api/src/state.rs @@ -27,12 +27,7 @@ pub struct ExplorerApiState { impl ExplorerApiState { pub(crate) async fn get_mix_node(&self, pubkey: &str) -> Option { - self.mix_nodes - .get() - .await - .value - .get(pubkey) - .map(|cache_item| cache_item.bond.clone()) + self.mix_nodes.get().await.value.get(pubkey).cloned() } }