aboutsummaryrefslogtreecommitdiffstats
path: root/src/routing.rs
diff options
context:
space:
mode:
authormurilo ijanc2026-03-25 16:52:03 -0300
committermurilo ijanc2026-03-25 16:52:03 -0300
commit4cff87560ba238ba6eebd16b1465c0ebae2f6ac2 (patch)
treeae9598973520d5cd6d4528f198dec7b9699c0f5e /src/routing.rs
parentc4076f54c9e66afb73081fd33b4176ba4407a8a5 (diff)
downloadtesseras-dht-4cff87560ba238ba6eebd16b1465c0ebae2f6ac2.tar.gz
Remove stale peers without replacement from routing table
When a peer exceeds STALE_THRESHOLD failures and the replacement cache is empty, remove it outright instead of leaving it in the bucket indefinitely. Prevents phantom peer accumulation in small clusters where the cache rarely fills.
Diffstat (limited to 'src/routing.rs')
-rw-r--r--src/routing.rs19
1 files changed, 13 insertions, 6 deletions
diff --git a/src/routing.rs b/src/routing.rs
index a9b618d..dad9bb5 100644
--- a/src/routing.rs
+++ b/src/routing.rs
@@ -140,10 +140,8 @@ impl KBucket {
/// Add a contact to the replacement cache.
fn add_to_cache(&mut self, peer: PeerInfo) {
// Update if already in cache
- if let Some(pos) = self
- .replacements
- .iter()
- .position(|r| r.id == peer.id)
+ if let Some(pos) =
+ self.replacements.iter().position(|r| r.id == peer.id)
{
self.replacements.remove(pos);
self.replacements.push(peer);
@@ -368,7 +366,9 @@ impl RoutingTable {
/// Record a communication failure for a peer.
/// If the peer becomes stale (exceeds threshold),
/// tries to replace it with a cached contact.
- /// Returns the evicted NodeId if replacement happened.
+ /// If no replacement is available, removes the stale
+ /// peer outright to avoid phantom entries.
+ /// Returns the evicted NodeId if removal happened.
pub fn record_failure(&mut self, id: &NodeId) -> Option<NodeId> {
// Never mark pinned nodes as stale
if self.pinned.contains(id) {
@@ -377,7 +377,14 @@ impl RoutingTable {
let idx = self.bucket_index(id)?;
let became_stale = self.buckets[idx].record_failure(id);
if became_stale {
- self.buckets[idx].try_replace_stale(id)
+ // Try replacement cache first; if empty, just
+ // remove the dead peer so it doesn't linger.
+ let evicted = self.buckets[idx].try_replace_stale(id);
+ if evicted.is_none() {
+ self.remove(id);
+ return Some(*id);
+ }
+ evicted
} else {
None
}