Skip to content

Commit

Permalink
Disable batching by default. (#5776)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Feb 5, 2023
1 parent 8dd8d39 commit 6f6e0e9
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ public sealed class GraphQLServerOptions
/// Defines if the GraphQL schema SDL can be downloaded.
/// </summary>
public bool EnableSchemaRequests { get; set; } = true;

/// <summary>
/// Defines if request batching is enabled.
/// </summary>
public bool EnableBatching { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ protected async Task HandleRequestAsync(HttpContext context)
string? operationNames = context.Request.Query[_batchOperations];

if (!string.IsNullOrEmpty(operationNames) &&
TryParseOperations(operationNames, out var ops))
TryParseOperations(operationNames, out var ops) &&
(context.GetGraphQLServerOptions()?.EnableGetRequests ?? false))
{
result = await ExecuteOperationBatchAsync(
context,
Expand Down Expand Up @@ -210,13 +211,23 @@ protected async Task HandleRequestAsync(HttpContext context)
// we need to execute a request batch where we need to execute multiple
// fully specified GraphQL requests at once.
default:
result = await ExecuteBatchAsync(
context,
requestExecutor,
requestInterceptor,
DiagnosticEvents,
requests,
requestFlags);
if (context.GetGraphQLServerOptions()?.EnableGetRequests ?? false)
{
result = await ExecuteBatchAsync(
context,
requestExecutor,
requestInterceptor,
DiagnosticEvents,
requests,
requestFlags);
}
else
{
var error = errorHandler.Handle(ErrorHelper.InvalidRequest());
statusCode = HttpStatusCode.BadRequest;
result = QueryResultBuilder.CreateError(error);
DiagnosticEvents.HttpRequestError(context, error);
}
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,19 @@ protected virtual TestServer CreateStarWarsServer(
.UseEndpoints(
endpoints =>
{
var builder = endpoints.MapGraphQL(pattern);
var builder = endpoints.MapGraphQL(pattern)
.WithOptions(new GraphQLServerOptions
{
EnableBatching = true
});

configureConventions?.Invoke(builder);
endpoints.MapGraphQL("/evict", "evict");
endpoints.MapGraphQL("/arguments", "arguments");
endpoints.MapGraphQL("/upload", "upload");
endpoints.MapGraphQL("/starwars", "StarWars");
endpoints.MapGraphQL("/test", "test");
endpoints.MapGraphQL("/batching");
}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,82 @@ query getHuman {
result.MatchSnapshot();
}

[Fact]
public async Task BatchRequest_GetHero_And_GetHuman_MultiPart_Batching_Disabled()
{
// arrange
var server = CreateStarWarsServer(
configureServices: sp => sp.AddHttpResponseFormatter());

// act
var response =
await server.SendPostRequestAsync(
JsonConvert.SerializeObject(
new List<ClientQueryRequest>
{
new ClientQueryRequest
{
Query = @"
query getHero {
hero(episode: EMPIRE) {
id @export
}
}"
},
new ClientQueryRequest
{
Query = @"
query getHuman {
human(id: $id) {
name
}
}"
}
}),
path: "/batching");

if (response.StatusCode == HttpStatusCode.NotFound)
{
throw new Exception("GraphQL endpoint not found.");
}

var result = await response.Content.ReadAsStringAsync();

// assert
result.MatchSnapshot();
}

[Fact]
public async Task OperationBatchRequest_GetHero_And_GetHuman_Batching_Disabled()
{
// arrange
var server = CreateStarWarsServer();

// act
var result =
await server.PostOperationAsync(
new ClientQueryRequest
{
Query =
@"query getHero {
hero(episode: EMPIRE) {
id @export
}
}
query getHuman {
human(id: $id) {
name
}
}"
},
"getHero, getHuman",
path: "/batching");

// assert
result.MatchSnapshot();
}

[Fact]
public async Task OperationBatchRequest_Invalid_BatchingParameter_1()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"errors":[{"message":"Invalid GraphQL Request.","extensions":{"code":"HC0009"}}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"ContentType": "application/graphql-response+json; charset=utf-8",
"StatusCode": "BadRequest",
"Data": null,
"Errors": [
{
"message": "Invalid GraphQL Request.",
"extensions": {
"code": "HC0009"
}
}
],
"Extensions": null
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public Task Send_Connect_Accept()
// no error
});

[Fact]
[Fact(Skip = "This test is flaky. We need to fix it.")]
public Task Subscribe_ReceiveDataOnMutation()
{
var snapshot = new Snapshot();
Expand Down Expand Up @@ -120,7 +120,7 @@ public Task Subscribe_Disconnect()
});
}

[Fact]
[Fact(Skip = "This test is flaky. We need to fix it.")]
public Task Send_Subscribe_SyntaxError()
{
var snapshot = new Snapshot();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using HotChocolate.Execution;
using HotChocolate.Types;
using Snapshooter.Xunit;
using Xunit;
Expand All @@ -21,7 +22,20 @@ public void Copy_Options()
UseXmlDocumentation = false,
DefaultBindingBehavior = BindingBehavior.Explicit,
FieldMiddleware = FieldMiddlewareApplication.AllFields,
PreserveSyntaxNodes = true
PreserveSyntaxNodes = true,
StrictRuntimeTypeValidation = true,
MaxAllowedNodeBatchSize = 20,
EnableOneOf = true,
DefaultDirectiveVisibility = DirectiveVisibility.Public,
EnableDirectiveIntrospection = true,
DefaultFieldBindingFlags = FieldBindingFlags.InstanceAndStatic,
ValidatePipelineOrder = true,
EnableDefer = true,
EnableStream = true,
EnableFlagEnums = true,
EnsureAllNodesCanBeResolved = true,
RemoveUnreachableTypes = true,
DefaultResolverStrategy = ExecutionStrategy.Serial
};

// act
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@
"ResolveXmlDocumentationFileName": null,
"SortFieldsByName": true,
"PreserveSyntaxNodes": true,
"RemoveUnreachableTypes": false,
"RemoveUnreachableTypes": true,
"DefaultBindingBehavior": "Explicit",
"DefaultFieldBindingFlags": "Instance",
"DefaultFieldBindingFlags": "InstanceAndStatic",
"FieldMiddleware": "AllFields",
"EnableDirectiveIntrospection": false,
"EnableDirectiveIntrospection": true,
"DefaultDirectiveVisibility": "Public",
"DefaultResolverStrategy": "Parallel",
"DefaultResolverStrategy": "Serial",
"ValidatePipelineOrder": true,
"StrictRuntimeTypeValidation": false,
"StrictRuntimeTypeValidation": true,
"DefaultIsOfTypeCheck": null,
"EnableOneOf": false,
"EnsureAllNodesCanBeResolved": false,
"EnableFlagEnums": false,
"EnableDefer": false,
"EnableStream": false
"EnableOneOf": true,
"EnsureAllNodesCanBeResolved": true,
"EnableFlagEnums": true,
"EnableDefer": true,
"EnableStream": true,
"MaxAllowedNodeBatchSize": 20
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
"EnsureAllNodesCanBeResolved": false,
"EnableFlagEnums": false,
"EnableDefer": false,
"EnableStream": false
"EnableStream": false,
"MaxAllowedNodeBatchSize": 10
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
"EnsureAllNodesCanBeResolved": false,
"EnableFlagEnums": false,
"EnableDefer": false,
"EnableStream": false
"EnableStream": false,
"MaxAllowedNodeBatchSize": 10
}
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ private static IEnumerable<ScopedVariableValue> ResolveUsedRequestVariables(
value = rewriter.RewriteValueNode(
schemaName,
(IInputType)variable.Type.ToType(namedType),
value);
value!);

