-
Notifications
You must be signed in to change notification settings - Fork 1k
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(core)!: make ConnectionId
s globally unique
#3327
Conversation
Converting to draft until #3318 is merged to prevent accidental merges. |
…ibp2p into 2824-unique-connection-ids
This is ready for review despite being draft. Only #3318 needs to merge first. |
This pull request has merge conflicts. Could you please resolve them @thomaseizinger? 🙏 |
…ibp2p into 2824-unique-connection-ids
/// A "dummy" [`ConnectionId`]. | ||
/// | ||
/// This is primarily useful for creating connection IDs | ||
/// in test environments. There is in general no guarantee | ||
/// that all connection IDs are based on non-negative integers. | ||
pub fn new(id: usize) -> Self { | ||
Self(id) | ||
} | ||
} | ||
|
||
impl std::ops::Add<usize> for ConnectionId { | ||
type Output = Self; | ||
|
||
fn add(self, other: usize) -> Self { | ||
Self(self.0 + other) | ||
/// Really, you should not use this, not even for testing but it is here if you need it. | ||
#[deprecated( | ||
since = "0.42.0", | ||
note = "Don't use this, it will be removed at a later stage again." | ||
)] | ||
pub const DUMMY: ConnectionId = ConnectionId(0); |
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 not very happy about this but I propose to accept this technical debt to be able to move forward with the connection management PR.
Long-term, we would need to re-write the gossipsub and kademlia tests to not manually call lifecycle functions and thus only have Swarm
construct ConnectionId
s.
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.
@libp2p/rust-libp2p-maintainers Please voice your opinion on 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.
Yeah it would be nice if this was possible. Other than that I don't see a better alternative for here.
use std::task::Waker; | ||
use std::time::Duration; | ||
use std::{fmt, io, mem, pin::Pin, task::Context, task::Poll}; | ||
|
||
static NEXT_CONNECTION_ID: AtomicUsize = AtomicUsize::new(1); |
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.
We start IDs at 1
so they can never clash with the DUMMY
one below.
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.
LGTM
/// A "dummy" [`ConnectionId`]. | ||
/// | ||
/// This is primarily useful for creating connection IDs | ||
/// in test environments. There is in general no guarantee | ||
/// that all connection IDs are based on non-negative integers. | ||
pub fn new(id: usize) -> Self { | ||
Self(id) | ||
} | ||
} | ||
|
||
impl std::ops::Add<usize> for ConnectionId { | ||
type Output = Self; | ||
|
||
fn add(self, other: usize) -> Self { | ||
Self(self.0 + other) | ||
/// Really, you should not use this, not even for testing but it is here if you need it. | ||
#[deprecated( | ||
since = "0.42.0", | ||
note = "Don't use this, it will be removed at a later stage again." | ||
)] | ||
pub const DUMMY: ConnectionId = ConnectionId(0); |
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 be nice if this was possible. Other than that I don't see a better alternative for here.
|
||
/// Returns the next available [`ConnectionId`]. | ||
pub(crate) fn next() -> Self { | ||
Self(NEXT_CONNECTION_ID.fetch_add(1, Ordering::SeqCst)) |
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 very elegant.
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.
Credits go to @rkuhn !
This pull request has merge conflicts. Could you please resolve them @thomaseizinger? 🙏 |
Note that this is only really valid once we have libp2p#3327 and the corresponding patch in `libp2p-swarm` `DialOpts`.
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 fine with the technical dept. I suggest moving forward here.
rust-libp2p-head x rust-libp2p-head is failing. Error seems to be:
|
Isn't that the flake that came up a couple of times now? |
yup exactly |
I am tracking removal of the tech-debt in #3371. |
…r` (#3384) The gossipsub tests are calling lifecycle functions of the `NetworkBehaviour` that aren't meant to be called outside of `Swarm`. This already surfaced as a problem in #3327 and it is coming up again in #3254 where `new_handler` gets deprecated. Try to mitigate that by constructing a dummy handler instead. Functionally, there is no difference as in both cases, the given handler has never seen a connection.
…r` (libp2p#3384) The gossipsub tests are calling lifecycle functions of the `NetworkBehaviour` that aren't meant to be called outside of `Swarm`. This already surfaced as a problem in libp2p#3327 and it is coming up again in libp2p#3254 where `new_handler` gets deprecated. Try to mitigate that by constructing a dummy handler instead. Functionally, there is no difference as in both cases, the given handler has never seen a connection.
A bit late to the party, but we (@paritytech) rely on being able to construct Would you be willing to change your opinion on making |
We do too in some tests but my current position is that you shouldn't call those lifecycle functions yourself but instead construct two or more Does that work for you? @mxinden I think we should publish |
please do 🙏
There are over 2000 lines of tests, but I think it may be possible to rewrite them using |
In some tests we need to inject custom handshake and I'm worried it won't be possible with
Overall this change is quite upsetting because we just want to test our state machine built on top of libp2p so spawning libp2p Swarms under it is overcomplicating the issue |
Thank you for sharing. We can re-introduce a public constructor for However, I think these whitebox tests are not a good idea. For example, recently we introduced callbacks for connection management that also involves the behaviour upon pending connections. Is your home-grown test framework calling these correctly? Going through |
Probably not, which is why I agree that we should use a) we want to ship 0.51.1 libp2p, which is currently blocked on this I'd humbly propose to reintroduce |
We are working on that:
Yep, we can do that. I'll send a PR. |
Actually, with how we have now modeled |
In earlier iterations of the design for generic connection management, we removed the `ConnectionId::new` constructor because it would have allowed users to create `ConnectionId`s that are already taken, thus breaking invariants that `NetworkBehaviour`s rely on. Later, we incorporated the creation of `ConnectionId` in `DialOpts` which mitigates this risk altogether. Thus, it is reasonably safe to introduce a public, non-deprecated constructor for `ConnectionId` that can be used for tests. Related #3327 (comment). Pull-Request: #3652.
Description
Instead of offering a public constructor, users are now no longer able to construct
ConnectionId
s at all. They only public API exposed are the derived traits. Internally,ConnectionId
s are monotonically incremented using a static atomic counter, thus no two connections will ever get assigned the same ID.Notes
Extracted out of #3254.
Links to any relevant issues
Open Questions
Change checklist