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 | |
| 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')
| -rw-r--r-- | src/handlers.rs | 7 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/routing.rs | 19 |
3 files changed, 16 insertions, 12 deletions
diff --git a/src/handlers.rs b/src/handlers.rs index f4c5b2c..574aca3 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -849,8 +849,7 @@ impl Node { .closest .iter() .find(|p| { - q.queried.contains(&p.id) - && p.id != sender_id + q.queried.contains(&p.id) && p.id != sender_id }) .cloned(); @@ -866,9 +865,7 @@ impl Node { is_unique: false, }; if let Err(e) = self.send_store(&peer, &store_msg) { - log::debug!( - "Republish-on-access failed: {e}" - ); + log::debug!("Republish-on-access failed: {e}"); } else { log::debug!( "Republished value to {:?} (nearest without)", @@ -124,5 +124,5 @@ pub use id::NodeId; pub use nat::NatState; // Re-export sha2 for downstream crates. -pub use sha2; pub use node::Node; +pub use sha2; 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 } |