graphql-platform icon indicating copy to clipboard operation
graphql-platform copied to clipboard

StreamResult attribute leads to abnormal IResolverContext data

Open conchip23 opened this issue 1 year ago • 1 comments

Product

Hot Chocolate

Version

13.8.1

Link to minimal reproduction

None

Steps to reproduce

  1. Define a GraphQL query that uses the [StreamResult] attribute.
  2. Inject IResolverContext into the query method.
  3. Execute the query to initiate the stream.
  4. Observe that the IResolverContext contains abnormal data, despite not being null.

What is expected?

The IResolverContext should contain accurate and expected data, reflecting the correct state of the HTTP context and user session.

What is actually happening?

The IResolverContext is populated with abnormal or incorrect data when using the [StreamResult] attribute.

Relevant log output

-		context	{HotChocolate.Execution.Processing.MiddlewareContext}	HotChocolate.Resolvers.IResolverContext {HotChocolate.Execution.Processing.MiddlewareContext}
		Arguments	null	System.Collections.Generic.IReadOnlyDictionary<string, HotChocolate.Resolvers.ArgumentValue>
+		ContextData	'((HotChocolate.Execution.Processing.MiddlewareContext)context).ContextData' threw an exception of type 'System.NullReferenceException'	System.Collections.Generic.IDictionary<string, object> {System.NullReferenceException}
+		Field	'((HotChocolate.Execution.Processing.MiddlewareContext)context).Field' threw an exception of type 'System.NullReferenceException'	HotChocolate.Types.IObjectField {System.NullReferenceException}
+		FieldSelection	'((HotChocolate.Execution.Processing.MiddlewareContext)context).FieldSelection' threw an exception of type 'System.NullReferenceException'	HotChocolate.Language.FieldNode {System.NullReferenceException}
		HasCleanupTasks	false	bool
		HasErrors	false	bool
		IsResultModified	false	bool
		LocalContextData	null	System.Collections.Immutable.IImmutableDictionary<string, object>
+		ObjectType	'((HotChocolate.Execution.Processing.MiddlewareContext)context).ObjectType' threw an exception of type 'System.NullReferenceException'	HotChocolate.Types.IObjectType {System.NullReferenceException}
+		Operation	'((HotChocolate.Execution.Processing.MiddlewareContext)context).Operation' threw an exception of type 'System.NullReferenceException'	HotChocolate.Execution.Processing.IOperation {System.NullReferenceException}
+		OperationResult	{HotChocolate.Execution.Processing.MiddlewareContext.OperationResultBuilderFacade}	HotChocolate.Resolvers.IOperationResultBuilder {HotChocolate.Execution.Processing.MiddlewareContext.OperationResultBuilderFacade}
		ParentResult	null	HotChocolate.Execution.Processing.ObjectResult
+		Path	'((HotChocolate.Execution.Processing.MiddlewareContext)context).Path' threw an exception of type 'System.NullReferenceException'	HotChocolate.Path {System.NullReferenceException}
+		PureResolver	'((HotChocolate.Execution.Processing.MiddlewareContext)context).PureResolver' threw an exception of type 'System.NullReferenceException'	HotChocolate.Resolvers.PureFieldDelegate {System.NullReferenceException}
+		RequestAborted	IsCancellationRequested = false	System.Threading.CancellationToken
+		RequestServices	'((HotChocolate.Execution.Processing.MiddlewareContext)context).RequestServices' threw an exception of type 'System.NullReferenceException'	System.IServiceProvider {System.NullReferenceException}
+		ResolverPipeline	'((HotChocolate.Execution.Processing.MiddlewareContext)context).ResolverPipeline' threw an exception of type 'System.NullReferenceException'	HotChocolate.Resolvers.FieldDelegate {System.NullReferenceException}
		ResponseIndex	0	int
+		ResponseName	'((HotChocolate.Execution.Processing.MiddlewareContext)context).ResponseName' threw an exception of type 'System.NullReferenceException'	string {System.NullReferenceException}
		Result	null	object
+		Schema	'((HotChocolate.Execution.Processing.MiddlewareContext)context).Schema' threw an exception of type 'System.NullReferenceException'	HotChocolate.ISchema {System.NullReferenceException}
		ScopedContextData	null	System.Collections.Immutable.IImmutableDictionary<string, object>
		Selection	null	HotChocolate.Execution.Processing.ISelection
		Services	null	System.IServiceProvider
		ValueType	null	HotChocolate.Types.IType
+		Variables	'((HotChocolate.Execution.Processing.MiddlewareContext)context).Variables' threw an exception of type 'System.NullReferenceException'	HotChocolate.Execution.IVariableValueCollection {System.NullReferenceException}
+		Static members		
+		Non-Public members

Additional context

I'm not sure if this will be helpful, but I was able to check the normal values by injecting IHttpContextAccessor.

conchip23 avatar Feb 20 '24 07:02 conchip23

I believe I have encountered this issue before. The basic problem seems to be that the resolver context is disposed after it produces the stream object (an IAsyncEnumerable<...> in my case) so that by the time MoveNextAsync() is invoked on the stream object to produce items to be streamed the resolver context is cleared out and useless. I had to work around this by capturing all information I need from the resolver context into my stream object.

atykhyy avatar Mar 28 '24 08:03 atykhyy

This is correct, the resolver context should not be used with in results or spawned of. With version 14 we have added two more ways to deal with this, IResolverResultPostProcessor which runs after the resolver pipeline and we streamlined IExecutable which allows to wrap service scopes into a unit that can be spawned of.

michaelstaib avatar Jul 08 '24 18:07 michaelstaib