yield return new ScopedVariableValue
(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using HotChocolate.Execution.Configuration;
using HotChocolate.Language;
using HotChocolate.Types.Descriptors;
Expand All @@ -15,9 +10,9 @@ public class PublishSchemaDefinitionDescriptor : IPublishSchemaDefinitionDescrip
{
private readonly IRequestExecutorBuilder _builder;
private readonly string _key = Guid.NewGuid().ToString();
private readonly List<DirectiveNode> _schemaDirectives = new List<DirectiveNode>();
private readonly List<DirectiveNode> _schemaDirectives = new();
private Func<IServiceProvider, ISchemaDefinitionPublisher>? _publisherFactory;
private string _name;
private string? _name;
private RemoteSchemaDefinition? _schemaDefinition;

public PublishSchemaDefinitionDescriptor(IRequestExecutorBuilder builder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ public async Task CreateIfNotExistsAsync(SqliteConnection connection)

private static async Task CreateEntitiesTableAsync(SqliteConnection connection)
{
using SqliteCommand command = connection.CreateCommand();
using var command = connection.CreateCommand();
command.CommandText = _entitiesTable;
await command.ExecuteNonQueryAsync().ConfigureAwait(false);
}

private static async Task CreateOperationsTableAsync(SqliteConnection connection)
{
using SqliteCommand command = connection.CreateCommand();
using var command = connection.CreateCommand();
command.CommandText = _operationsTable;
await command.ExecuteNonQueryAsync().ConfigureAwait(false);
}
Expand Down Expand Up @@ -81,7 +81,7 @@ public async IAsyncEnumerable<EntityDto> GetAllEntitiesAsync(
{
_loadEntities.Connection = connection;

using SqliteDataReader reader =
using var reader =
await _loadEntities.ExecuteReaderAsync(cancellationToken);

while (await reader.ReadAsync(cancellationToken))
Expand Down Expand Up @@ -128,7 +128,7 @@ public async IAsyncEnumerable<OperationDto> GetAllOperationsAsync(
{
_loadOperations.Connection = connection;

using SqliteDataReader reader =
using var reader =
await _loadOperations.ExecuteReaderAsync(cancellationToken);

while (await reader.ReadAsync(cancellationToken))
Expand Down
Loading

0 comments on commit 6f6e0e9

Please sign in to comment.