More extensive error handling in NC directory

This commit is contained in:
Jon Häggblad
2023-08-31 17:52:51 +02:00
parent de531d41ed
commit 58f79a972c
2 changed files with 72 additions and 33 deletions
+15 -2
View File
@@ -81,8 +81,21 @@ pub enum BackendError {
CouldNotGetConfigFilename,
#[error("could not load existing gateway configuration")]
CouldNotLoadExistingGatewayConfiguration(std::io::Error),
#[error("no suitable gateways found when querying!")]
NoGatewaysFound,
#[error("no gateways found in directory")]
NoGatewaysFoundInDirectory,
#[error("no gateways found with compatible version: {0}")]
NoVersionCompatibleGatewaysFound(String),
#[error("no gateways found with acceptable performance")]
NoGatewayWithAcceptablePerformanceFound,
#[error("no gateways found with acceptable performance when measuring latency")]
NoGatewayWithAcceptablePerformanceFoundToQuery,
#[error("no network-requesters found in directory")]
NoServicesFoundInDirectory,
#[error("no active network-requesters found in directory")]
NoActiveServicesFound,
#[error("unable to open a new window")]
NewWindowError,
#[error("unable to parse the specified gateway")]
@@ -71,14 +71,14 @@ pub async fn get_services(
let filtered_services = filter_out_inactive_services(&all_services, active_services);
log::trace!("After filtering: {:#?}", filtered_services);
if filtered_services.is_empty() {
if let Ok(services) = filtered_services {
Ok(services)
} else {
log::warn!(
"After filtering, no active services found! Using all services instead as fallback"
);
return Ok(all_services);
Ok(all_services)
}
Ok(filtered_services)
}
async fn fetch_services(privacy_level: &PrivacyLevel) -> Result<Vec<DirectoryService>> {
@@ -93,7 +93,12 @@ async fn fetch_services(privacy_level: &PrivacyLevel) -> Result<Vec<DirectorySer
.await?
.json::<Vec<DirectoryService>>()
.await?;
Ok(services_res)
if services_res.is_empty() {
log::error!("No services found in directory!");
Err(BackendError::NoServicesFoundInDirectory)
} else {
Ok(services_res)
}
}
async fn fetch_active_services() -> Result<PagedResult<HarbourMasterService>> {
@@ -101,14 +106,19 @@ async fn fetch_active_services() -> Result<PagedResult<HarbourMasterService>> {
.await?
.json::<PagedResult<HarbourMasterService>>()
.await?;
Ok(active_services)
if active_services.items.is_empty() {
log::error!("No active services found!");
Err(BackendError::NoActiveServicesFound)
} else {
Ok(active_services)
}
}
fn filter_out_inactive_services(
all_services: &[DirectoryServiceProvider],
active_services: PagedResult<HarbourMasterService>,
) -> Vec<DirectoryServiceProvider> {
all_services
) -> Result<Vec<DirectoryServiceProvider>> {
let services: Vec<_> = all_services
.iter()
.filter(|sp| {
active_services.items.iter().any(|active| {
@@ -117,34 +127,60 @@ fn filter_out_inactive_services(
})
})
.cloned()
.collect()
.collect();
if services.is_empty() {
Err(BackendError::NoServicesFoundInDirectory)
} else {
Ok(services)
}
}
async fn fetch_gateways() -> Result<Vec<GatewayBondAnnotated>> {
async fn fetch_all_gateways() -> Result<Vec<GatewayBondAnnotated>> {
let api_client = ApiClient::new(Url::from_str(&std::env::var(NYM_API)?)?);
let gateways = api_client.get_gateways_detailed().await?;
if gateways.is_empty() {
Err(BackendError::NoGatewaysFoundInDirectory)
} else {
Ok(gateways)
}
}
async fn fetch_compatible_gateways() -> Result<Vec<GatewayBondAnnotated>> {
let gateways = fetch_all_gateways().await?;
let our_version = env!("CARGO_PKG_VERSION");
log::debug!(
"Our version that we use to filter compatible gateways: {}",
our_version
);
let gateways = gateways
let gateways: Vec<_> = gateways
.into_iter()
.filter(|g| is_minor_version_compatible(&g.gateway_bond.gateway.version, our_version))
.collect();
Ok(gateways)
if gateways.is_empty() {
Err(BackendError::NoVersionCompatibleGatewaysFound(
our_version.to_string(),
))
} else {
Ok(gateways)
}
}
fn filter_out_low_performance_gateways(
gateways: Vec<GatewayBondAnnotated>,
) -> Vec<GatewayBondAnnotated> {
gateways
) -> Result<Vec<GatewayBondAnnotated>> {
let gateways: Vec<_> = gateways
.into_iter()
.filter(|g| {
g.node_performance.most_recent
> Percent::from_percentage_value(GATEWAY_PERFORMANCE_SCORE_THRESHOLD).unwrap()
})
.collect()
.collect();
if gateways.is_empty() {
log::error!("No gateways found! (with high enough performance score)");
Err(BackendError::NoGatewayWithAcceptablePerformanceFound)
} else {
Ok(gateways)
}
}
async fn select_gateway_by_latency(gateways: Vec<GatewayBondAnnotated>) -> Result<gateway::Node> {
@@ -164,22 +200,16 @@ async fn select_gateway_by_latency(gateways: Vec<GatewayBondAnnotated>) -> Resul
#[tauri::command]
pub async fn get_gateways() -> Result<Vec<Gateway>> {
log::trace!("Fetching gateways");
let all_gateways = fetch_gateways().await?;
let all_gateways = fetch_compatible_gateways().await?;
log::trace!("Received: {:#?}", all_gateways);
let gateways_filtered = filter_out_low_performance_gateways(all_gateways.clone())
let gateways_filtered = filter_out_low_performance_gateways(all_gateways.clone())?
.into_iter()
.map(|g| Gateway {
identity: g.identity().clone(),
})
.collect_vec();
log::trace!("Filtered: {:#?}", gateways_filtered);
if gateways_filtered.is_empty() {
log::error!("No gateways found! (with high enough performance score)");
return Err(BackendError::NoGatewaysFound);
}
Ok(gateways_filtered)
}
@@ -187,10 +217,10 @@ pub async fn get_gateways() -> Result<Vec<Gateway>> {
#[tauri::command]
pub async fn get_gateway_with_low_latency() -> Result<Gateway> {
log::trace!("Fetching gateways");
let all_gateways = fetch_gateways().await?;
let all_gateways = fetch_compatible_gateways().await?;
log::trace!("Received: {:#?}", all_gateways);
let gateways_filtered = filter_out_low_performance_gateways(all_gateways);
let gateways_filtered = filter_out_low_performance_gateways(all_gateways)?;
let selected_gateway = select_gateway_by_latency(gateways_filtered).await?;
log::debug!("Selected gateway: {}", selected_gateway);
Ok(Gateway {
@@ -203,16 +233,12 @@ pub async fn get_gateway_with_low_latency() -> Result<Gateway> {
pub async fn select_gateway_with_low_latency_from_list(gateways: Vec<Gateway>) -> Result<Gateway> {
log::debug!("Selecting a gateway with low latency");
let gateways = gateways.into_iter().map(|g| g.identity).collect_vec();
let all_gateways = fetch_gateways().await?;
let all_gateways = fetch_compatible_gateways().await?;
let gateways_union_set: Vec<GatewayBondAnnotated> = all_gateways
.into_iter()
.filter(|g| gateways.contains(g.identity()))
.collect();
let gateways_filtered = filter_out_low_performance_gateways(gateways_union_set);
if gateways_filtered.is_empty() {
log::error!("No gateways found! (with high enough performance score)");
return Err(BackendError::NoGatewaysFound);
}
let gateways_filtered = filter_out_low_performance_gateways(gateways_union_set)?;
let selected_gateway = select_gateway_by_latency(gateways_filtered).await?;
log::debug!("Selected gateway: {}", selected_gateway);
Ok(Gateway {