-
-
Notifications
You must be signed in to change notification settings - Fork 748
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduces fully serial execution strategy (#1552)
- Loading branch information
1 parent
47c61e1
commit 3b9e329
Showing
21 changed files
with
277 additions
and
17 deletions.
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
src/Core/Core.Tests/Execution/ExecutionStrategyResolverTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using HotChocolate.Execution.Configuration; | ||
using HotChocolate.Language; | ||
using Xunit; | ||
|
||
namespace HotChocolate.Execution | ||
{ | ||
public class ExecutionStrategyResolverTests | ||
{ | ||
[Fact] | ||
public void Default_Query_Strategy_Is_QueryExecutionStrategy() | ||
{ | ||
// arrange | ||
var options = new QueryExecutionOptions(); | ||
var strategyResolver = new ExecutionStrategyResolver(options, options); | ||
|
||
// act | ||
IExecutionStrategy strategy = strategyResolver.Resolve(OperationType.Query); | ||
|
||
// assert | ||
Assert.IsType<QueryExecutionStrategy>(strategy); | ||
} | ||
|
||
[Fact] | ||
public void Default_Mutation_Strategy_Is_MutationStrategy() | ||
{ | ||
// arrange | ||
var options = new QueryExecutionOptions(); | ||
var strategyResolver = new ExecutionStrategyResolver(options, options); | ||
|
||
// act | ||
IExecutionStrategy strategy = strategyResolver.Resolve(OperationType.Mutation); | ||
|
||
// assert | ||
Assert.IsType<MutationExecutionStrategy>(strategy); | ||
} | ||
|
||
[Fact] | ||
public void Default_Subscription_Strategy_Is_SubscriptionStrategy() | ||
{ | ||
// arrange | ||
var options = new QueryExecutionOptions(); | ||
var strategyResolver = new ExecutionStrategyResolver(options, options); | ||
|
||
// act | ||
IExecutionStrategy strategy = strategyResolver.Resolve(OperationType.Subscription); | ||
|
||
// assert | ||
Assert.IsType<SubscriptionExecutionStrategy>(strategy); | ||
} | ||
|
||
[Fact] | ||
public void Serial_Query_Strategy_Is_QueryExecutionStrategy() | ||
{ | ||
// arrange | ||
var options = new QueryExecutionOptions { ForceSerialExecution = true }; | ||
var strategyResolver = new ExecutionStrategyResolver(options, options); | ||
|
||
// act | ||
IExecutionStrategy strategy = strategyResolver.Resolve(OperationType.Query); | ||
|
||
// assert | ||
Assert.IsType<SerialExecutionStrategy>(strategy); | ||
} | ||
|
||
[Fact] | ||
public void Serial_Mutation_Strategy_Is_MutationStrategy() | ||
{ | ||
// arrange | ||
var options = new QueryExecutionOptions { ForceSerialExecution = true }; | ||
var strategyResolver = new ExecutionStrategyResolver(options, options); | ||
|
||
// act | ||
IExecutionStrategy strategy = strategyResolver.Resolve(OperationType.Mutation); | ||
|
||
// assert | ||
Assert.IsType<SerialExecutionStrategy>(strategy); | ||
} | ||
|
||
[Fact] | ||
public void Serial_Subscription_Strategy_Is_SubscriptionStrategy() | ||
{ | ||
// arrange | ||
var options = new QueryExecutionOptions { ForceSerialExecution = true }; | ||
var strategyResolver = new ExecutionStrategyResolver(options, options); | ||
|
||
// act | ||
IExecutionStrategy strategy = strategyResolver.Resolve(OperationType.Subscription); | ||
|
||
// assert | ||
Assert.IsType<SubscriptionExecutionStrategy>(strategy); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
src/Core/Core/Execution/Configuration/IExecutionStrategyOptionsAccessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace HotChocolate.Execution.Configuration | ||
{ | ||
/// <summary> | ||
/// Represents a dedicated options accessor to read the execution strategy options | ||
/// </summary> | ||
public interface IExecutionStrategyOptionsAccessor | ||
{ | ||
/// <summary> | ||
/// Defines that the query graph shall be traversed and execution serially. | ||
/// </summary> | ||
bool? ForceSerialExecution { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
using System; | ||
using System.Buffers; | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace HotChocolate.Execution | ||
{ | ||
/// <summary> | ||
/// This execution strategy executes the full query graph serailly. | ||
/// This execution strategy is used to help with entity framework and | ||
/// will be removed with version 11. | ||
/// </summary> | ||
internal sealed class SerialExecutionStrategy | ||
: ExecutionStrategyBase | ||
{ | ||
public override Task<IExecutionResult> ExecuteAsync( | ||
IExecutionContext executionContext, | ||
CancellationToken cancellationToken) | ||
{ | ||
if (executionContext == null) | ||
{ | ||
throw new ArgumentNullException(nameof(executionContext)); | ||
} | ||
|
||
return ExecuteSeriallyAsync(executionContext, cancellationToken); | ||
} | ||
|
||
private static async Task<IExecutionResult> ExecuteSeriallyAsync( | ||
IExecutionContext executionContext, | ||
CancellationToken cancellationToken) | ||
{ | ||
ResolverContext[] initialBatch = | ||
CreateInitialBatch(executionContext, | ||
executionContext.Result.Data); | ||
|
||
BatchOperationHandler batchOperationHandler = | ||
CreateBatchOperationHandler(executionContext); | ||
|
||
try | ||
{ | ||
await ExecuteResolverBatchSeriallyAsync( | ||
executionContext, | ||
initialBatch, | ||
batchOperationHandler, | ||
cancellationToken) | ||
.ConfigureAwait(false); | ||
|
||
EnsureRootValueNonNullState( | ||
executionContext.Result, | ||
initialBatch); | ||
|
||
return executionContext.Result; | ||
} | ||
finally | ||
{ | ||
batchOperationHandler?.Dispose(); | ||
ResolverContext.Return(initialBatch); | ||
ArrayPool<ResolverContext>.Shared.Return(initialBatch); | ||
} | ||
} | ||
|
||
private static async Task ExecuteResolverBatchSeriallyAsync( | ||
IExecutionContext executionContext, | ||
IEnumerable<ResolverContext> batch, | ||
BatchOperationHandler batchOperationHandler, | ||
CancellationToken cancellationToken) | ||
{ | ||
var current = new List<ResolverContext>(batch); | ||
var next = new List<ResolverContext>(); | ||
|
||
while (current.Count > 0) | ||
{ | ||
foreach (ResolverContext resolverContext in current) | ||
{ | ||
if (resolverContext is null) | ||
{ | ||
break; | ||
} | ||
|
||
await ExecuteResolverSeriallyAsync( | ||
resolverContext, | ||
next.Add, | ||
batchOperationHandler, | ||
executionContext.ErrorHandler, | ||
cancellationToken) | ||
.ConfigureAwait(false); | ||
|
||
cancellationToken.ThrowIfCancellationRequested(); | ||
} | ||
|
||
ResolverContext.Return(current); | ||
|
||
current.Clear(); | ||
current.AddRange(next); | ||
next.Clear(); | ||
|
||
cancellationToken.ThrowIfCancellationRequested(); | ||
} | ||
} | ||
|
||
private static async Task ExecuteResolverSeriallyAsync( | ||
ResolverContext resolverContext, | ||
Action<ResolverContext> enqueueNext, | ||
BatchOperationHandler batchOperationHandler, | ||
IErrorHandler errorHandler, | ||
CancellationToken cancellationToken) | ||
{ | ||
resolverContext.Task = ExecuteResolverAsync( | ||
resolverContext, | ||
errorHandler); | ||
|
||
if (batchOperationHandler != null) | ||
{ | ||
await CompleteBatchOperationsAsync( | ||
new[] { resolverContext }, | ||
batchOperationHandler, | ||
cancellationToken) | ||
.ConfigureAwait(false); | ||
} | ||
|
||
await resolverContext.Task.ConfigureAwait(false); | ||
|
||
// serialize and integrate result into final query result | ||
ValueCompletion.CompleteValue(enqueueNext, resolverContext); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.