diff options
| author | murilo ijanc | 2026-03-25 16:52:03 -0300 |
|---|---|---|
| committer | murilo ijanc | 2026-03-25 16:52:03 -0300 |
| commit | 4cff87560ba238ba6eebd16b1465c0ebae2f6ac2 (patch) | |
| tree | ae9598973520d5cd6d4528f198dec7b9699c0f5e /src/routing.rs | |
| parent | c4076f54c9e66afb73081fd33b4176ba4407a8a5 (diff) | |
| download | tesseras-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.rs | 19 |
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 } |