pub struct Router { /* private fields */ }Expand description
Router for mesh message routing.
Peer selection uses UCB1 (multi-armed bandit) once sufficient samples exist;
falls back to a heuristic score during cold-start.
UCB1 state is persisted via an optional RouterStore so learned topology
survives restarts.
Implementations§
Source§impl Router
impl Router
Sourcepub fn with_store(our_node_id: String, store: Arc<dyn RouterStore>) -> Self
pub fn with_store(our_node_id: String, store: Arc<dyn RouterStore>) -> Self
Create a router backed by store for UCB1 state persistence.
Previously learned peer quality is loaded immediately.
Sourcepub async fn should_process(&self, message: &MeshMessage) -> bool
pub async fn should_process(&self, message: &MeshMessage) -> bool
Check if message should be processed (deduplication and TTL check)
Sourcepub fn is_for_us(&self, message: &MeshMessage) -> bool
pub fn is_for_us(&self, message: &MeshMessage) -> bool
Check if message is for us
Sourcepub fn prepare_for_forwarding(&self, message: &MeshMessage) -> MeshMessage
pub fn prepare_for_forwarding(&self, message: &MeshMessage) -> MeshMessage
Prepare message for forwarding (decrement TTL, add to path)
Sourcepub fn calculate_peer_score(
peer_metrics: &PeerMetrics,
route_stats: Option<&RouteStats>,
) -> f64
pub fn calculate_peer_score( peer_metrics: &PeerMetrics, route_stats: Option<&RouteStats>, ) -> f64
Calculate routing score for a peer based on metrics (higher is better) Uses adaptive learning: score = αold_score + βnew_score
Sourcepub fn get_forward_peers(
&self,
message: &MeshMessage,
all_peers: &[String],
) -> Vec<String>
pub fn get_forward_peers( &self, message: &MeshMessage, all_peers: &[String], ) -> Vec<String>
Get list of peers to forward to (flooding: all except sender)
Sourcepub async fn get_best_forward_peers(
&self,
message: &MeshMessage,
peer_infos: &[PeerInfo],
max_peers: usize,
) -> Vec<String>
pub async fn get_best_forward_peers( &self, message: &MeshMessage, peer_infos: &[PeerInfo], max_peers: usize, ) -> Vec<String>
Get best peers to forward to using UCB1 adaptive routing.
Peer selection strategy:
- Warm-up (selections < UCB1_MIN_SAMPLES): heuristic score + exploration bonus. Unvisited peers receive the highest bonus, ensuring all peers are tried first.
- Exploitation (selections >= UCB1_MIN_SAMPLES): pure UCB1 score.
Returns peers sorted by score (best first), limited to top max_peers.
Sourcepub async fn get_best_forward_peers_toward(
&self,
message: &MeshMessage,
peer_infos: &[PeerInfo],
max_peers: usize,
dest: &str,
) -> Vec<String>
pub async fn get_best_forward_peers_toward( &self, message: &MeshMessage, peer_infos: &[PeerInfo], max_peers: usize, dest: &str, ) -> Vec<String>
Destination-conditioned peer selection.
Identical to Self::get_best_forward_peers except that the bandit state
consulted is the one scoped to dest. A neighbour that is an excellent step
toward one destination is often a poor step toward another, so scoring peers
with a single destination-agnostic estimate discards the signal that actually
determines routing quality.
Warm-up behaviour is unchanged: until a peer has UCB1_MIN_SAMPLES
observations for this destination, the heuristic score plus an exploration
bonus is used, so unvisited peers are still tried first.
Sourcepub async fn record_route_outcome_toward(
&self,
dest: &str,
peer_id: &str,
success: Option<Duration>,
)
pub async fn record_route_outcome_toward( &self, dest: &str, peer_id: &str, success: Option<Duration>, )
Record a delivery outcome against the bandit scoped to dest.
success carries the observed hop latency; None records a failure.
Reward matches the destination-agnostic path: clamp(1 - 2*latency, 0.5, 1.0)
on success, 0.0 on failure.
Sourcepub async fn q_select_toward(
&self,
message: &MeshMessage,
peer_infos: &[PeerInfo],
max_peers: usize,
dest: &str,
) -> Vec<String>
pub async fn q_select_toward( &self, message: &MeshMessage, peer_infos: &[PeerInfo], max_peers: usize, dest: &str, ) -> Vec<String>
Choose next hops for dest by Q-value, best first, limited to max_peers.
Optimistic initialisation (Q_INIT = 1.0) means any neighbour never yet
tried for dest outscores explored ones, so every neighbour is attempted
at least once before the estimates take over — the same warm-up the
benchmark uses. Connected peers only; sender and nodes already on the path
are excluded for loop-freedom.
Sourcepub async fn q_advertised_value(&self, dest: &str, neighbours: &[String]) -> f64
pub async fn q_advertised_value(&self, dest: &str, neighbours: &[String]) -> f64
The value this node advertises to an upstream neighbour for dest:
max over its own neighbours’ Q-estimates. This is the quantity a
downstream node bootstraps from. neighbours is the caller’s current
connected-peer id list.
Sourcepub async fn q_record(
&self,
dest: &str,
peer: &str,
delivered: bool,
downstream_value: f64,
)
pub async fn q_record( &self, dest: &str, peer: &str, delivered: bool, downstream_value: f64, )
Update the Q-estimate for hop peer toward dest after an outcome.
downstream_value is the estimate the neighbour advertised (its
q_advertised_value for dest). On success the bootstrap target is that
value; on failure it is 0. This is the delivery-probability form of the
Boyan–Littman update.
Sourcepub async fn record_route_success(&self, peer_id: &str, latency: Duration)
pub async fn record_route_success(&self, peer_id: &str, latency: Duration)
Record successful route (for adaptive learning). Updates both the heuristic history and the UCB1 bandit state. Reward is latency-weighted: r = clamp(1 - 2*latency_secs, 0.5, 1.0).
Sourcepub async fn record_route_failure(&self, peer_id: &str)
pub async fn record_route_failure(&self, peer_id: &str)
Record failed route (for adaptive learning). Updates both the heuristic history and the UCB1 bandit state (reward = 0).
Sourcepub async fn cleanup_cache(&self)
pub async fn cleanup_cache(&self)
Cleanup old cache entries