Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Change DispatchInterceptor API #85

Merged
merged 3 commits into from
Feb 16, 2021
Merged

Change DispatchInterceptor API #85

merged 3 commits into from
Feb 16, 2021

Conversation

bernardnormier
Copy link
Member

This PR changes the DispatchInterceptor API to be more like ASP.NET's request delegate API.

See https://www.stevejgordon.co.uk/how-is-the-asp-net-core-middleware-pipeline-built

Just like in ASP.NET, a dispatch interceptor is now a Func<Dispatcher, Dispatcher> while a "simple" dispatch interceptor (with a parameterless next) has a more complicated Func definition.

/// <returns>The <c>adapter</c> argument.</returns>
public static ObjectAdapter Use(
this ObjectAdapter adapter,
Func<IncomingRequestFrame, Current, Func<ValueTask<OutgoingResponseFrame>>, CancellationToken, ValueTask<OutgoingResponseFrame>> dispatchInterceptor) =>
Copy link
Contributor

Choose a reason for hiding this comment

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

The signature of this delegate is a bit difficult to understand. We could consider adding delegate definitions instead:

delegate ValueTask<OutgoingResponseFrame> NextDispatcher();

delegate ValueTask<OutgoingResponseFrame> SimpleDispatcher(IncomingRequestFrame frame, Current current, NextDispatcher next, CancellationToken cancel);

Or perhaps just define NextDispatcher and use Func<IncomingRequestFrame, Current, NextDispatcher, CancellationToken, ValueTask<OutgoingResponseFrame>> in the Use signature.

Copy link
Member

Choose a reason for hiding this comment

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

Agree will be good to simplify this signature

Copy link
Member Author

Choose a reason for hiding this comment

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

Here again it's like ASP.NET, where they don't define a delegate for the simple middleware registration:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.useextensions.use?view=aspnetcore-5.0

Copy link
Member

@pepone pepone left a comment

Choose a reason for hiding this comment

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

Looks good!

DispatchInterceptors = ImmutableList.Create<DispatchInterceptor>(
(request, current, next, cancel) => throw new ArgumentException())
};
await using var adapter = new ObjectAdapter(communicator);
Copy link
Member

Choose a reason for hiding this comment

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

using System.Collections.Immutable; is no longer required in this test

Copy link
Member

@externl externl left a comment

Choose a reason for hiding this comment

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

Looks good. I find "simple" and "regular" somewhat confusing.

Comment on lines +10 to +11
/// <summary>Adds a simple dispatch interceptor to the request dispatch pipeline. This is an adapter for <see
/// cref="ObjectAdapter.Use"/>.</summary>
Copy link
Member

Choose a reason for hiding this comment

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

  • Is the user ever expected to use the non-so-simple ObjectAdapter.Use directly or only ever use this extension method?

  • Why does this need to be an extension and not just defined in the ObejctAdapter class directly?

  • We should clarify this comment.

This is an adapter for <see...

Copy link
Contributor

Choose a reason for hiding this comment

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

My understanding is that extensions are supposed to be used to extend classes from some dependant assembly (e.g.: TaskExtensions). So here this method could indeed directly go on the adapter class instead. It will be easier to find when browsing the documentation.

Copy link
Member Author

Choose a reason for hiding this comment

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

My understanding is that extensions are supposed to be used to extend classes from some dependant assembly (e.g.: TaskExtensions). So here this method could indeed directly go on the adapter class instead. It will be easier to find when browsing the documentation.

I don't believe this is correct.

Extension methods (and functions found through ADL in C++) are preferred for code that does not need private / internal access to the class implementation. It doesn't matter where it is.

In this particular Use case, it's just like ASP.NET and its UseExtensions class that provides a simple "middleware" registration:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.useextensions.use?view=aspnetcore-5.0

Note that both UseExtensions and IApplicationBuilder are in the same assembly (Microsoft.AspNetCore.Http.Abstractions.dll).

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, looks like ASP.NET loves extensions :). From the Socket API guys, it looks like they'd rather get rid of extensions according to this bug dotnet/runtime#33417

I find it simpler to not have extensions but if it's not recommended... ok.

Copy link
Member

Choose a reason for hiding this comment

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

I also think it's simpler to not have extensions.

Copy link
Member

Choose a reason for hiding this comment

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

the fact that this is implemented as an extension ensures this is not coupled to the private implementation as extensions are using the public API, here it can use internals because it is in the same assembly.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see why we need to expose this non-coupling detail to the user. He doesn't care and I don't think we should care that much about it, at least not to the point of spreading the API in many extensions like ASP.NET does.

Copy link
Member Author

Choose a reason for hiding this comment

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

I like extensions and also "free" C++ functions found through ADL. However, we don't need an extension class per method like ASP.NET ... I agree that's overkill.

@bernardnormier bernardnormier merged commit ed8bf7a into icerpc:main Feb 16, 2021
@bernardnormier bernardnormier deleted the request-delegate branch April 11, 2021 19:54
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants