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: make it possible to override method name in subscriptions #568

Merged
merged 23 commits into from
Nov 19, 2021

Conversation

niklasad1
Copy link
Member

@niklasad1 niklasad1 commented Nov 17, 2021

Fixes paritytech/substrate#8783 (comment) to be compatible with current the behavior on substrate master to make it possible to configure custom method name for subscriptions (i.e, not the same as subscription method name) to avoid breakage for libraries that can't distinguish between ordinary notifications and subscription notifications

Example:

/// Use `override` as method name in the subscription notif
#[subscription(name = "subscribe_method" => "override", item = u32)]
fn sub_with_override(&self) -> RpcResult<()>;


/// Use default `subscription name` as method name in the subscription notif
#[subscription(name = "subscribeHello", item = u32)]
fn sub_with_override(&self) -> RpcResult<()>;

@niklasad1 niklasad1 changed the title feat: override notif method name feat: override method name in subscription notif Nov 17, 2021
@dvdplm
Copy link
Contributor

dvdplm commented Nov 18, 2021

Thoughts about this such as naming?!

I absolutely hate it. 😆

I would like to not have to support this, or at the very least understand why we need it.

Copy link
Contributor

@maciejhirsz maciejhirsz left a comment

Choose a reason for hiding this comment

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

Some open questions, but looks good to me otherwise!

}

