use std::collections::HashMap;
use std::sync::atomic::Ordering;
use crate::errors;
use crate::models::ServerState;
pub fn select_backend_server(
servers: &HashMap<String, ServerState>,
requested_block: Option<u32>,
) -> Result<String, &'static str> {
let mut best: Option<(u8, usize, String)> = None;
for (server, state) in servers.iter() {
if !state.enabled || !state.online {
continue;
}
let conns = state.connections.load(Ordering::Relaxed);
let covers_range = match requested_block {
Some(block) => {
state.trace_end_block > 0
&& state.trace_begin_block <= block
&& block < state.trace_end_block
}
None => false,
};
let rank = match (covers_range, state.stale) {
(true, false) => 0u8,
(true, true) => 1,
(false, false) => 2,
(false, true) => 3,
};
let better = match &best {
None => true,
Some((best_rank, best_conns, _)) => (rank, conns) < (*best_rank, *best_conns),
};
if better {
best = Some((rank, conns, server.clone()));
}
}
match best {
Some((rank, _, server)) => {
if let Some(block) = requested_block {
if rank >= 2 {
tracing::warn!(
block,
"no upstream covers the requested block; falling back to least-connections"
);
}
}
Ok(server)
}
None => Err(errors::NO_SERVERS_AVAILABLE),
}
}
pub fn buffer_to_hex(buffer: Vec<u8>) -> String {
let mut hex = String::with_capacity(buffer.len() * 2);
for byte in buffer {
hex.push_str(&format!("{:02x}", byte));
}
hex
}