ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.26k stars 746 forks source link

Fusion uses wrong top-level resolver #6728

Open interad-woergoetter opened 1 year ago

interad-woergoetter commented 1 year ago

Is there an existing issue for this?

Product

Hot Chocolate

Describe the bug

Fusion may try to use the wrong resolver when multiple different resolvers on different alternate keys are available.

The order of variable or resolver definitions in the gateway package file seems to influence the decision of the gateway, so names of resolvers or variables may influence the reproducibility.

Steps to reproduce

  1. Set up a Fusion gateway server with the attached gateway package. gateway.fgp.zip
  2. Start the gateway server.
  3. Send the query query { subgraph3Foo { name } } to the gateway.
  4. Confirm that the gateway is able to create a query plan fetching additional data from Subgraph1.
  5. Now send the query query { subgraph2Foo { name } } to the gateway.
  6. Notice that the gateway is not able to create a query plan.

Relevant log output

{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "extensions": {
        "message": "The schema metadata are not consistent.",
        "stackTrace": "   at HotChocolate.Fusion.Planning.Pipeline.RequirementsPlannerMiddleware.Plan(QueryPlanContext context)\r\n   at HotChocolate.Fusion.Planning.Pipeline.RequirementsPlannerMiddleware.Invoke(QueryPlanContext context, QueryPlanDelegate next)\r\n   at HotChocolate.Fusion.Planning.QueryPlanPipelineBuilder.<>c__DisplayClass4_0`1.<Use>b__1(QueryPlanContext context)\r\n   at HotChocolate.Fusion.Planning.Pipeline.FieldRequirementsPlannerMiddleware.Invoke(QueryPlanContext context, QueryPlanDelegate next)\r\n   at HotChocolate.Fusion.Planning.QueryPlanPipelineBuilder.<>c__DisplayClass5_1`1.<Use>b__1(QueryPlanContext context)\r\n   at HotChocolate.Fusion.Planning.Pipeline.ExecutionStepDiscoveryMiddleware.Invoke(QueryPlanContext context, QueryPlanDelegate next)\r\n   at HotChocolate.Fusion.Planning.QueryPlanPipelineBuilder.<>c__DisplayClass5_1`1.<Use>b__1(QueryPlanContext context)\r\n   at HotChocolate.Fusion.Planning.QueryPlanner.Plan(IOperation operation)\r\n   at HotChocolate.Fusion.Execution.Pipeline.OperationQueryPlanCompiler.OptimizeOperation(OperationOptimizerContext context)\r\n   at HotChocolate.Execution.Processing.OperationCompiler.CreateOperation(String operationId, OperationDefinitionNode operationDefinition, ObjectType operationType, DocumentNode document, ISchema schema)\r\n   at HotChocolate.Execution.Processing.OperationCompiler.Compile(String operationId, OperationDefinitionNode operationDefinition, ObjectType operationType, DocumentNode document, ISchema schema, IReadOnlyList`1 optimizers, Boolean enableNullBubbling)\r\n   at HotChocolate.Execution.Pipeline.OperationResolverMiddleware.CompileOperation(IRequestContext context, String operationId, OperationDefinitionNode operationDefinition, ObjectType operationType)\r\n   at HotChocolate.Execution.Pipeline.OperationResolverMiddleware.InvokeAsync(IRequestContext context)\r\n   at HotChocolate.Execution.Pipeline.OperationComplexityMiddleware.InvokeAsync(IRequestContext context)\r\n   at HotChocolate.Execution.Pipeline.OperationCacheMiddleware.InvokeAsync(IRequestContext context)\r\n   at HotChocolate.Execution.Pipeline.DocumentValidationMiddleware.InvokeAsync(IRequestContext context)\r\n   at HotChocolate.Execution.Pipeline.DocumentParserMiddleware.InvokeAsync(IRequestContext context)\r\n   at HotChocolate.Execution.Pipeline.DocumentCacheMiddleware.InvokeAsync(IRequestContext context)\r\n   at HotChocolate.Execution.Pipeline.TimeoutMiddleware.InvokeAsync(IRequestContext context)\r\n   at HotChocolate.Execution.Pipeline.ExceptionMiddleware.InvokeAsync(IRequestContext context)"
      }
    }
  ]
}

Additional Context?

I think the bug may be related to the call to GatherVariablesInContext in the method TrySetEntityResolver. It appears that this method adds all variables on the type of the selection set into the variables context, even if those variables are only available on subgraphs that we have not yet visited. https://github.com/ChilliCream/graphql-platform/blob/a090dab523d3157be1733b3febdb58f0c5d37aec/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionStepDiscoveryMiddleware.cs#L580C9-L580C97

Version

13.7.0

nhuethmayr commented 11 months ago

Any news regarding this @michaelstaib?