Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using HotChocolate.Buffers;
using HotChocolate.Execution;
Expand Down Expand Up @@ -364,17 +365,25 @@ internal ImmutableArray<VariableValues> CreateVariableValueSets(
return [_resultStore.CreateVariableValueSets(ToResultPath(selectionSet), [])];
}

var variableValues = GetPathThroughVariables(forwardedVariables);
return [_resultStore.CreateVariableValueSets(CompactPath.Root, variableValues)];
using var resolvedVariables = ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return
[
_resultStore.CreateVariableValueSetsFromResolvedVariables(
CompactPath.Root,
resolvedVariables.Span)
];
}
else
{
var importedMatchCount = CountImportedRequirementKeys(requirements);

if (importedMatchCount == 0)
{
var variableValues = GetPathThroughVariables(forwardedVariables);
return _resultStore.CreateVariableValueSets(selectionSet, variableValues, requirements);
using var resolvedVariables = ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return _resultStore.CreateVariableValueSetsFromResolvedVariables(
selectionSet,
resolvedVariables.Span,
requirements);
}

if (importedMatchCount != requirements.Length)
Expand All @@ -391,11 +400,12 @@ internal ImmutableArray<VariableValues> CreateVariableValueSets(
return _requirementValues;
}

var variableValuesFromSnapshot = GetPathThroughVariables(forwardedVariables);
return _resultStore.CreateVariableValueSetsFromSnapshot(
using var resolvedSnapshotVariables =
ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return _resultStore.CreateVariableValueSetsFromSnapshotWithResolvedVariables(
_requirementValues,
_requirementKeys!,
variableValuesFromSnapshot,
resolvedSnapshotVariables.Span,
requirements);
}
}
Expand All @@ -412,17 +422,25 @@ internal ImmutableArray<VariableValues> CreateVariableValueSets(
return [];
}

var variableValues = GetPathThroughVariables(forwardedVariables);
return [_resultStore.CreateVariableValueSets(CompactPath.Root, variableValues)];
using var resolvedVariables = ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return
[
_resultStore.CreateVariableValueSetsFromResolvedVariables(
CompactPath.Root,
resolvedVariables.Span)
];
}
else
{
var importedMatchCount = CountImportedRequirementKeys(requiredData);

if (importedMatchCount == 0)
{
var variableValues = GetPathThroughVariables(forwardedVariables);
return _resultStore.CreateVariableValueSets(selectionSets, variableValues, requiredData);
using var resolvedVariables = ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return _resultStore.CreateVariableValueSetsFromResolvedVariables(
selectionSets,
resolvedVariables.Span,
requiredData);
}

if (importedMatchCount != requiredData.Length)
Expand All @@ -439,11 +457,12 @@ internal ImmutableArray<VariableValues> CreateVariableValueSets(
return _requirementValues;
}

var variableValuesFromSnapshot = GetPathThroughVariables(forwardedVariables);
return _resultStore.CreateVariableValueSetsFromSnapshot(
using var resolvedSnapshotVariables =
ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return _resultStore.CreateVariableValueSetsFromSnapshotWithResolvedVariables(
_requirementValues,
_requirementKeys!,
variableValuesFromSnapshot,
resolvedSnapshotVariables.Span,
requiredData);
}
}
Expand All @@ -464,10 +483,10 @@ internal RepresentationValue CreateRepresentationVariableValue(
return RepresentationValue.Empty;
}

