-
Notifications
You must be signed in to change notification settings - Fork 961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(kad): introduce AsyncBehaviour #5294
base: master
Are you sure you want to change the base?
Conversation
d36c250
to
b6cf27f
Compare
I think it's OK to drop some messages though, they are not that important. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi François, thanks for starting this! I think this is a great idea for kademlia to offer async await friendly primitives, left some notes to help move this forward
/// with an [`Event::OutboundQueryProgressed`] like nothing happen. | ||
/// | ||
/// For more information, see [`Behaviour`]. | ||
pub struct AsyncBehaviour<TStore> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it would probably be great !!
I'm thinking about it but I really don't see how I could implement it since I need to capture the events emitted by the kad::Behaviour
. Do you have an idea ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jxs , I've thought a little bit about this. The only way I see to make a Control
work for the kad::Behaviour
is to have the entire Behaviour
behind an Arc<Mutex<>>
. I don't know if it is a good or bad idea.
Will the "control" semantic become something standard for all the behaviours ? If so why not. But if not, I don't know how it will be understood by the end user to have some behaviours using a control
and others not.
I'd really like to also have your opinion on this @guillaumemichel when you have the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am discovering how Control
works and I think it would make sense in this case. What would be the arguments against using it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jxs , I've thought a little bit about this. The only way I see to make a Control work for the kad::Behaviour is to have the entire Behaviour behind an Arc<Mutex<>>. I don't know if it is a good or bad idea.
I don't think you need an Arc/ Mutex.
You could split the current AsyncBehavior
logic into two parts: the Control part and the NetworkBehavior part, that communicate through an additional mpsc channel (the "command-channel").
Control
would have all the async variants of the kademlia behavior (get_closest_peers_async
,get_providers_async
, etc.).
There, it would create the mpsc channel for the results, and then send the a tuple (Command::GetProviders {..}, mpsc::Sender<AsyncQueryResult>)
through the "command-channel" to theAsyncBehavior
.AsyncBehavior
would wrap the kademlia behavior and implNetworkBehavior
. In itspoll_next
loop it would poll the receiving side of the command-channel, and handle the incoming command by calling the matching function on the wrapped kademlia behavior and storing theSender
in thequery_result_senders
hashmap.poll_next
would also still have the already existing logic for interceptingToSwarm::GenerateEvent
events from the inner behavior and forwarding the results.
Does that make sense? @jxs was that roughly what you had in mind?
48cf62a
to
83480f9
Compare
@jxs like I mentioned in this PR description (in section Notes and open questions), I have used unbounded channels thinking that this could not cause a memory issue more than what there is already since all the sent events are already in memory. Still, I really don't have an opinion on this. |
It would be preferred to use bounded channels so we dont introduce that vector. |
This pull request has merge conflicts. Could you please resolve them @stormshield-frb? 🙏 |
83480f9
to
6433d13
Compare
6433d13
to
e455bee
Compare
Sorry for the late comment, I like the idea of having async updates from the query in an easier manner. I would also prefer to avoid unbounded channels |
// This query was either not triggered by the user or the receiver has been dropped and removed | ||
// so we simply forward it back up to the swarm like nothing happened. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The query could also have been triggered through the non-async methods of the inner kad Behavior that we deref to, right?
/// with an [`Event::OutboundQueryProgressed`] like nothing happen. | ||
/// | ||
/// For more information, see [`Behaviour`]. | ||
pub struct AsyncBehaviour<TStore> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jxs , I've thought a little bit about this. The only way I see to make a Control work for the kad::Behaviour is to have the entire Behaviour behind an Arc<Mutex<>>. I don't know if it is a good or bad idea.
I don't think you need an Arc/ Mutex.
You could split the current AsyncBehavior
logic into two parts: the Control part and the NetworkBehavior part, that communicate through an additional mpsc channel (the "command-channel").
Control
would have all the async variants of the kademlia behavior (get_closest_peers_async
,get_providers_async
, etc.).
There, it would create the mpsc channel for the results, and then send the a tuple (Command::GetProviders {..}, mpsc::Sender<AsyncQueryResult>)
through the "command-channel" to theAsyncBehavior
.AsyncBehavior
would wrap the kademlia behavior and implNetworkBehavior
. In itspoll_next
loop it would poll the receiving side of the command-channel, and handle the incoming command by calling the matching function on the wrapped kademlia behavior and storing theSender
in thequery_result_senders
hashmap.poll_next
would also still have the already existing logic for interceptingToSwarm::GenerateEvent
events from the inner behavior and forwarding the results.
Does that make sense? @jxs was that roughly what you had in mind?
Description
The more things our software is doing, the more it is complicated to track Kademlia queries. We find ourselves needing to have distinct
HashMap
to keep track of every queries we are doing so we can link them back to where and why there were triggered and we needed them. This began to be very messy and that is why we have implemented a wrapper of thekad::Behaviour
with the goal of simplifying the tracking of Kademlia queries.This wrapper is pretty simple and has one method for each of the possible Kademlia queries (
bootstrap
,get_closest_peers
, etc) respectively suffixed_async
(bootstrap_async
,get_closest_peers_async
, etc). Those methods, instead of returning aQueryId
, return a typedUnboundedQueryResultReceiver
that will receive everyEvent::OutboundQueryProgressed
corresponding to theQueryId
. The only purpose of this wrapper is to map anOutboundQueryProgressed
to the corresponding sender and send it.Doing so, it is very easy for the developer to track his queries and keep a correct state in his application specific code.
Notes & open questions
I have chosen to use
UnboundedChannel
considering that the data transmitted is already in memory since this we obtain it when receiving anOutboundQueryProgressed
. That is why I don't think there is a particular risk of running out of memory. If there is, I can rework my wrapper to work with bounded channels.Change checklist