Skip to content

Commit

Permalink
Fixed issue with operation optimizers in fusion. (#7291)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Jul 23, 2024
1 parent b91ddb7 commit b6403e2
Show file tree
Hide file tree
Showing 62 changed files with 499 additions and 446 deletions.

This file was deleted.

2 changes: 1 addition & 1 deletion src/HotChocolate/Core/src/Execution/IRequestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public interface IRequestContext : IHasContextData
/// Gets the request executor version.
/// </summary>
ulong ExecutorVersion { get; }

/// <summary>
/// Gets the index of the request that corresponds to this context.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public async ValueTask InvokeAsync(IRequestContext context)

if (operationId is null)
{
operationId = context.CreateCacheId(context.DocumentId.Value.Value, context.Request.OperationName);
operationId = context.CreateCacheId();
context.OperationId = operationId;
}

Expand All @@ -61,7 +61,7 @@ context.Document is not null &&
}
}
}

public static RequestCoreMiddleware Create()
=> (core, next) =>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HotChocolate.Execution.Processing;
using HotChocolate.Language;
using HotChocolate.Types;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.ObjectPool;
using static HotChocolate.Execution.ErrorHelper;
using static HotChocolate.WellKnownContextData;

namespace HotChocolate.Execution.Pipeline;

internal sealed class OperationResolverMiddleware
{
private readonly RequestDelegate _next;
private readonly ObjectPool<OperationCompiler> _operationCompilerPool;
private readonly OperationCompilerOptimizers _operationCompilerOptimizers;

private OperationResolverMiddleware(
RequestDelegate next,
ObjectPool<OperationCompiler> operationCompilerPool)
ObjectPool<OperationCompiler> operationCompilerPool,
OperationCompilerOptimizers operationCompilerOptimizer)
{
_next = next ??
throw new ArgumentNullException(nameof(next));
_operationCompilerPool = operationCompilerPool ??
throw new ArgumentNullException(nameof(operationCompilerPool));
_next = next ?? throw new ArgumentNullException(nameof(next));
_operationCompilerPool =
operationCompilerPool ?? throw new ArgumentNullException(nameof(operationCompilerPool));
_operationCompilerOptimizers = operationCompilerOptimizer
?? throw new ArgumentNullException(nameof(operationCompilerOptimizer));
}

public async ValueTask InvokeAsync(IRequestContext context)
Expand Down Expand Up @@ -68,15 +68,20 @@ private IOperation CompileOperation(
OperationDefinitionNode operationDefinition,
ObjectType operationType)
{
var compiler = _operationCompilerPool.Get();
var operation = compiler.Compile(
var request = new OperationCompilerRequest(
operationId,
context.Document!,
operationDefinition,
operationType,
context.Document!,
context.Schema,
IsNullBubblingEnabled(context));
_operationCompilerOptimizers.OperationOptimizers,
_operationCompilerOptimizers.SelectionSetOptimizers,
context.IsNullBubblingEnabled());

var compiler = _operationCompilerPool.Get();
var operation = compiler.Compile(request);
_operationCompilerPool.Return(compiler);

return operation;
}

Expand All @@ -91,15 +96,12 @@ private IOperation CompileOperation(
_ => throw ThrowHelper.RootTypeNotSupported(operationType),
};

private bool IsNullBubblingEnabled(IRequestContext context)
=> !context.Schema.ContextData.ContainsKey(EnableTrueNullability) ||
!context.ContextData.ContainsKey(EnableTrueNullability);

public static RequestCoreMiddleware Create()
=> (core, next) =>
{
var operationCompilerPool = core.Services.GetRequiredService<ObjectPool<OperationCompiler>>();
var middleware = new OperationResolverMiddleware(next, operationCompilerPool);
var optimizers = core.SchemaServices.GetRequiredService<OperationCompilerOptimizers>();
var middleware = new OperationResolverMiddleware(next, operationCompilerPool, optimizers);
return context => middleware.InvokeAsync(context);
};
}
49 changes: 36 additions & 13 deletions src/HotChocolate/Core/src/Execution/Pipeline/PipelineTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,38 @@ internal static class PipelineTools

