-
-
Notifications
You must be signed in to change notification settings - Fork 916
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 IConfigureExecution #3121
Add IConfigureExecution #3121
Conversation
/// <remarks> | ||
/// <see cref="ExecutionOptions.RequestServices"/> can be used within the delegate to access the service provider for this execution. | ||
/// </remarks> | ||
public static IGraphQLBuilder ConfigureExecution(this IGraphQLBuilder builder, Func<Func<ExecutionOptions, Task<ExecutionResult>>, ExecutionOptions, Task<ExecutionResult>> action) |
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.
public static IGraphQLBuilder ConfigureExecution(this IGraphQLBuilder builder, Func<Func<ExecutionOptions, Task<ExecutionResult>>, ExecutionOptions, Task<ExecutionResult>> action) | |
public static IGraphQLBuilder ConfigureExecution(this IGraphQLBuilder builder, Func<ExecutionOptions, ExecutionDelegate, Task<ExecutionResult>> action) |
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.
@Shane32 Compare this with
/// <summary>
/// Adds a middleware delegate defined in-line to the application's request pipeline.
/// If you aren't calling the next function, use <see cref="RunExtensions.Run(IApplicationBuilder, RequestDelegate)"/> instead.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> instance.</param>
/// <param name="middleware">A function that handles the request and calls the given next function.</param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, RequestDelegate, Task> middleware)
{
return app.Use(next => context => middleware(context, next));
}
ConfigureExecution
<-> Use
IGraphQLBuilder
<-> IApplicationBuilder
action
<-> middleware
ExecutionOptions
<-> HttpContext
ExecutionDelegate
<-> RequestDelegate
Task<ExecutionResult>
<-> Task
Suggestions from me:
- Maybe rename method name and argument name to align with ASP.NET stuff? I'm 50/50.
- Add other overloads from ASP.NET:
public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware)
and
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
- Add docs mentioning that GraphQL.NET document execution pipeline follows the very same design as ASP.NET http request pipeline.
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.
ASP.NET Core docs discourage the use of the first overload you suggested, so I would suggest we simply skip that one. The second overload requires a change in design to implement: it's an application builder, so instead of IConfigureExecution
we would have IExecutionBuilder
(or something named like that), where the interface method is ExecutionDelegate BuildExecution(ExecutionDelegate next)
.
Do you think it's worth it? Ideally, the start of the execution would initialize an ExecutionContext
(similar to HttpContext
), and everything - document parsing, document caching, document listeners, document validation, and even the execution strategy selection and execution - would be based on installable middleware, similar to ASP.NET Core. However, we would need a place to configure the builder pipeline in case of branches, as pulling a list from DI would be insufficient. I feel like that's too big of a change to tackle for v5, although it is worth considering for v6.
I would suggest we leave this a bit simpler for v5, tackling the ability to add middleware around the existing document executer, and if we wish to rewrite the execution pipeline from scratch, we do so for v6.
What do you think? If you still think we should make the changes you proposed, fine, but can you be a little more specific as to the interface definition that should be added, and builder methods to be added?
Example interface:
// now:
public interface IConfigureExecution
{
Task<ExecutionResult> ExecuteAsync(ExecutionOptions options, ExecutionDelegate next);
}
public static IGraphQLBuilder ConfigureExecution(this IGraphQLBuilder builder, Func<ExecutionOptions, ExecutionDelegate, Task<ExecutionResult>> action);
// suggestion???
public interface IExecutionBuilder
{
ExecutionDelegate Build(ExecutionDelegate next);
}
public static IGraphQLBuilder ConfigureExecution(this IGraphQLBuilder builder, Func<ExecutionOptions, ExecutionDelegate, Task<ExecutionResult>> middleware);
public static IGraphQLBuilder ConfigureExecution(this IGraphQLBuilder builder, Func<ExecutionDelegate, ExecutionDelegate> middleware);
Again, personally I think I'd just leave it as shown in this PR for v5.
One other option: we could leave the interface as-is and add the extra configuration method like shown below, but I don't like it - it seems like a hack.
public static IGraphQLBuilder ConfigureExecution(this IGraphQLBuilder builder, Func<ExecutionDelegate, ExecutionDelegate> middleware)
{
builder.Services.Register<IConfigureExecution>(new ConfigureExecution((options, next) => middleware(next)(options)));
return builder;
}
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.
@sungam3r bump - if we answer this one question, we may be able to merge this now or shortly.
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 agree to postpone redesign to v6.
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.
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 very-very useful feature and at the same time it is quite simple to implement and support. 👍
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
@sungam3r Thanks for the comments. They all look good. I bumped the apollo tracing method to a separate PR so we can discuss the best way to implement that. Also see above for my comments on |
Only this one left - #3121 (comment) |
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
Co-authored-by: Ivan Maximov <sungam3r@yandex.ru>
Whoops; missed that. Please see reply above. |
Codecov Report
@@ Coverage Diff @@
## master #3121 +/- ##
==========================================
- Coverage 84.38% 84.32% -0.07%
==========================================
Files 362 363 +1
Lines 15900 15944 +44
Branches 2583 2580 -3
==========================================
+ Hits 13417 13444 +27
- Misses 1867 1883 +16
- Partials 616 617 +1
Continue to review full report at Codecov.
|
This allows for 'middleware' or 'plugin' behavior to the document executer. This will be immediately useful for appending Apollo Tracing results, as well as implementation of Automatic Persisted Queries.
IConfigureExecution
works similarly to "Apollo Link"s as seen below:Within our library, these components are implemented similarly to this:
IDocumentExecuter
IConfigureExecution
GraphQLHttpMiddleware
(In the diagram above, Apollo Links are shown in the context of a client, but same design applies to a server.)