Skip to content
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(swarm): rename associated types for message passing #3848

Merged
merged 51 commits into from
May 14, 2023

Conversation

tcoratger
Copy link
Contributor

@tcoratger tcoratger commented Apr 28, 2023

Description

Previously, the associated types on NetworkBehaviour and ConnectionHandler carried generic names like InEvent and OutEvent. These names are correct in that OutEvents are passed out and InEvents are passed in but they don't help users understand how these types are used.

In theory, a ConnectionHandler could be used separately from NetworkBehaviours but that is highly unlikely. Thus, we rename these associated types to indicate, where the message is going to be sent to:

  • NetworkBehaviour::OutEvent is renamed to ToSwarm: It describes the message(s) a NetworkBehaviour can emit to the Swarm. The user is going to receive those in SwarmEvent::Behaviour.
  • ConnectionHandler::InEvent is renamed to FromBehaviour: It describes the message(s) a ConnectionHandler can receive from its behaviour via ConnectionHandler::on_swarm_event. The NetworkBehaviour can send it via the ToSwarm::NotifyHandler command.
  • ConnectionHandler::OutEvent is renamed to ToBehaviour: It describes the message(s) a ConnectionHandler can send back to the behaviour via the now also renamed ConnectionHandlerEvent::NotifyBehaviour (previously ConnectionHandlerEvent::Custom)

Resolves: #2854.

Notes & open questions

Change checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • A changelog entry has been made in the appropriate crates

@mergify
Copy link
Contributor

mergify bot commented Apr 28, 2023

This pull request has merge conflicts. Could you please resolve them @tcoratger? 🙏

Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

As someone that is relatively new to the codebase: Does this make things easier to understand? What is your opinion?

core/CHANGELOG.md Outdated Show resolved Hide resolved
protocols/dcutr/src/handler/direct.rs Outdated Show resolved Hide resolved
swarm/CHANGELOG.md Outdated Show resolved Hide resolved
swarm/CHANGELOG.md Outdated Show resolved Hide resolved
@tcoratger
Copy link
Contributor Author

Thank you!

As someone that is relatively new to the codebase: Does this make things easier to understand? What is your opinion?

@thomaseizinger Yes this logic helps me personally to better understand how traits work with these explicit names which in any case help the user. Here are some additional remarks:

  • At the beginning I didn't understand why there is no FromSwarm event in the NetworkBehaviour trait.
  • What was really confusing to me reading these few parts of the code was the fact that there are also InEvent and OutEvent items in many other places in the code for other implementations that have absolutely nothing to do with each other. One example: in the SubstreamHandler trait there also these two items. So maybe we should open other issues to give also explicit name to these other items and avoid generic InEvent and OutEvent usage, what do you think?

@thomaseizinger
Copy link
Contributor

Thank you!

As someone that is relatively new to the codebase: Does this make things easier to understand? What is your opinion?

@thomaseizinger Yes this logic helps me personally to better understand how traits work with these explicit names which in any case help the user. Here are some additional remarks:

  • At the beginning I didn't understand why there is no FromSwarm event in the NetworkBehaviour trait.

There actually is a FromSwarm event but there isn't an associated type in NetworkBehaviour which is probably what you meant :)

The reason is that you can directly call functions on NetworkBehaviour via Swarm::behaviour_mut and thus no message passing is needed to "talk" to the NetworkBehaviour.

  • What was really confusing to me reading these few parts of the code was the fact that there are also InEvent and OutEvent items in many other places in the code for other implementations that have absolutely nothing to do with each other. One example: in the SubstreamHandler trait there also these two items. So maybe we should open other issues to give also explicit name to these other items and avoid generic InEvent and OutEvent usage, what do you think?

Ugh yes. I really want to get rid of all of StreamHandler. That was what I now consider a failed experiment.

@drHuangMHT
Copy link
Contributor

Looking forward to merging this! The naming can be rather confusing.

  • At the beginning I didn't understand why there is no FromSwarm event in the NetworkBehaviour trait.

There actually is a FromSwarm event but there isn't an associated type in NetworkBehaviour which is probably what you meant :)

The reason is that you can directly call functions on NetworkBehaviour via Swarm::behaviour_mut and thus no message passing is needed to "talk" to the NetworkBehaviour.

By the way, is there any plan to run different NetworkBehaviour on different tasks?

@mxinden
Copy link
Member

mxinden commented May 1, 2023