var variableValues = GetPathThroughVariables(forwardedVariables);
return _resultStore.CreateRepresentationVariableValue(
using var resolvedVariables = ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return _resultStore.CreateRepresentationVariableValueFromResolvedVariables(
selectionSet,
variableValues,
resolvedVariables.Span,
requirements,
entityTypeName,
shape);
Expand All @@ -477,10 +496,10 @@ internal RepresentationValue CreateRepresentationVariableValue(

if (importedMatchCount == 0)
{
var variableValues = GetPathThroughVariables(forwardedVariables);
return _resultStore.CreateRepresentationVariableValue(
using var resolvedVariables = ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return _resultStore.CreateRepresentationVariableValueFromResolvedVariables(
selectionSet,
variableValues,
resolvedVariables.Span,
requirements,
entityTypeName,
shape);
Expand All @@ -495,11 +514,12 @@ internal RepresentationValue CreateRepresentationVariableValue(
throw CreateMixedScopeException(requirements);
}

var variableValuesFromSnapshot = GetPathThroughVariables(forwardedVariables);
return _resultStore.CreateRepresentationVariableValueFromSnapshot(
using var resolvedSnapshotVariables =
ForwardedVariableValues.Resolve(Variables, forwardedVariables);
return _resultStore.CreateRepresentationVariableValueFromSnapshotWithResolvedVariables(
_requirementValues,
_requirementKeys!,
variableValuesFromSnapshot,
resolvedSnapshotVariables.Span,
requirements,
entityTypeName,
shape);
Expand Down Expand Up @@ -837,38 +857,6 @@ internal OperationResult Complete(bool reusable = false, bool retainMemoryForDef
return operationResult;
}

private ObjectFieldNode[] GetPathThroughVariables(
ReadOnlySpan<string> forwardedVariables)
{
if (Variables.IsEmpty || forwardedVariables.Length == 0)
{
return [];
}

var buffer = new ObjectFieldNode[forwardedVariables.Length];
var count = 0;

foreach (var variableName in forwardedVariables)
{
if (Variables.TryGetValue<IValueNode>(variableName, out var variableValue))
{
buffer[count++] = new ObjectFieldNode(variableName, variableValue);
}
}

if (count == 0)
{
return [];
}

if (count == buffer.Length)
{
return buffer;
}

return buffer.AsMemory(0, count).ToArray();
}

/// <summary>
/// Gets or creates a source schema client for the specified schema and operation type.
/// </summary>
Expand Down Expand Up @@ -1017,3 +1005,106 @@ private static ulong[] RentBitset(int bitsetWordCount)
}
}
}

internal ref struct ForwardedVariableValues
{
private const int InlineCapacity = 8;

private ForwardedVariableValueBuffer _inline;
private ForwardedVariableValue[]? _rented;
private int _count;

private ForwardedVariableValues(int capacity)
{
_inline = default;
_rented = capacity > InlineCapacity
? ArrayPool<ForwardedVariableValue>.Shared.Rent(capacity)
: null;
_count = 0;
Comment on lines +1017 to +1023
}

[UnscopedRef]
public readonly ReadOnlySpan<ForwardedVariableValue> Span
{
get
{
if (_rented is { } rented)
{
return rented.AsSpan(0, _count);
}

return ((ReadOnlySpan<ForwardedVariableValue>)_inline)[.._count];
}
}

public static ForwardedVariableValues Resolve(
IVariableValueCollection variables,
ReadOnlySpan<string> forwardedVariables)
{
ArgumentNullException.ThrowIfNull(variables);

if (variables.IsEmpty || forwardedVariables.IsEmpty)
{
return default;
}

var resolved = new ForwardedVariableValues(forwardedVariables.Length);

try
{
foreach (var name in forwardedVariables)
{
if (variables.TryGetValue<IValueNode>(name, out var value))
{
resolved.Add(new ForwardedVariableValue(name, value));
}
}

return resolved;
}
catch
{
resolved.Dispose();
throw;
}
}

public void Dispose()
{
if (_rented is { } rented)
{
rented.AsSpan(0, _count).Clear();
_rented = null;
_count = 0;
ArrayPool<ForwardedVariableValue>.Shared.Return(rented, clearArray: false);
return;
}

for (var i = 0; i < _count; i++)
{
_inline[i] = default;
}

_count = 0;
}

private void Add(ForwardedVariableValue value)
{
if (_rented is { } rented)
{
rented[_count++] = value;
}
else
{
_inline[_count++] = value;
}
}

[InlineArray(InlineCapacity)]
private struct ForwardedVariableValueBuffer
{
private ForwardedVariableValue _element0;
}
}

internal readonly record struct ForwardedVariableValue(string Name, IValueNode Value);
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using HotChocolate.Language;

namespace HotChocolate.Fusion.Execution.Results;

internal sealed partial class FetchResultStore
{
private readonly ref struct ForwardedVariableValues
{
private readonly IReadOnlyList<ObjectFieldNode>? _fields;
private readonly ReadOnlySpan<ForwardedVariableValue> _values;

public ForwardedVariableValues(IReadOnlyList<ObjectFieldNode> requestVariables)
{
ArgumentNullException.ThrowIfNull(requestVariables);

_fields = requestVariables;
_values = default;
}

public ForwardedVariableValues(ReadOnlySpan<ForwardedVariableValue> requestVariables)
{
_fields = null;
_values = requestVariables;
}

public bool CanUseRequirementFastPath
=> _fields is null || _fields.Count == 0;

public bool IsDirect => _fields is null;

public IReadOnlyList<ObjectFieldNode> Fields => _fields!;

public ReadOnlySpan<ForwardedVariableValue> Values => _values;
}
}
Loading