Skip to content

Commit 4db0169

Browse files
author
Threepwood-7
committed
RUST-PAR-017: drive the hourly bucket refresh with the NODE lookup
Wire run_bucket_refresh to DhtNode::refresh_node_lookup instead of the full lookup_nodes_with_class convergence traversal, matching the oracle's per-refresh wire amplitude (one initial KADEMLIA2_REQ, jump-start retries only while silent, stop on first RES -- Search.cpp:194,271-328,373-387). The cadence and gating stay untouched: hourly per-zone big-timer re-arm, one due zone per 10s tick, and the fill gate (RoutingZone.cpp:802-810) all live in the routing table as before. The refresh outcome (responded / reqs_sent / contacts_ingested) is logged so soak diffs keep per-refresh visibility alongside the ed2k_packet_v1 wire dumps.
1 parent 0eaf30c commit 4db0169

1 file changed

Lines changed: 21 additions & 16 deletions

File tree

crates/emulebb-core/src/kad_routing_maintenance.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
//!
33
//! The master keeps its routing tree healthy through two cadenced per-zone
44
//! callbacks driven by the Kad event scheduler:
5-
//! - `OnBigTimer` (~10 s/zone): a per-zone random-target `FindNode` lookup to
6-
//! refill/refresh buckets (`RoutingZone.cpp:802-810,908-916`).
5+
//! - `OnBigTimer` (~10 s/zone): a per-zone random-target NODE lookup (one
6+
//! initial REQ, stop on first RES) to refill/refresh buckets
7+
//! (`RoutingZone.cpp:802-810,908-916`, `Search.cpp:194,373-387`).
78
//! - `OnSmallTimer` (~1 min/leaf): seed expiry windows, drop dead+expired
89
//! contacts, and HELLO-probe the single lowest-quality expired contact per
910
//! leaf to re-verify liveness (`RoutingZone.cpp:852-906`).
@@ -83,10 +84,10 @@ pub(crate) async fn run_kad_routing_maintenance_loop(
8384
}
8485
}
8586

86-
/// Kick off at most one random-target `FindNode` lookup per tick, into the
87-
/// next due refreshable leaf zone, to keep buckets populated (oracle
88-
/// `RandomLookup`). The master fires at most ONE zone's `OnBigTimer` per
89-
/// scheduler pass (`tNow >= m_tBigTimer` + `m_tBigTimer = tNow + SEC(10)`,
87+
/// Kick off at most one random-target NODE lookup per tick, into the next due
88+
/// refreshable leaf zone, to keep buckets populated (oracle `RandomLookup`).
89+
/// The master fires at most ONE zone's `OnBigTimer` per scheduler pass
90+
/// (`tNow >= m_tBigTimer` + `m_tBigTimer = tNow + SEC(10)`,
9091
/// Kademlia.cpp:289-294) and re-arms the fired zone one hour out
9192
/// (`m_tNextBigTimer = tNow + HR2S(1)`); the per-zone re-arm lives in the
9293
/// routing table, so ticks naturally rotate across due zones.
@@ -96,16 +97,20 @@ async fn run_bucket_refresh(dht: &DhtNode) {
9697
};
9798
let dht = dht.clone();
9899
tokio::spawn(async move {
99-
// A bucket-refresh lookup is best-effort maintenance traffic; the
100-
// discovered + answered contacts are folded into the routing table by
101-
// the lookup itself (final closest-set) and by the AddUnfiltered RES
102-
// sink (every answered contact).
103-
if let Err(error) = dht
104-
.lookup_nodes_with_class(&target, RpcWorkClass::Maintenance)
105-
.await
106-
{
107-
tracing::debug!("kad routing refresh lookup failed target={target}: {error}");
108-
}
100+
// Oracle NODE search (CSearchManager::FindNode(uRandom, false),
101+
// RoutingZone.cpp:915): ONE initial KADEMLIA2_REQ, jump-start retries
102+
// only while silent, stop on the first RES (Search.cpp:194,373-387) —
103+
// not a full convergence walk. The answered contacts are folded into
104+
// the routing table by the AddUnfiltered RES sink.
105+
let outcome = dht
106+
.refresh_node_lookup(&target, RpcWorkClass::Maintenance)
107+
.await;
108+
tracing::debug!(
109+
"kad routing refresh (NODE lookup) target={target} responded={} reqs_sent={} contacts_ingested={}",
110+
outcome.responded,
111+
outcome.reqs_sent,
112+
outcome.contacts_ingested
113+
);
109114
});
110115
}
111116

0 commit comments

Comments
 (0)