By the way, is there any plan to run different NetworkBehaviour on different tasks?

What would be the motivation to do so? In case it is performance, thus far I have seen no indication that it is a bottleneck in any deployment. (Note absence of evidence does not mean evidence of absence, though when it comes to performance "improvements" I am reluctant of optimization without proof.) Also, in case our NetworkBehaviour hierarchy is a bottleneck, I would prefer first introducing a smarter polling logic, along the lines of FuturesUnordered, only polling the NetworkBehaviour that triggered the wake-up of the task.

@mergify
Copy link
Contributor

mergify bot commented May 2, 2023

This pull request has merge conflicts. Could you please resolve them @tcoratger? 🙏

Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I am really looking forward to merging this, I think it will make understanding our abstractions a lot easier.

Left some minor comments.

swarm-derive/src/lib.rs Show resolved Hide resolved
swarm/CHANGELOG.md Show resolved Hide resolved
swarm/src/handler.rs Outdated Show resolved Hide resolved
libp2p/CHANGELOG.md Outdated Show resolved Hide resolved
Copy link
Contributor

@thomaseizinger thomaseizinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! One question and two suggestions.

if meta.path().is_ident("out_event") {
if meta.path().is_ident("to_swarm") || meta.path().is_ident("out_event") {
if meta.path().is_ident("out_event") {
log::warn!("The 'out_event' key is deprecated, use 'to_swarm' instead",);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this warning going to show up? log is only an API crate and needs a concrete implementation like env_logger to actually print the messages. Does cargo automatically configure a logger when it runs proc-macros?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thomaseizinger I thought so, but you're right it's not, I added env_logger::init(); to put it simply, in this way the warning should be displayed correctly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be displayed correctly.

@tcoratger Have you confirmed that it is actually displayed? :)

I am asking because there is an entire nightly library feature that deals with diagnostics in proc macros and I think it is not as easy as just emitting a log :)

I think we can work around this by emitting code that has deprecation warnings on it. Here is an idea:

  1. If the user users out_event, also generate a trait: trait OutEventAttributeIsDeprecatedAndHasBeenRenamedToToSwarm { }
  2. Also put a #[deprecated] attribute on this trait
  3. Implement the trait for the generated out event

I think this should then show up as a deprecation warning in the user's code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thomaseizinger Can you enlighten me on the subject, I am not very familiar with proc macros, I noticed the following things:

  • When I do a simple println! I thought it was the right approach but in fact the warning is generated only at the first compilation but not at each use of the code, because I imagine that it is a piece of code that runs only at compilation.
  • On the another hand when I use an approach like:
if meta.path().is_ident("out_event") {
  #[deprecated(
      since = "0.33.0",
      note = "The 'out_event' key is deprecated, use 'to_swarm' instead."
  )]
  trait OutEventAttributeIsDeprecatedAndHasBeenRenamedToToSwarm {}

  impl OutEventAttributeIsDeprecatedAndHasBeenRenamedToToSwarm for Meta {}
}

then the deprecation warning appears each time even if we use to_swarm, this is normal because we face a general trait implementation that is deprecated and this is not what we want. Any advice here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't want to implement it for Meta but for the type that the user specifies in out_event.

Also, we need to wrap this in quote! to generate this code for the user.

The idea is, when out_event is used, we emit code that contains deprecated symbols. The compiler then has to compile this code, encounters the #[deprecated] attribute and emits a warning. At least that is the hypothesis, not sure if it works as intended :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't get this to work. For some reason, I am not seeing any warnings that should be produced for the generated code. I swear I saw some of them in the past (which is why we have allow(clippy) attributes in there).

I've found https://github.com/ggwpez/proc-macro-warning but couldn't get it to work. Let's just leave it out and document that it is deprecated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use https://docs.rs/proc-macro-error/1.0.4/proc_macro_error/macro.emit_warning.html then at least the users on nightly will get a warning!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thomaseizinger Yes on my side also I looked a lot and I did not find anything conclusive. You mean doing an implementation like:

