Filter by semver
This commit is contained in:
@@ -2,7 +2,9 @@ use axum::{
|
||||
extract::{Path, Query, State},
|
||||
Json, Router,
|
||||
};
|
||||
use semver::Version;
|
||||
use serde::Deserialize;
|
||||
use std::sync::LazyLock;
|
||||
use tracing::instrument;
|
||||
use utoipa::IntoParams;
|
||||
|
||||
@@ -12,6 +14,8 @@ use crate::http::{
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
static MIN_SUPPORTED_VERSION: LazyLock<Version> = LazyLock::new(|| Version::new(1, 6, 2));
|
||||
|
||||
pub(crate) fn routes() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", axum::routing::get(dvpn_gateways))
|
||||
@@ -45,12 +49,17 @@ async fn dvpn_gateways(
|
||||
Query(MinNodeVersionQuery { min_node_version }): Query<MinNodeVersionQuery>,
|
||||
state: State<AppState>,
|
||||
) -> HttpResult<Json<Vec<DVpnGateway>>> {
|
||||
let min_node_version: String = min_node_version.unwrap_or_else(|| String::from("1.6.2"));
|
||||
let _min_node_version = semver::Version::parse(&min_node_version)
|
||||
.map_err(|_| HttpError::invalid_input("Min version must be valid semver"))?;
|
||||
let min_node_version = match min_node_version {
|
||||
Some(min_version) => semver::Version::parse(&min_version)
|
||||
.map_err(|_| HttpError::invalid_input("Min version must be valid semver"))?,
|
||||
None => MIN_SUPPORTED_VERSION.clone(),
|
||||
};
|
||||
|
||||
Ok(Json(
|
||||
state.cache().get_dvpn_gateway_list(state.db_pool()).await,
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool(), &min_node_version)
|
||||
.await,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -87,7 +96,7 @@ async fn gateways_by_country(
|
||||
2 => Ok(Json(
|
||||
state
|
||||
.cache()
|
||||
.get_dvpn_gateway_list(state.db_pool())
|
||||
.get_dvpn_gateway_list(state.db_pool(), &MIN_SUPPORTED_VERSION)
|
||||
.await
|
||||
.into_iter()
|
||||
.filter(|gw| {
|
||||
|
||||
@@ -5,6 +5,7 @@ use nym_contracts_common::NaiveFloat;
|
||||
use nym_crypto::asymmetric::ed25519::PublicKey;
|
||||
use nym_mixnet_contract_common::NodeId;
|
||||
use nym_validator_client::nym_api::SkimmedNode;
|
||||
use semver::Version;
|
||||
use std::{collections::HashMap, sync::Arc, time::Duration};
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::{error, instrument, warn};
|
||||
@@ -80,7 +81,6 @@ impl AppState {
|
||||
}
|
||||
|
||||
static GATEWAYS_LIST_KEY: &str = "gateways";
|
||||
static DVPN_GATEWAYS_LIST_KEY: &str = "dvpn_gateways";
|
||||
static MIXNODES_LIST_KEY: &str = "mixnodes";
|
||||
static NYM_NODES_LIST_KEY: &str = "nym_nodes";
|
||||
static MIXSTATS_LIST_KEY: &str = "mixstats";
|
||||
@@ -92,7 +92,8 @@ const MIXNODE_STATS_HISTORY_DAYS: usize = 30;
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct HttpCache {
|
||||
gateways: Cache<String, Arc<RwLock<Vec<Gateway>>>>,
|
||||
dvpn_gateways: Cache<String, Arc<RwLock<Vec<DVpnGateway>>>>,
|
||||
// each min_version has their own cached list
|
||||
dvpn_gateways: Cache<Version, Arc<RwLock<Vec<DVpnGateway>>>>,
|
||||
mixnodes: Cache<String, Arc<RwLock<Vec<Mixnode>>>>,
|
||||
nym_nodes: Cache<String, Arc<RwLock<Vec<ExtendedNymNode>>>>,
|
||||
mixstats: Cache<String, Arc<RwLock<Vec<DailyStats>>>>,
|
||||
@@ -108,7 +109,7 @@ impl HttpCache {
|
||||
.time_to_live(Duration::from_secs(ttl_seconds))
|
||||
.build(),
|
||||
dvpn_gateways: Cache::builder()
|
||||
.max_capacity(2)
|
||||
.max_capacity(6)
|
||||
.time_to_live(Duration::from_secs(ttl_seconds))
|
||||
.build(),
|
||||
mixnodes: Cache::builder()
|
||||
@@ -182,9 +183,10 @@ impl HttpCache {
|
||||
pub async fn upsert_dvpn_gateway_list(
|
||||
&self,
|
||||
new_gateway_list: Vec<DVpnGateway>,
|
||||
) -> Entry<String, Arc<RwLock<Vec<DVpnGateway>>>> {
|
||||
min_node_version: &Version,
|
||||
) -> Entry<Version, Arc<RwLock<Vec<DVpnGateway>>>> {
|
||||
self.dvpn_gateways
|
||||
.entry_by_ref(DVPN_GATEWAYS_LIST_KEY)
|
||||
.entry_by_ref(min_node_version)
|
||||
.and_upsert_with(|maybe_entry| async {
|
||||
if let Some(entry) = maybe_entry {
|
||||
let v = entry.into_value();
|
||||
@@ -198,8 +200,12 @@ impl HttpCache {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_dvpn_gateway_list(&self, db: &DbPool) -> Vec<DVpnGateway> {
|
||||
match self.dvpn_gateways.get(DVPN_GATEWAYS_LIST_KEY).await {
|
||||
pub async fn get_dvpn_gateway_list(
|
||||
&self,
|
||||
db: &DbPool,
|
||||
min_node_version: &Version,
|
||||
) -> Vec<DVpnGateway> {
|
||||
match self.dvpn_gateways.get(min_node_version).await {
|
||||
Some(guard) => {
|
||||
tracing::trace!("Fetching from cache...");
|
||||
let read_lock = guard.read().await;
|
||||
@@ -258,6 +264,15 @@ impl HttpCache {
|
||||
}
|
||||
},
|
||||
)
|
||||
.filter(|gw| {
|
||||
let gw_version = &gw.build_information.build_version;
|
||||
if let Ok(gw_version) = Version::parse(gw_version) {
|
||||
&gw_version >= min_node_version
|
||||
} else {
|
||||
warn!("Failed to parse GW version {}", gw_version);
|
||||
false
|
||||
}
|
||||
})
|
||||
.filter(|gw| {
|
||||
// gateways must have a country
|
||||
if gw.location.two_letter_iso_country_code.len() == 2 {
|
||||
@@ -282,7 +297,8 @@ impl HttpCache {
|
||||
if res_gws.is_empty() && started_with > 0 {
|
||||
tracing::warn!("Started with {}, got 0 gateways", started_with);
|
||||
} else {
|
||||
self.upsert_dvpn_gateway_list(res_gws.clone()).await;
|
||||
self.upsert_dvpn_gateway_list(res_gws.clone(), min_node_version)
|
||||
.await;
|
||||
}
|
||||
|
||||
res_gws
|
||||
|
||||
@@ -105,11 +105,10 @@ impl Monitor {
|
||||
.clone()
|
||||
.expect("rust sdk mainnet default missing api_url");
|
||||
|
||||
let nym_api =
|
||||
nym_http_api_client::ClientBuilder::new_with_url(default_api_url.into())
|
||||
.no_hickory_dns()
|
||||
.with_timeout(self.nym_api_client_timeout)
|
||||
.build::<&str>()?;
|
||||
let nym_api = nym_http_api_client::ClientBuilder::new_with_url(default_api_url)
|
||||
.no_hickory_dns()
|
||||
.with_timeout(self.nym_api_client_timeout)
|
||||
.build::<&str>()?;
|
||||
|
||||
let api_client = NymApiClient::from(nym_api);
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ async fn run(
|
||||
.clone()
|
||||
.expect("rust sdk mainnet default missing api_url");
|
||||
|
||||
let nym_api = nym_http_api_client::ClientBuilder::new_with_url(default_api_url.into())
|
||||
let nym_api = nym_http_api_client::ClientBuilder::new_with_url(default_api_url)
|
||||
.no_hickory_dns()
|
||||
.with_timeout(nym_api_client_timeout)
|
||||
.build::<&str>()?;
|
||||
|
||||
Reference in New Issue
Block a user