diff --git a/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs b/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs index 6d19c7d916f..d93a89d8e14 100644 --- a/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs +++ b/src/HotChocolate/Core/src/Execution/Pipeline/OperationExecutionMiddleware.cs @@ -1,10 +1,10 @@ using System; using System.Threading.Tasks; +using HotChocolate.Execution.DependencyInjection; using HotChocolate.Execution.Processing; using HotChocolate.Fetching; using HotChocolate.Language; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.ObjectPool; using static HotChocolate.Execution.GraphQLRequestFlags; using static HotChocolate.Execution.ThrowHelper; @@ -13,7 +13,7 @@ namespace HotChocolate.Execution.Pipeline; internal sealed class OperationExecutionMiddleware { private readonly RequestDelegate _next; - private readonly ObjectPool _operationContextPool; + private readonly IFactory _contextFactory; private readonly QueryExecutor _queryExecutor; private readonly SubscriptionExecutor _subscriptionExecutor; private readonly ITransactionScopeHandler _transactionScopeHandler; @@ -22,15 +22,15 @@ internal sealed class OperationExecutionMiddleware public OperationExecutionMiddleware( RequestDelegate next, - ObjectPool operationContextPool, + IFactory contextFactory, QueryExecutor queryExecutor, SubscriptionExecutor subscriptionExecutor, [SchemaService] ITransactionScopeHandler transactionScopeHandler) { _next = next ?? throw new ArgumentNullException(nameof(next)); - _operationContextPool = operationContextPool ?? - throw new ArgumentNullException(nameof(operationContextPool)); + _contextFactory = contextFactory ?? + throw new ArgumentNullException(nameof(contextFactory)); _queryExecutor = queryExecutor ?? throw new ArgumentNullException(nameof(queryExecutor)); _subscriptionExecutor = subscriptionExecutor ?? @@ -76,7 +76,7 @@ private async Task ExecuteOperationAsync( { if (operation.Definition.Operation == OperationType.Subscription) { - // since the context is pooled we need to clone the context for + // since the request context is pooled we need to clone the context for // long running executions. var cloned = context.Clone(); @@ -91,7 +91,8 @@ private async Task ExecuteOperationAsync( } else { - var operationContext = _operationContextPool.Get(); + var operationContextOwner = _contextFactory.Create(); + var operationContext = operationContextOwner.OperationContext; try { @@ -102,22 +103,21 @@ await ExecuteQueryOrMutationAsync( if (operationContext.DeferredScheduler.HasResults && context.Result is IQueryResult result) { - var stream = operationContext.DeferredScheduler.CreateResultStream(result); - - context.Result = new ResponseStream( - () => stream, + var results = operationContext.DeferredScheduler.CreateResultStream(result); + var responseStream = new ResponseStream( + () => results, ExecutionResultKind.DeferredResult); - context.Result.RegisterForCleanup(result); + responseStream.RegisterForCleanup(result); + responseStream.RegisterForCleanup(operationContextOwner); + context.Result = responseStream; + operationContextOwner = null; } await _next(context).ConfigureAwait(false); } finally { - if (operationContext is not null) - { - _operationContextPool.Return(operationContext); - } + operationContextOwner?.Dispose(); } } } diff --git a/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs b/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs index 181b2d506c3..1cedc873218 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/DeferredStream.cs @@ -76,14 +76,11 @@ protected override async Task ExecuteAsync( uint patchId) { var operationContext = operationContextOwner.OperationContext; - var aborted = operationContext.RequestAborted; - var error = false; try { _task ??= new StreamExecutionTask(this); _task.Reset(operationContext, resultId); - operationContext.Scheduler.Register(_task); await operationContext.Scheduler.ExecuteAsync().ConfigureAwait(false); @@ -91,7 +88,6 @@ protected override async Task ExecuteAsync( if (_task.ChildTask is null) { operationContext.DeferredScheduler.Complete(new(resultId, parentResultId)); - operationContextOwner.Dispose(); return; } @@ -99,7 +95,7 @@ protected override async Task ExecuteAsync( var result = operationContext .SetLabel(Label) - .SetPath(operationContext.PathFactory.Append(Path, Index)) + .SetPath(operationContext.PathFactory.Append(Path, Index).Clone()) .SetItems(new[] { item }) .SetPatchId(patchId) .BuildResult(); @@ -110,19 +106,15 @@ protected override async Task ExecuteAsync( operationContext.DeferredScheduler.Register(this, patchId); operationContext.DeferredScheduler.Complete(new(resultId, parentResultId, result)); } - catch(Exception ex) + catch (Exception ex) { var builder = operationContext.ErrorHandler.CreateUnexpectedError(ex); var result = QueryResultBuilder.CreateError(builder.Build()); operationContext.DeferredScheduler.Complete(new(resultId, parentResultId, result)); - error = true; } finally { - if (error || aborted.IsCancellationRequested) - { - operationContextOwner.Dispose(); - } + operationContextOwner.Dispose(); } } diff --git a/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkStateOwner.cs b/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkStateOwner.cs index c2f03bda3f4..fa9f6f5c307 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkStateOwner.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/DeferredWorkStateOwner.cs @@ -19,7 +19,7 @@ public DeferredWorkStateOwner(DeferredWorkState state, ObjectPool(result).MatchSnapshot(); } - [Fact] public async Task Stream_Label_Set_To_abc() {