pub struct AdaptivePeerScheduler {
pub config: SchedulerConfig,
pub peers: HashMap<String, PeerMetrics>,
pub schedule: HashMap<String, ScheduleSlot>,
pub global_backpressure: BackpressureSignal,
pub total_requests_dispatched: u64,
pub total_requests_succeeded: u64,
}Expand description
A dynamic peer request scheduler that adapts request rates based on peer performance, network conditions, and backpressure signals.
§Usage
use ipfrs_network::{
ApsSchedulerConfig, ApsBackpressureSignal, AdaptivePeerScheduler,
};
let config = ApsSchedulerConfig::default();
let mut sched = AdaptivePeerScheduler::new(config);
sched.register_peer("peer-1".to_string(), 0);
sched.record_success("peer-1", 50, 100);
sched.recompute_schedule(200);
if let Some(peer) = sched.next_peer() {
println!("dispatch to {peer}");
}Fields§
§config: SchedulerConfigScheduler configuration.
peers: HashMap<String, PeerMetrics>Per-peer performance metrics.
schedule: HashMap<String, ScheduleSlot>Last computed schedule.
global_backpressure: BackpressureSignalCurrent global backpressure signal.
total_requests_dispatched: u64Monotonically increasing counter of dispatched requests.
total_requests_succeeded: u64Monotonically increasing counter of succeeded requests.
Implementations§
Source§impl AdaptivePeerScheduler
impl AdaptivePeerScheduler
Sourcepub fn new(config: SchedulerConfig) -> Self
pub fn new(config: SchedulerConfig) -> Self
Creates a new scheduler with the supplied configuration.
Sourcepub fn register_peer(&mut self, peer_id: String, now: u64)
pub fn register_peer(&mut self, peer_id: String, now: u64)
Registers a peer with the scheduler.
If the peer is already known this is a no-op (existing metrics are
preserved). When the peer table is full the peer with the oldest
last_seen timestamp is evicted to make room.
Sourcepub fn remove_peer(&mut self, peer_id: &str) -> bool
pub fn remove_peer(&mut self, peer_id: &str) -> bool
Removes a peer from both the metrics table and the schedule.
Returns true if the peer was present and has been removed.
Sourcepub fn record_success(&mut self, peer_id: &str, latency_ms: u64, now: u64)
pub fn record_success(&mut self, peer_id: &str, latency_ms: u64, now: u64)
Records a successful request completion for the given peer.
Also increments the global total_requests_succeeded counter.
Silently ignores unknown peer IDs.
Sourcepub fn record_failure(&mut self, peer_id: &str, now: u64)
pub fn record_failure(&mut self, peer_id: &str, now: u64)
Records a request failure for the given peer.
Silently ignores unknown peer IDs.
Sourcepub fn set_backpressure(&mut self, signal: BackpressureSignal)
pub fn set_backpressure(&mut self, signal: BackpressureSignal)
Updates the global backpressure signal.
The new signal takes effect on the next call to
recompute_schedule.
Sourcepub fn compute_weight(&self, metrics: &PeerMetrics) -> f64
pub fn compute_weight(&self, metrics: &PeerMetrics) -> f64
Computes the scheduling weight for a single peer.
Formula:
weight = success_weight * success_rate
+ latency_weight * (1 / (1 + avg_latency_ms / 1000))The result is clamped to [0.01, 1.0].
Additionally, if the peer’s success rate is below
config.backpressure_threshold, the weight is further multiplied by
config.failure_penalty.
Sourcepub fn recompute_schedule(&mut self, now: u64)
pub fn recompute_schedule(&mut self, now: u64)
Recomputes the entire schedule based on current peer metrics and the active backpressure signal.
For each registered peer:
- The weight is computed via
compute_weight. allocated = clamp(round(weight × base × bp_factor), min, max). When backpressure isBackpressureSignal::Overloadedthe allocation is forced to0regardless of the clamp range.- The
ScheduleSlotinself.scheduleis updated (or inserted).
Sourcepub fn next_peer(&self) -> Option<&str>
pub fn next_peer(&self) -> Option<&str>
Returns the peer ID with the highest allocated_requests in the current
schedule (among peers with at least one allocated request).
Returns None when every slot is at zero (or the schedule is empty).
Also increments total_requests_dispatched when a peer is returned.
Sourcepub fn mark_dispatched(&mut self)
pub fn mark_dispatched(&mut self)
Increments the total dispatched counter. Callers should call this once
they have committed to sending a request to the peer returned by
next_peer.
Sourcepub fn peek_schedule(&self) -> Vec<(&str, u32, f64)>
pub fn peek_schedule(&self) -> Vec<(&str, u32, f64)>
Returns a snapshot of the schedule sorted by allocated_requests
descending.
Each entry is (peer_id, allocated_requests, weight).
Sourcepub fn evict_stale_peers(&mut self, now: u64, max_idle_ms: u64)
pub fn evict_stale_peers(&mut self, now: u64, max_idle_ms: u64)
Removes all peers that have not been seen within the last max_idle_ms
milliseconds (i.e. where now - last_seen > max_idle_ms).
Sourcepub fn scheduler_stats(&self) -> SchedulerStats
pub fn scheduler_stats(&self) -> SchedulerStats
Returns a statistics snapshot.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for AdaptivePeerScheduler
impl RefUnwindSafe for AdaptivePeerScheduler
impl Send for AdaptivePeerScheduler
impl Sync for AdaptivePeerScheduler
impl Unpin for AdaptivePeerScheduler
impl UnsafeUnpin for AdaptivePeerScheduler
impl UnwindSafe for AdaptivePeerScheduler
Blanket Implementations§
impl<T> Allocation for T
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more