From 55a862930e628b4d39b16c01ccf8f8813add2a78 Mon Sep 17 00:00:00 2001 From: Ian Clarke Date: Tue, 10 Oct 2023 15:37:52 -0500 Subject: [PATCH 1/3] propagate estimation errors --- crates/core/src/router.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/core/src/router.rs b/crates/core/src/router.rs index 9d6ca0689..de00fb985 100644 --- a/crates/core/src/router.rs +++ b/crates/core/src/router.rs @@ -192,19 +192,19 @@ impl Router { if !self.has_sufficient_historical_data() { return Err(RoutingError::InsufficientDataError); } - + let time_to_response_start_estimate = self .response_start_time_estimator .estimate_retrieval_time(peer, contract_location) - .unwrap(); + .map_err(|e| RoutingError::EstimationError(format!("Response Start Time Estimation failed: {}", e)))?; let failure_estimate = self .failure_estimator .estimate_retrieval_time(peer, contract_location) - .unwrap(); + .map_err(|e| RoutingError::EstimationError(format!("Failure Estimation failed: {}", e)))?; let transfer_rate_estimate = self .transfer_rate_estimator .estimate_retrieval_time(peer, contract_location) - .unwrap(); + .map_err(|e| RoutingError::EstimationError(format!("Transfer Rate Estimation failed: {}", e)))?; // This is a fairly naive approach, assuming that the cost of a failure is a multiple // of the cost of success. @@ -233,6 +233,7 @@ impl Router { #[derive(Debug)] pub(crate) enum RoutingError { InsufficientDataError, + EstimationError(String), } #[derive(Debug, Clone, Copy, Serialize)] From b296f537a1f37da7e4a4f2c8a0db99f9ba0d8e0f Mon Sep 17 00:00:00 2001 From: Ian Clarke Date: Tue, 10 Oct 2023 16:32:20 -0500 Subject: [PATCH 2/3] fix build --- crates/core/src/router.rs | 11 ++++++++++- crates/core/src/router/isotonic_estimator.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/core/src/router.rs b/crates/core/src/router.rs index de00fb985..97bf1a87f 100644 --- a/crates/core/src/router.rs +++ b/crates/core/src/router.rs @@ -5,7 +5,7 @@ mod util; use crate::ring::{Location, PeerKeyLocation}; use isotonic_estimator::{EstimatorType, IsotonicEstimator, IsotonicEvent}; use serde::Serialize; -use std::time::Duration; +use std::{time::Duration, fmt,}; use util::{Mean, TransferSpeed}; #[derive(Debug, Clone, Serialize)] @@ -236,6 +236,15 @@ pub(crate) enum RoutingError { EstimationError(String), } +impl fmt::Display for RoutingError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + RoutingError::InsufficientDataError => write!(f, "Insufficient data provided"), + RoutingError::EstimationError(err_msg) => write!(f, "Estimation error: {}", err_msg), + } + } +} + #[derive(Debug, Clone, Copy, Serialize)] pub(crate) struct RoutingPrediction { pub failure_probability: f64, diff --git a/crates/core/src/router/isotonic_estimator.rs b/crates/core/src/router/isotonic_estimator.rs index 300854e11..71c9331fe 100644 --- a/crates/core/src/router/isotonic_estimator.rs +++ b/crates/core/src/router/isotonic_estimator.rs @@ -1,7 +1,7 @@ use crate::ring::{Distance, Location, PeerKeyLocation}; use pav_regression::pav::{IsotonicRegression, Point}; use serde::Serialize; -use std::collections::HashMap; +use std::{collections::HashMap, fmt,}; const MIN_POINTS_FOR_REGRESSION: usize = 5; @@ -160,6 +160,14 @@ pub(crate) enum EstimationError { InsufficientData, // Error indicating that there is not enough data for estimation } +impl fmt::Display for EstimationError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + EstimationError::InsufficientData => write!(f, "Insufficient data for estimation"), + } + } +} + /// A routing event is a single request to a peer for a contract, and some value indicating /// the result of the request, such as the time it took to retrieve the contract. #[derive(Debug, Clone)] From f882c1d8580f057afd84d537b5479576f8b31cef Mon Sep 17 00:00:00 2001 From: Ian Clarke Date: Tue, 10 Oct 2023 17:11:48 -0500 Subject: [PATCH 3/3] format --- crates/core/src/router.rs | 19 ++++++++++++++----- crates/core/src/router/isotonic_estimator.rs | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/core/src/router.rs b/crates/core/src/router.rs index 97bf1a87f..46f229aaa 100644 --- a/crates/core/src/router.rs +++ b/crates/core/src/router.rs @@ -5,7 +5,7 @@ mod util; use crate::ring::{Location, PeerKeyLocation}; use isotonic_estimator::{EstimatorType, IsotonicEstimator, IsotonicEvent}; use serde::Serialize; -use std::{time::Duration, fmt,}; +use std::{fmt, time::Duration}; use util::{Mean, TransferSpeed}; #[derive(Debug, Clone, Serialize)] @@ -192,19 +192,28 @@ impl Router { if !self.has_sufficient_historical_data() { return Err(RoutingError::InsufficientDataError); } - + let time_to_response_start_estimate = self .response_start_time_estimator .estimate_retrieval_time(peer, contract_location) - .map_err(|e| RoutingError::EstimationError(format!("Response Start Time Estimation failed: {}", e)))?; + .map_err(|e| { + RoutingError::EstimationError(format!( + "Response Start Time Estimation failed: {}", + e + )) + })?; let failure_estimate = self .failure_estimator .estimate_retrieval_time(peer, contract_location) - .map_err(|e| RoutingError::EstimationError(format!("Failure Estimation failed: {}", e)))?; + .map_err(|e| { + RoutingError::EstimationError(format!("Failure Estimation failed: {}", e)) + })?; let transfer_rate_estimate = self .transfer_rate_estimator .estimate_retrieval_time(peer, contract_location) - .map_err(|e| RoutingError::EstimationError(format!("Transfer Rate Estimation failed: {}", e)))?; + .map_err(|e| { + RoutingError::EstimationError(format!("Transfer Rate Estimation failed: {}", e)) + })?; // This is a fairly naive approach, assuming that the cost of a failure is a multiple // of the cost of success. diff --git a/crates/core/src/router/isotonic_estimator.rs b/crates/core/src/router/isotonic_estimator.rs index 71c9331fe..e3670607e 100644 --- a/crates/core/src/router/isotonic_estimator.rs +++ b/crates/core/src/router/isotonic_estimator.rs @@ -1,7 +1,7 @@ use crate::ring::{Distance, Location, PeerKeyLocation}; use pav_regression::pav::{IsotonicRegression, Point}; use serde::Serialize; -use std::{collections::HashMap, fmt,}; +use std::{collections::HashMap, fmt}; const MIN_POINTS_FOR_REGRESSION: usize = 5;