-
Notifications
You must be signed in to change notification settings - Fork 959
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
Add addresses field for closing listeners #1485
Conversation
Our code isn't formatted with |
Oh, that would explain the indentation for your Will change my editor setup to match you project and submit non-draft PR :) Thanks @tomaka |
I see you guys use |
Add an addresses field to the ListenersEvent and the ListenerClosed to hold the addresses of a listener that has just closed. When we return a ListenerClosed network event loop over the addresses and call inject_expired_listen_address on each one. Fixes: libp2p#1482
FTR, I did not configure my editor to use |
I'm not sure how to proceed with the CI integration test failure. |
Researching further, Discussed here: https://www.reddit.com/r/rust/comments/9jl6a9/pro_tip_if_you_use_cargo_fmtrustfmt_use_a/ |
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.
This looks good to me, but I would like @tomaka or some other maintainer to take another look.
Retriggered the tests. All green now. |
core/src/connection/listeners.rs
Outdated
@@ -148,6 +148,8 @@ where | |||
Closed { | |||
/// The ID of the listener that closed. | |||
listener_id: ListenerId, | |||
/// The addresses that the listener was listening on. | |||
addresses: SmallVec<[Multiaddr; 4]>, |
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.
This is a nit, but I'd rather go with Vec
in order to not expose a third-party dependency in our API.
Alternatively, a custom iterator type that wraps around smallvec::IntoIter
would work as well.
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.
No worries, will fix and re-spin. Thanks.
core/src/connection/listeners.rs
Outdated
@@ -283,12 +285,14 @@ where | |||
Poll::Ready(None) => { | |||
return Poll::Ready(ListenersEvent::Closed { | |||
listener_id: *listener_project.id, | |||
addresses: listener.addresses.clone(), |
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.
Since we're destroying the listener, you don't need to clone.
addresses: listener.addresses.clone(), | |
addresses: mem::replace(listener.addresses, SmallVec::new()), |
(or, for Vec
, listener.addresses.drain(..).collect()
)
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 went with a Vec
and used the SmallVec
method to_vec()
for the conversion.
core/src/network/event.rs
Outdated
@@ -55,6 +56,8 @@ where | |||
ListenerClosed { | |||
/// The listener ID that closed. | |||
listener_id: ListenerId, | |||
/// The addresses that the listener was listening on. | |||
addresses: SmallVec<[Multiaddr; 4]>, |
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.
Same remark
In order to not expose a third party dependency in our API use a `Vec` type for the addresses list instead of a `SmallVec`.
Whats the rust-libp2p projects protocol on squashing/rebasing of PRs? Would you prefer the second commit (added after review) to be squashed into the first or left as it is? Thanks for the reviews. |
@tcharding no action required from your side. We use Github's Squash and merge feature. |
core/src/connection/listeners.rs
Outdated
@@ -283,12 +285,14 @@ where | |||
Poll::Ready(None) => { | |||
return Poll::Ready(ListenersEvent::Closed { | |||
listener_id: *listener_project.id, | |||
addresses: listener.addresses.to_vec(), |
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.
It's still cloning the content of the container, which is what I was trying to avoid with my suggestion.
addresses: listener.addresses.to_vec(), | |
addresses: listener.addresses.drain(..).collect(), |
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.
Its hard to get good help :) I did try your suggestion but it didn't seem to work. Will explore further. Thanks
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've had a bit more of a play with it. Please correct me if I'm wrong but it seems we cannot get a mutable reference to listener
(needed if we want to drain addresses
) because we have already taken a mutable reference. We would need the following code to be possible (I think, open to correction):
/// Provides an API similar to `Stream`, except that it cannot end.
pub fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<ListenersEvent<TTrans>> {
let mut remaining = self.listeners.len();
while let Some(mut listener) = self.listeners.pop_back() {
let mut listener_project = listener.as_mut().project();
let mut addresses = listener.as_mut().addresses;
This is clearly not possible. Am I missing something, is there another way to do this?
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.
Ah sorry, you just have to use listener_project
addresses: listener.addresses.to_vec(), | |
addresses: listener_project.addresses.drain(..).collect(), |
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.
Cool, thanks. I learned (a little bit) about pin_project, seems I still have a lot to learn about pinning :) Thanks for your patient revies @tomaka. One final thing, just to make sure, are you happy with the remaining usage of SmallVec
in connection/listener.rs
introduced in this PR?
Closed {
/// The ID of the listener that closed.
listener_id: ListenerId,
+ /// The addresses that the listener was listening on.
+ addresses: SmallVec<[Multiaddr; 4]>,
And, since I'm new and its good to start on the right foot; can you please confirm that the typical pre-PR-push tasks you would expect to pass are only:
cargo build
cargo test
(i.e., no clippy, no e2e tests etc)
Thanks,
Tobin.
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.
are you happy with the remaining usage of SmallVec in connection/listener.rs introduced in this PR?
Ah! No, I missed that. Please turn that into a Vec
as well.
There are more tests than cargo test
, but running cargo test
locally is good enough before opening a PR.
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.
Done, I think we are getting dangerously close to a mergeable PR :)
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.
Wait. Please revert that last change. Having SmallVec
in a private field is good.
(you mentioned "introduced in this PR", but your PR didn't touch this.)
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.
Oh boy, you are right. I hope you meant 'revert' figuratively, I removed last patch and force pushed. Thanks for your patience.
We would like to avoid clones where possible for efficiency reasons. When returning a `ListenersEvent::Closed` we are already consuming the listener (by way of a pin projection). We can therefore use a consuming iterator instead of cloning. Use `drain(..).collect()` instead of clone to consume the addresses when returning a `ListenersEvent::Closed`.
92d8612
to
2867fe8
Compare
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.
Should be good for merge after that
for addr in addresses.iter() { | ||
this.behaviour.inject_expired_listen_addr(addr); | ||
} |
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.
One last change: could you move this above inject_listener_closed
?
The listener and its addresses technically expire at the same time, but since here we have to pick an order, it makes more sense that the addresses expire before.
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.
No worries, done!
The listener and its addresses technically expire at the same time, but since here we have to pick an order, it makes more sense that the addresses expire first.
This reverts commit 7bf5266
We would like to be able expire addresses when a listener closes.
Add an
addresses
field to theListenersEvent
and theListenerClosed
to hold the addresses of a listener that has just closed. When we return aListenerClosed
network event, loop over the addresses and callinject_expired_listen_address()
on each one.Fixes: #1482