if meta.path().is_ident("to_swarm") || meta.path().is_ident("out_event") {
  if meta.path().is_ident("out_event") {
      quote! {
          macro_rules! emit_warning {
              ($span:expr, $($tts:tt)*) => {
                  println!("warning: {}", format_args!($($tts)*));
              };
          }
      };

      let emit_warning_call = quote! {
          emit_warning!(#meta, "The 'out_event' key is deprecated, use 'to_swarm' instead.");
      };

      use quote::ToTokens;
      quote! {
          #emit_warning_call
      }
      .to_token_stream();
  }
....
}

I've tried that a little bit yesterday switching my rustup to nightly and did work properly, what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, that is also a creative idea but not quite what I meant :)

We can just depend on the proc-macro-error crate directly and use their emit_warning! macro! On nightly, that should allow us to issue a diagnostic, similar to how the Rust compiler or clippy issues them.

Copy link
Contributor

@thomaseizinger thomaseizinger May 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exciting news over at proc-macro-warning: ggwpez/proc-macro-warning#2 (comment).

swarm/src/handler.rs Outdated Show resolved Hide resolved
swarm/src/handler.rs Outdated Show resolved Hide resolved
@mergify
Copy link
Contributor

mergify bot commented May 5, 2023

This pull request has merge conflicts. Could you please resolve them @tcoratger? 🙏

Copy link
Member

@mxinden mxinden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like @mxinden to have a look over this too.

I like the new names. Thanks to you two for pushing this forward!

@thomaseizinger
Copy link
Contributor

@tcoratger Would you mind exploring whether the deprecation warning works with what is documented in ggwpez/proc-macro-warning#2?

I think that would make it a lot easier for users to migrate.

swarm-derive/src/lib.rs Outdated Show resolved Hide resolved
@mergify
Copy link
Contributor

mergify bot commented May 12, 2023

This pull request has merge conflicts. Could you please resolve them @tcoratger? 🙏

@tcoratger
Copy link
Contributor Author

@tcoratger Would you mind exploring whether the deprecation warning works with what is documented in ggwpez/proc-macro-warning#2?

I think that would make it a lot easier for users to migrate.

I just pushed an implementation that works:

  • Inside the parse_attributes function, if out_event appears as an attribute then I add a TokenStream deprecation_tokenstream to the output structure.
  • Then I take this TokenStream which contains the warning and I add it in the final_quote of the build_struct function
  • In this way, as soon as out_event appears, I have the warning of deprecation while nothing is displayed when it is not there.

@thomaseizinger Feel free to modify if something doesn't suit you but I think it's a good compromise. We will then be good to merge I think.

@thomaseizinger
Copy link
Contributor

@tcoratger Thank you! I've pushed a unit test that assert the warning we see. I also updated the deprecation message.

@mergify mergify bot merged commit 6e36e8a into libp2p:master May 14, 2023
@mxinden
Copy link
Member

mxinden commented May 15, 2023

Great to see this merged. Thanks for the work. Also neat warnings AND warning tests!

@tcoratger tcoratger deleted the swarm-behaviour-handler branch May 15, 2023 06:27
mergify bot pushed a commit that referenced this pull request May 16, 2023
Rename `ConnectionHandlerEvent::Custom` to `ConnectionHandlerEvent::NotifyBehaviour`.

Related #3848.

Pull-Request: #3955.
umgefahren pushed a commit to umgefahren/rust-libp2p that referenced this pull request Mar 8, 2024
Previously, the associated types on `NetworkBehaviour` and `ConnectionHandler` carried generic names like `InEvent` and `OutEvent`. These names are _correct_ in that `OutEvent`s are passed out and `InEvent`s are passed in but they don't help users understand how these types are used.

In theory, a `ConnectionHandler` could be used separately from `NetworkBehaviour`s but that is highly unlikely. Thus, we rename these associated types to indicate, where the message is going to be sent to:

- `NetworkBehaviour::OutEvent` is renamed to `ToSwarm`: It describes the message(s) a `NetworkBehaviour` can emit to the `Swarm`. The user is going to receive those in `SwarmEvent::Behaviour`.
- `ConnectionHandler::InEvent` is renamed to `FromBehaviour`: It describes the message(s) a `ConnectionHandler` can receive from its behaviour via `ConnectionHandler::on_swarm_event`. The `NetworkBehaviour` can send it via the `ToSwarm::NotifyHandler` command.
- `ConnectionHandler::OutEvent` is renamed to `ToBehaviour`: It describes the message(s) a `ConnectionHandler` can send back to the behaviour via the now also renamed `ConnectionHandlerEvent::NotifyBehaviour` (previously `ConnectionHandlerEvent::Custom`)

Resolves: libp2p#2854.

Pull-Request: libp2p#3848.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

swarm/handler: Rename InEvent and OutEvent to FromBehaviour and ToBehaviour
4 participants