pub struct FloodSubRouter { /* private fields */ }Expand description
Topic-based message flooding router.
§Responsibilities
- Maintain per-peer topic subscriptions.
- Deduplicate messages using a bounded, TTL-based ID cache.
- Track which peers have already received a given message to prevent loops.
- Compute forward sets excluding the origin peer and previously-forwarded peers.
§Thread safety
FloodSubRouter is not Send + Sync by default; callers should wrap it
in a Mutex or RwLock when sharing across threads.
Implementations§
Source§impl FloodSubRouter
impl FloodSubRouter
Sourcepub fn new(config: RouterConfig) -> Self
pub fn new(config: RouterConfig) -> Self
Create a new router with the supplied configuration.
Sourcepub fn subscribe(&mut self, peer_id: &str, topic: &FloodTopic, now: u64) -> bool
pub fn subscribe(&mut self, peer_id: &str, topic: &FloodTopic, now: u64) -> bool
Subscribe peer_id to topic.
Returns true if this was a new subscription, false if the peer
was already subscribed to this topic.
The subscription is rejected (returns false) when either:
- the per-topic peer limit (
max_peers_per_topic) would be exceeded, or - the global topic limit (
max_topics) would be exceeded by a new topic.
Sourcepub fn unsubscribe(&mut self, peer_id: &str, topic: &FloodTopic) -> bool
pub fn unsubscribe(&mut self, peer_id: &str, topic: &FloodTopic) -> bool
Unsubscribe peer_id from topic.
Returns true if the subscription existed and was removed.
Sourcepub fn peers_for_topic(&self, topic: &FloodTopic) -> Vec<String>
pub fn peers_for_topic(&self, topic: &FloodTopic) -> Vec<String>
Return all peer IDs subscribed to topic.
Sourcepub fn topics_for_peer(&self, peer_id: &str) -> Vec<FloodTopic>
pub fn topics_for_peer(&self, peer_id: &str) -> Vec<FloodTopic>
Return all topics to which peer_id is subscribed.
Sourcepub fn route(&mut self, msg: &FloodMessage, now: u64) -> ForwardDecision
pub fn route(&mut self, msg: &FloodMessage, now: u64) -> ForwardDecision
Decide how to forward msg and update all internal state accordingly.
§Decision logic (in order)
- If
msg.idis already in the dedup cache →Drop(duplicate). - If
msg.ttl <= config.min_ttl→Drop(TTL exhausted). - If no peer is subscribed to
msg.topic→Drop(no subscribers). - Insert
msg.idinto the dedup cache withnowas the timestamp. - Build the candidate forward set: all subscribers except the origin
peer and peers already recorded in
forwarded_to[msg.id]. - Record the candidate set in
forwarded_to. - If the candidate set is empty and the origin is the only subscriber
→
Loopback. - If the candidate set is empty (all already forwarded) →
Drop. - Otherwise →
Forward { to_peers }.
Sourcepub fn mark_forwarded(&mut self, id: &FloodMessageId, peer_id: &str)
pub fn mark_forwarded(&mut self, id: &FloodMessageId, peer_id: &str)
Record that msg_id was manually forwarded to peer_id.
Useful when the caller forwards a message outside of route and wants
to keep the loop-prevention state consistent.
Sourcepub fn expire_cache(&mut self, now: u64)
pub fn expire_cache(&mut self, now: u64)
Evict all dedup-cache entries older than config.dedup_window_secs.
Should be called periodically (e.g. every 10–30 seconds) to bound memory consumption.
Sourcepub fn stats(&self) -> &FsrRouterStats
pub fn stats(&self) -> &FsrRouterStats
Return a reference to the current operational statistics.
Sourcepub fn compute_message_id(
payload: &[u8],
topic: &FloodTopic,
peer_id: &str,
now: u64,
) -> FloodMessageId
pub fn compute_message_id( payload: &[u8], topic: &FloodTopic, peer_id: &str, now: u64, ) -> FloodMessageId
Compute a FloodMessageId from payload, topic, peer_id, and a
Unix-epoch timestamp.
The ID is produced by running FNV-1a over all inputs concatenated in a deterministic order, then taking two sequential hashes to fill 16 bytes.
Sourcepub fn cache_full(&self) -> bool
pub fn cache_full(&self) -> bool
Return true when the dedup cache is at capacity.
Sourcepub fn forwarded_count(&self, id: &FloodMessageId) -> usize
pub fn forwarded_count(&self, id: &FloodMessageId) -> usize
Return the number of peers that have already been sent id.
Sourcepub fn is_subscribed(&self, peer_id: &str, topic: &FloodTopic) -> bool
pub fn is_subscribed(&self, peer_id: &str, topic: &FloodTopic) -> bool
Return true if peer_id is subscribed to topic.
Sourcepub fn subscription(
&self,
peer_id: &str,
topic: &FloodTopic,
) -> Option<&SubscriptionRecord>
pub fn subscription( &self, peer_id: &str, topic: &FloodTopic, ) -> Option<&SubscriptionRecord>
Return the SubscriptionRecord for peer_id on topic, if any.
Sourcepub fn subscription_count(&self) -> usize
pub fn subscription_count(&self) -> usize
Return the total number of active subscriptions.
Sourcepub fn all_subscriptions(&self) -> impl Iterator<Item = &SubscriptionRecord>
pub fn all_subscriptions(&self) -> impl Iterator<Item = &SubscriptionRecord>
Return an iterator over all active SubscriptionRecords.
Auto Trait Implementations§
impl Freeze for FloodSubRouter
impl RefUnwindSafe for FloodSubRouter
impl Send for FloodSubRouter
impl Sync for FloodSubRouter
impl Unpin for FloodSubRouter
impl UnsafeUnpin for FloodSubRouter
impl UnwindSafe for FloodSubRouter
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