private static readonly IReadOnlyList<VariableValueCollection> _noVariables = [VariableValueCollection.Empty,];

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string CreateOperationId(string documentId, string? operationName)
=> operationName is null
? documentId
: $"{documentId}+{operationName}";

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string CreateCacheId(this IRequestContext context, string operationId)
=> $"{context.Schema.Name}-{context.ExecutorVersion}-{operationId}";
public static string CreateCacheId(this IRequestContext context)
{
var documentId = context.DocumentId!.Value.Value;
var operationName = context.Request.OperationName;

if (string.IsNullOrEmpty(documentId))
{
throw new ArgumentException(
"The request context must have a valid document ID "
+ "in order to create a cache ID.");
}

var operationId = CreateOperationId(documentId, operationName);

var flags = OperationFlags.Nothing;

if (!context.IsNullBubblingEnabled())
{
flags |= OperationFlags.DisableNullBubbling;
}

return $"{context.Schema.Name}-{context.ExecutorVersion}-{(int)flags}-{operationId}";
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string CreateCacheId(
this IRequestContext context,
string documentId,
string? operationName)
=> CreateCacheId(context, CreateOperationId(documentId, operationName));
public static bool IsNullBubblingEnabled(this IRequestContext context)
=> !context.Schema.ContextData.ContainsKey(WellKnownContextData.EnableTrueNullability)
|| !context.ContextData.ContainsKey(WellKnownContextData.EnableTrueNullability);

public static IReadOnlyList<IVariableValueCollection> CoerceVariables(
IRequestContext context,
Expand Down Expand Up @@ -61,7 +77,7 @@ public static IReadOnlyList<IVariableValueCollection> CoerceVariables(
return context.Variables;
}
}

if (context.Request is VariableBatchRequest variableBatchRequest)
{
using (context.DiagnosticEvents.CoerceVariables(context))
Expand All @@ -70,7 +86,7 @@ public static IReadOnlyList<IVariableValueCollection> CoerceVariables(
var variableSetCount = variableBatchRequest.VariableValues?.Count ?? 0;
var variableSetInput = variableBatchRequest.VariableValues!;
var variableSet = new IVariableValueCollection[variableSetCount];

for (var i = 0; i < variableSetCount; i++)
{
var coercedValues = new Dictionary<string, VariableValueOrLiteral>();
Expand All @@ -91,4 +107,11 @@ public static IReadOnlyList<IVariableValueCollection> CoerceVariables(

throw new NotSupportedException("Request type not supported.");
}
}

[Flags]
private enum OperationFlags
{
Nothing = 0,
DisableNullBubbling
}
}
80 changes: 22 additions & 58 deletions src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,55 +61,29 @@ public OperationCompiler(InputParser parser)

internal OperationCompilerMetrics Metrics => _metrics;

public IOperation Compile(
string operationId,
OperationDefinitionNode operationDefinition,
ObjectType operationType,
DocumentNode document,
ISchema schema,
bool enableNullBubbling = true)
public IOperation Compile(OperationCompilerRequest request)
{
if (string.IsNullOrEmpty(operationId))
if (string.IsNullOrEmpty(request.Id))
{
throw new ArgumentException(
OperationCompiler_OperationIdNullOrEmpty,
nameof(operationId));
}

if (operationDefinition is null)
{
throw new ArgumentNullException(nameof(operationDefinition));
}

if (operationType is null)
{
throw new ArgumentNullException(nameof(operationType));
}

if (document is null)
{
throw new ArgumentNullException(nameof(document));
}

if (schema is null)
{
throw new ArgumentNullException(nameof(schema));
nameof(request.Id));
}

try
{
var backlogMaxSize = 0;
var selectionSetOptimizers = schema.GetSelectionSetOptimizers();
_operationOptimizers = schema.GetOperationOptimizers();
var selectionSetOptimizers = request.SelectionSetOptimizers;
_operationOptimizers = request.OperationOptimizers;

// collect root fields
var rootPath = SelectionPath.Root;
var id = GetOrCreateSelectionSetRefId(operationDefinition.SelectionSet, rootPath);
var id = GetOrCreateSelectionSetRefId(request.Definition.SelectionSet, rootPath);
var variants = GetOrCreateSelectionVariants(id);
SelectionSetInfo[] infos = [new(operationDefinition.SelectionSet, 0)];
SelectionSetInfo[] infos = [new(request.Definition.SelectionSet, 0)];

var context = new CompilerContext(schema, document, enableNullBubbling);
context.Initialize(operationType, variants, infos, rootPath, selectionSetOptimizers);
var context = new CompilerContext(request.Schema, request.Document, request.EnableNullBubbling);
context.Initialize(request.RootType, variants, infos, rootPath, selectionSetOptimizers);
CompileSelectionSet(context);

// process consecutive selections
Expand All @@ -130,12 +104,7 @@ public IOperation Compile(
}

// create operation
var operation = CreateOperation(
operationId,
operationDefinition,
operationType,
document,
schema);
var operation = CreateOperation(request);

_metrics = new OperationCompilerMetrics(
_nextSelectionId,
Expand Down Expand Up @@ -170,18 +139,13 @@ public IOperation Compile(
}
}

private Operation CreateOperation(
string operationId,
OperationDefinitionNode operationDefinition,
ObjectType operationType,
DocumentNode document,
ISchema schema)
private Operation CreateOperation(OperationCompilerRequest request)
{
var variants = new SelectionVariants[_selectionVariants.Count];

if (_operationOptimizers.Length == 0)
{
CompleteResolvers(schema);
CompleteResolvers(request.Schema);

// if we do not have any optimizers we will copy
// the variants and seal them in one go.
Expand All @@ -198,11 +162,11 @@ private Operation CreateOperation(
// more mutations on the compiled selection variants.
// after we have executed all optimizers we will seal the selection variants.
var context = new OperationOptimizerContext(
operationId,
document,
operationDefinition,
schema,
operationType,
request.Id,
request.Document,
request.Definition,
request.Schema,
request.RootType,
variants,
_includeConditions,
_contextData,
Expand Down Expand Up @@ -244,7 +208,7 @@ private Operation CreateOperation(
}
#endif

CompleteResolvers(schema);
CompleteResolvers(request.Schema);

variantsSpan = variants.AsSpan();
variantsStart = ref GetReference(variantsSpan)!;
Expand All @@ -258,10 +222,10 @@ private Operation CreateOperation(
}

return new Operation(
operationId,
document,
operationDefinition,
operationType,
request.Id,
request.Document,
request.Definition,
request.RootType,
variants,
_includeConditions,
new Dictionary<string, object?>(_contextData),
Expand Down

This file was deleted.

Loading

0 comments on commit b6403e2

Please sign in to comment.