Skip to content

Commit 3a96ebf

Browse files
romanbmxinden
andauthored
More insight into Kademlia queries. (#1567)
* [libp2p-kad] Provide more insight and control into Kademlia queries. More insight: The API allows iterating over the active queries and inspecting their state and execution statistics. More control: The API allows aborting queries prematurely at any time. To that end, API operations that initiate new queries return the query ID and multi-phase queries such as `put_record` retain the query ID across all phases, each phase being executed by a new (internal) query. * Cleanup * Cleanup * Update examples and re-exports. * Incorporate review feedback. * Update CHANGELOG * Update CHANGELOG Co-authored-by: Max Inden <[email protected]>
1 parent c271f6f commit 3a96ebf

File tree

9 files changed

+921
-362
lines changed

9 files changed

+921
-362
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@
2727
has no effect.
2828
[PR 1536](https://github.com/libp2p/rust-libp2p/pull/1536)
2929

30+
- `libp2p-kad`: Provide more insight into, and control of, the execution of
31+
queries. All query results are now wrapped in `KademliaEvent::QueryResult`.
32+
As a side-effect of these changes and for as long as the record storage
33+
API is not asynchronous, local storage errors on `put_record` are reported
34+
synchronously in a `Result`, instead of being reported asynchronously by
35+
an event.
36+
[PR 1567](https://github.com/libp2p/rust-libp2p/pull/1567)
37+
3038
- `libp2p-tcp`: On listeners started with an IPv6 multi-address the socket
3139
option `IPV6_V6ONLY` is set to true. Instead of relying on IPv4-mapped IPv6
3240
address support, two listeners can be started if IPv4 and IPv6 should both

examples/distributed-key-value-store.rs

+30-19
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,15 @@
3232
use async_std::{io, task};
3333
use futures::prelude::*;
3434
use libp2p::kad::record::store::MemoryStore;
35-
use libp2p::kad::{record::Key, Kademlia, KademliaEvent, PutRecordOk, Quorum, Record};
35+
use libp2p::kad::{
36+
record::Key,
37+
Kademlia,
38+
KademliaEvent,
39+
PutRecordOk,
40+
QueryResult,
41+
Quorum,
42+
Record
43+
};
3644
use libp2p::{
3745
NetworkBehaviour,
3846
PeerId,
@@ -76,26 +84,29 @@ fn main() -> Result<(), Box<dyn Error>> {
7684
// Called when `kademlia` produces an event.
7785
fn inject_event(&mut self, message: KademliaEvent) {
7886
match message {
79-
KademliaEvent::GetRecordResult(Ok(result)) => {
80-
for Record { key, value, .. } in result.records {
87+
KademliaEvent::QueryResult { result, .. } => match result {
88+
QueryResult::GetRecord(Ok(ok)) => {
89+
for Record { key, value, .. } in ok.records {
90+
println!(
91+
"Got record {:?} {:?}",
92+
std::str::from_utf8(key.as_ref()).unwrap(),
93+
std::str::from_utf8(&value).unwrap(),
94+
);
95+
}
96+
}
97+
QueryResult::GetRecord(Err(err)) => {
98+
eprintln!("Failed to get record: {:?}", err);
99+
}
100+
QueryResult::PutRecord(Ok(PutRecordOk { key })) => {
81101
println!(
82-
"Got record {:?} {:?}",
83-
std::str::from_utf8(key.as_ref()).unwrap(),
84-
std::str::from_utf8(&value).unwrap(),
102+
"Successfully put record {:?}",
103+
std::str::from_utf8(key.as_ref()).unwrap()
85104
);
86105
}
87-
}
88-
KademliaEvent::GetRecordResult(Err(err)) => {
89-
eprintln!("Failed to get record: {:?}", err);
90-
}
91-
KademliaEvent::PutRecordResult(Ok(PutRecordOk { key })) => {
92-
println!(
93-
"Successfully put record {:?}",
94-
std::str::from_utf8(key.as_ref()).unwrap()
95-
);
96-
}
97-
KademliaEvent::PutRecordResult(Err(err)) => {
98-
eprintln!("Failed to put record: {:?}", err);
106+
QueryResult::PutRecord(Err(err)) => {
107+
eprintln!("Failed to put record: {:?}", err);
108+
}
109+
_ => {}
99110
}
100111
_ => {}
101112
}
@@ -188,7 +199,7 @@ fn handle_input_line(kademlia: &mut Kademlia<MemoryStore>, line: String) {
188199
publisher: None,
189200
expires: None,
190201
};
191-
kademlia.put_record(record, Quorum::One);
202+
kademlia.put_record(record, Quorum::One).expect("Failed to store record locally.");
192203
}
193204
_ => {
194205
eprintln!("expected GET or PUT");

examples/ipfs-kad.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ use libp2p::{
3030
identity,
3131
build_development_transport
3232
};
33-
use libp2p::kad::{Kademlia, KademliaConfig, KademliaEvent, GetClosestPeersError};
33+
use libp2p::kad::{
34+
Kademlia,
35+
KademliaConfig,
36+
KademliaEvent,
37+
GetClosestPeersError,
38+
QueryResult,
39+
};
3440
use libp2p::kad::record::store::MemoryStore;
3541
use std::{env, error::Error, time::Duration};
3642

@@ -91,7 +97,10 @@ fn main() -> Result<(), Box<dyn Error>> {
9197
task::block_on(async move {
9298
loop {
9399
let event = swarm.next().await;
94-
if let KademliaEvent::GetClosestPeersResult(result) = event {
100+
if let KademliaEvent::QueryResult {
101+
result: QueryResult::GetClosestPeers(result),
102+
..
103+
} = event {
95104
match result {
96105
Ok(ok) =>
97106
if !ok.peers.is_empty() {

0 commit comments

Comments
 (0)