impl<Context> RpcModule<Context> {
/// Create a new module with a given shared `Context`.
pub fn new(ctx: Context) -> Self {
Self { ctx: Arc::new(ctx), methods: Default::default() }
Self { ctx: Arc::new(ctx), methods: Default::default(), notif_overrides: SubscriptionNotifOverride::default() }
Copy link
Contributor

@maciejhirsz maciejhirsz Nov 18, 2021

Choose a reason for hiding this comment

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

This doesn't really prevent us from having the same notification name in two different modules (the set is local to the instance and is thrown away the moment you turn it into Methods).

If we can't easily guarantee that notification names are unique, and there isn't really much of a point in checking that they are in the server (notifications will be sent regardless, and we rely on sub id more than name on the client anyway), I think it might actually be better to drop the check altogether.

Copy link
Member Author

Choose a reason for hiding this comment

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

ty, can't we handle it in RpcModule::merge?

Copy link
Contributor

Choose a reason for hiding this comment

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

You can, but you'd have to move the hashset inside Methods because that's what merge operates on.

Copy link
Member Author

Choose a reason for hiding this comment

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

let's keep it simple I removed all of this but kept the check in the proc macros for now, ok?

Copy link
Contributor

Choose a reason for hiding this comment

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

Good pt @maciejhirsz. I'm ok making this a "sharp" feature, but we need to document it properly. "NOTE: the author is expected to ensure the uniqueness of the override across all RpcModules used on the server." or some such.

Copy link
Member Author

@niklasad1 niklasad1 Nov 19, 2021

Choose a reason for hiding this comment

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

Note, we have a check for this in the proc macros where each trait ensures uniqueness for each name.

Do you want me to remove it be to somewhat consistent?

utils/src/server/rpc_module.rs Outdated Show resolved Hide resolved
@niklasad1 niklasad1 changed the title feat: override method name in subscription notif feat: make it possible to override method name in subscriptions Nov 18, 2021
@niklasad1 niklasad1 requested review from dvdplm and TarikGul November 18, 2021 22:09
Copy link
Contributor

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

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

Sorry for being a trouble maker wrt naming; I'm concerned about mixing up the concept of "notification" with the spec's definition.
We need to update the macro docs with a clear explanation of what this change is and when it's useful (stressing it should never be used for new code; people should use the subscription ID to track things).

proc-macros/src/render_server.rs Outdated Show resolved Hide resolved
proc-macros/src/render_server.rs Outdated Show resolved Hide resolved
proc-macros/src/render_server.rs Outdated Show resolved Hide resolved
proc-macros/src/render_server.rs Outdated Show resolved Hide resolved
proc-macros/src/rpc_macro.rs Outdated Show resolved Hide resolved
proc-macros/src/rpc_macro.rs Outdated Show resolved Hide resolved
proc-macros/src/rpc_macro.rs Outdated Show resolved Hide resolved
proc-macros/tests/ui/correct/basic.rs Outdated Show resolved Hide resolved
utils/src/server/rpc_module.rs Outdated Show resolved Hide resolved
@@ -312,7 +312,7 @@ async fn multiple_blocking_calls_overlap() {

#[tokio::test]
async fn subscriptions_do_not_work_for_http_servers() {
let htserver = HttpServerBuilder::default().build("127.0.0.1:0".parse().unwrap()).unwrap();
let htserver = HttpServerBuilder::default().build("127.0.0.1:0").unwrap();
Copy link
Member

Choose a reason for hiding this comment

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

👍

Copy link
Member

@TarikGul TarikGul left a comment

Choose a reason for hiding this comment

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

lgtm, fwiw I agree with David that some clearer naming could be a +1.

@maciejhirsz
Copy link
Contributor

maciejhirsz commented Nov 19, 2021

@dvdplm

I'm concerned about mixing up the concept of "notification" with the spec's definition.

So I did re-read things to make sure I have it right. There is nothing wrong with us using the term "Notification", and the spec explicitly allows / remains agnostic about server acting as a client:

The Client is defined as the origin of Request objects and the handler of Response objects.
The Server is defined as the origin of Response objects and the handler of Request objects.

One implementation of this specification could easily fill both of those roles, even at the same time, to other different clients or the same client. This specification does not address that layer of complexity.

We are using JSON-RPC notifications in a very specific fashion, but I don't see how that stops them from being notifications. TCP packets don't stop being TCP packets if they carry HTTP paylods. Everything we do with subscriptions is fully compliant with the JSON-RPC spec, we don't change anything about the spec, nor do we add anything to the spec, subscriptions are just a meta protocol bolted on top of it.

@niklasad1
Copy link
Member Author

niklasad1 commented Nov 19, 2021

lgtm, fwiw I agree with David that some clearer naming could be a +1.

Technically the naming is accurate because subscriptions is a notification according the the spec which has a special field subscription passed in the params where the subscription ID goes but subscription payload works too if that's more understandable....

Good to get your review still to get some eyes outside the jsonrpc bubble :)

@TarikGul
Copy link
Member

Technically the naming is accurate because subscriptions is a notification according the the spec which has a special field subscription passed in the params where the subscription ID goes but subscription payload works too if that's more understandable....

@niklasad1 Just read @maciejhirsz comments as well. Totally understand where the convention is coming from. Happy to see it kept as is as well. With a third glance over I can see it makes sense to have notif. :)

@dvdplm
Copy link
Contributor

dvdplm commented Nov 19, 2021

@maciejhirsz You are right and I am wrong; the spec is indeed agnostic just the way you quote it. My concern was we'd introduce a naming convention that conflicts with a specific meaning defined in the spec. Instead there is no such conflict.

I'll go over my naming suggestions again and see if I know feel differently. Ty!

proc-macros/src/render_server.rs Outdated Show resolved Hide resolved
proc-macros/src/render_server.rs Outdated Show resolved Hide resolved
proc-macros/src/rpc_macro.rs Outdated Show resolved Hide resolved
@@ -31,6 +31,11 @@ pub trait Rpc {

#[subscription(name = "echo", aliases = ["ECHO"], item = u32, unsubscribe_aliases = ["NotInterested", "listenNoMore"])]
fn sub_with_params(&self, val: u32) -> RpcResult<()>;

// This will send data to subscribers with the `method` field in the JSON payload set to `foo_subscribe_override`
// because it's in the `foo` namespace.
Copy link
Contributor

Choose a reason for hiding this comment

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

oh that's a good point, let's not forget to include that in the docs for the macro.

utils/src/server/rpc_module.rs Outdated Show resolved Hide resolved
utils/src/server/rpc_module.rs Outdated Show resolved Hide resolved
@niklasad1 niklasad1 merged commit 9c6fd4b into master Nov 19, 2021
@niklasad1 niklasad1 deleted the na-override-notif-method-name branch November 19, 2021 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants