use custom_debug_derive::Debug;
use super::scoring::ScoringWeights;
use crate::{environment::Environment, remote_node::RemoteNode};
#[derive(Debug, Clone)]
pub(super) struct NodeInfo<Env: Environment> {
pub(super) node: RemoteNode<Env::ValidatorNode>,
ema_latency_ms: f64,
ema_success_rate: f64,
total_requests: u64,
weights: ScoringWeights,
alpha: f64,
max_expected_latency_ms: f64,
}
impl<Env: Environment> NodeInfo<Env> {
pub(super) fn with_config(
node: RemoteNode<Env::ValidatorNode>,
weights: ScoringWeights,
alpha: f64,
max_expected_latency_ms: f64,
) -> Self {
assert!(alpha > 0.0 && alpha < 1.0, "Alpha must be in (0, 1) range");
Self {
node,
ema_latency_ms: 100.0, ema_success_rate: 1.0, total_requests: 0,
weights,
alpha,
max_expected_latency_ms,
}
}
pub(super) fn calculate_score(&self) -> f64 {
let latency_score = 1.0
- (self.ema_latency_ms.min(self.max_expected_latency_ms)
/ self.max_expected_latency_ms);
let success_score = self.ema_success_rate;
let confidence_factor = (self.total_requests as f64 / 10.0).min(1.0);
let raw_score =
(self.weights.latency * latency_score) + (self.weights.success * success_score);
raw_score * (0.5 + 0.5 * confidence_factor)
}
pub(super) fn update_metrics(&mut self, success: bool, response_time_ms: u64) {
let response_time_f64 = response_time_ms as f64;
self.ema_latency_ms =
(self.alpha * response_time_f64) + ((1.0 - self.alpha) * self.ema_latency_ms);
let success_value = if success { 1.0 } else { 0.0 };
self.ema_success_rate =
(self.alpha * success_value) + ((1.0 - self.alpha) * self.ema_success_rate);
self.total_requests += 1;
}
pub(super) fn ema_success_rate(&self) -> f64 {
self.ema_success_rate
}
pub(super) fn total_requests(&self) -> u64 {
self.total_requests
}
}