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

New schema published in the redis cache breaks the live gateway

Open vmary2014 opened this issue 2 years ago • 1 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the bug

Hi. So we use HC 12.11.1, Apollo federation, Redis and schema stitching. We have an issue with the the Gateway and the redis cache schema publishing.

The gateway is configured with a list of URls for each service, in the form of <name, url> IE:

"GraphQlUrlCollection": {
    "Customer": "https://localhost:5001/graphql/",
...
}

customer in this instance is used to create a named HttpClient with its corresponding url. All is well if the redis cache also contains a customer record with the described schema of the service.

However we have found an issue: If we have a hosted working gateway and someone pushes a new schema to redis and this schema is not configured in the gateway, the gateway breaks with the following message: 1. Unable to resolve type reference None: Uuid!. (HotChocolate.Types.ObjectType)

This breaks until someone creates a value for this service in the collection above and restarts the gateway.

Importantly it has to be noted that this only occurs if the schema has a Uuid type in it. I tried with schemas without Uuid and it seems fine.

However this obviously is an issue that can be disastrous in production as if a new service is deployed in the environment and pushes a new schema in redis, that could break the gateway.

I have reproduced this also removing the Apollo federation.

My start-up now is :

 services
    .AddLogging()
    .AddSingleton(sp =>
    {
        var redisConnectionString = Configuration.GetConnectionString("Redis");
        return ConnectionMultiplexer.Connect(ConfigurationOptions.Parse(redisConnectionString));
    })
    .AddGraphQLServer()
    .AddType(() => new UuidType("Uuid", defaultFormat: 'D'))
    .AddAuthorization() 
    .AddRemoteSchemasFromConfiguration(httpOnlySchemas) // This is a small extension method to add remote http clients
    .AddRemoteSchemasFromRedis(
        SchemaCache.RedisCollectionName,
        sp => sp.GetRequiredService<ConnectionMultiplexer>())
    .AddTypeExtensionsFromString("type Query @authorize { }")
    .RenameTypes()
    .IgnoreType("ApplyPolicy")
    .AddDirectiveMergeRule(MergeRuleFactory)
    .AddTypeExtensionsFromFile("stitching/Stitching-CCD.graphql")
    .ModifyRequestOptions(opt =>
        opt.IncludeExceptionDetails = _currentEnv.IsDevelopment())
    .InitializeOnStartup();

// Below this adds the `Uuid` to all underlying services as otherwise it breaks at start-up with the same error message as before
foreach (var schema in allSchemas)
{
    services.AddGraphQL(schema)
        .AddType(() => new UuidType("Uuid", defaultFormat: 'N'));
}

To validate the issue ref httpClients and redis I modified the code locally to add a collection of known schemas to the redis extension, and only add this schema if known as shown in this diff, and this works as a workaround, but I guess you guys didn't intend for that to work this way so will refrain to do a PR just yet.

Could you point me in the right direction in the HC code as to where this could potentially break? It definitely seems to occur when a Uuid is added (and most our schemas use Guids so....)

Cheers

Vincent

Steps to reproduce

  1. Configure a redis cache.
  2. Make a gateway pull from it
  3. Start a service that publishes to Redis with a Uuid type in it
  4. Restart the gateway, the error message should be occur

Also it has to be noted that step 4 is necessary only locally as I use a local instance of docker redis. In our environments we use a hosted redis in aws and the gateway polls from it. No restart is necessary in this instance as it breaks once polled.

Relevant log output

BackgroundService failed
HotChocolate.SchemaException: For more details look at the `Errors` property.

1. Unable to resolve type reference `None: Uuid!`. (HotChocolate.Types.ObjectType)

   at HotChocolate.Configuration.RegisteredType.GetType[T](ITypeReference typeRef) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Configuration/RegisteredType.CompletionContext.cs:line 86
   at HotChocolate.Types.OutputFieldBase`1.OnCompleteField(ITypeCompletionContext context, ITypeSystemMember declaringMember, TDefinition definition) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Types/OutputFieldBase.cs:line 58
   at HotChocolate.Types.ObjectField.OnCompleteField(ITypeCompletionContext context, ITypeSystemMember declaringMember, ObjectFieldDefinition definition) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Types/ObjectField.cs:line 121
   at HotChocolate.Types.FieldBase`1.CompleteField(ITypeCompletionContext context, ITypeSystemMember declaringMember) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Types/FieldBase.cs:line 63
   at HotChocolate.Types.FieldBase`1.HotChocolate.Types.Helpers.IFieldCompletion.CompleteField(ITypeCompletionContext context, ITypeSystemMember declaringMember) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Types/FieldBase.cs:line 85
   at HotChocolate.Internal.FieldInitHelper.CompleteFieldsInternal[TField](ITypeCompletionContext context, ITypeSystemMember declaringMember, TField[] fields) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Internal/FieldInitHelper.cs:line 209
   at HotChocolate.Internal.FieldInitHelper.CompleteFieldsInternal[TFieldDefinition,TField](ITypeCompletionContext context, ITypeSystemMember declaringMember, IEnumerable`1 fieldDefinitions, Func`3 fieldFactory, Int32 fieldCount) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Internal/FieldInitHelper.cs:line 161
   at HotChocolate.Internal.FieldInitHelper.CompleteFields[TFieldDefinition,TField](ITypeCompletionContext context, ITypeSystemMember declaringMember, IReadOnlyList`1 fieldDefs, Func`3 fieldFactory) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Internal/FieldInitHelper.cs:line 76
   at HotChocolate.Types.ObjectType.OnCompleteFields(ITypeCompletionContext context, ObjectTypeDefinition definition) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Types/ObjectType.Initialization.cs:line 73
   at HotChocolate.Types.ObjectType.OnCompleteType(ITypeCompletionContext context, ObjectTypeDefinition definition) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Types/ObjectType.Initialization.cs:line 63
   at HotChocolate.Types.TypeSystemObjectBase`1.CompleteType(ITypeCompletionContext context) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Types/TypeSystemObjectBase~1.cs:line 127
   at HotChocolate.Configuration.TypeInitializer.<CompleteTypes>g__CompleteType|27_0(RegisteredType registeredType) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Configuration/TypeInitializer.cs:line 386
   at HotChocolate.Configuration.TypeInitializer.ProcessTypes(TypeDependencyKind kind, Func`2 action) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Configuration/TypeInitializer.cs:line 429
   at HotChocolate.Configuration.TypeInitializer.CompleteTypes() in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Configuration/TypeInitializer.cs:line 393
   at HotChocolate.Configuration.TypeInitializer.Initialize() in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/Configuration/TypeInitializer.cs:line 96
   at HotChocolate.SchemaBuilder.Setup.InitializeTypes(SchemaBuilder builder, IDescriptorContext context, IReadOnlyList`1 types, LazySchema lazySchema) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/SchemaBuilder.Setup.cs:line 206
   at HotChocolate.SchemaBuilder.Setup.Create(SchemaBuilder builder, LazySchema lazySchema, IDescriptorContext context) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/SchemaBuilder.Setup.cs:line 74
   at HotChocolate.SchemaBuilder.Create(IDescriptorContext context) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/SchemaBuilder.Create.cs:line 14
   at HotChocolate.SchemaBuilder.HotChocolate.ISchemaBuilder.Create(IDescriptorContext context) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Types/SchemaBuilder.Create.cs:line 30
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(NameString schemaName, RequestExecutorSetup options, RequestExecutorOptions executorOptions, IServiceProvider serviceProvider, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Execution/RequestExecutorResolver.cs:line 351
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(NameString schemaName, RequestExecutorSetup options, CancellationToken cancellationToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Execution/RequestExecutorResolver.cs:line 281
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorNoLockAsync(NameString schemaName, CancellationToken cancellationToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Execution/RequestExecutorResolver.cs:line 86
   at Microsoft.Extensions.DependencyInjection.HotChocolateStitchingRequestExecutorExtensions.<>c__DisplayClass5_0.<<AddRemoteSchema>b__2>d.MoveNext() in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Stitching/src/Stitching/DependencyInjection/HotChocolateStitchingRequestExecutorExtensions.cs:line 237
--- End of stack trace from previous location ---
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(NameString schemaName, RequestExecutorSetup options, RequestExecutorOptions executorOptions, IServiceProvider serviceProvider, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Execution/RequestExecutorResolver.cs:line 344
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(NameString schemaName, RequestExecutorSetup options, CancellationToken cancellationToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Execution/RequestExecutorResolver.cs:line 281
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorNoLockAsync(NameString schemaName, CancellationToken cancellationToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Execution/RequestExecutorResolver.cs:line 86
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorAsync(NameString schemaName, CancellationToken cancellationToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/Core/src/Execution/RequestExecutorResolver.cs:line 62
   at HotChocolate.AspNetCore.Warmup.ExecutorWarmupService.ExecuteAsync(CancellationToken stoppingToken) in /home/vincentmary/work/repos/vmary2014hotchocolate/src/HotChocolate/AspNetCore/src/AspNetCore/Warmup/ExecutorWarmupService.cs:line 40
   at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)

Additional Context?

No response

Product

Hot Chocolate

Version

12.11.1. Also reproduced using 12.12.1 locally.

vmary2014 avatar Sep 01 '22 09:09 vmary2014

Describe the bug

I guess I have the similar issue but using AddRemoteSchema or AddRemoteSchemaFromFile

Startup:

builder.Services
           .AddGraphQLServer()
           .AddRemoteSchemaFromFile("TestSchema", @"schema.graphql")

Schema file "schema.graphql":

scalar ObjectId

type Query {
  hello: ObjectId!
}

Steps to reproduce

  1. Use schema from url or local file
  2. Start gateway
  3. See error: Unable to resolve type reference None: ObjectId!. (HotChocolate.Types.ObjectType).
  4. Adding ".AddType<ObjectIdType>()" from mongo package does not affect the behavior. If schema is described in code (via classes), everything is working ok.

Relevant log output

An unhandled exception has occurred while executing the request.
HotChocolate.SchemaException: For more details look at the `Errors` property.

1. Unable to resolve type reference `None: ObjectId!`. (HotChocolate.Types.ObjectType)

   at HotChocolate.Configuration.RegisteredType.GetType[T](ITypeReference typeRef)
   at HotChocolate.Types.OutputFieldBase`1.OnCompleteField(ITypeCompletionContext context, ITypeSystemMember declaringMember, TDefinition definition)
   at HotChocolate.Types.ObjectField.OnCompleteField(ITypeCompletionContext context, ITypeSystemMember declaringMember, ObjectFieldDefinition definition)
   at HotChocolate.Types.FieldBase`1.CompleteField(ITypeCompletionContext context, ITypeSystemMember declaringMember)
   at HotChocolate.Internal.FieldInitHelper.CompleteFieldsInternal[TField](ITypeCompletionContext context, ITypeSystemMember declaringMember, TField[] fields)
   at HotChocolate.Internal.FieldInitHelper.CompleteFieldsInternal[TFieldDefinition,TField](ITypeCompletionContext context, ITypeSystemMember declaringMember, IEnumerable`1 fieldDefinitions, Func`3 fieldFactory, Int32 fieldCount)
   at HotChocolate.Internal.FieldInitHelper.CompleteFields[TFieldDefinition,TField](ITypeCompletionContext context, ITypeSystemMember declaringMember, IReadOnlyList`1 fieldDefs, Func`3 fieldFactory)
   at HotChocolate.Types.ObjectType.OnCompleteFields(ITypeCompletionContext context, ObjectTypeDefinition definition)
   at HotChocolate.Types.ObjectType.OnCompleteType(ITypeCompletionContext context, ObjectTypeDefinition definition)
   at HotChocolate.Types.TypeSystemObjectBase`1.CompleteType(ITypeCompletionContext context)
   at HotChocolate.Configuration.TypeInitializer.<CompleteTypes>g__CompleteType|27_0(RegisteredType registeredType)
   at HotChocolate.Configuration.TypeInitializer.ProcessTypes(TypeDependencyKind kind, Func`2 action)
   at HotChocolate.Configuration.TypeInitializer.CompleteTypes()
   at HotChocolate.Configuration.TypeInitializer.Initialize()
   at HotChocolate.SchemaBuilder.Setup.InitializeTypes(SchemaBuilder builder, IDescriptorContext context, IReadOnlyList`1 types, LazySchema lazySchema)
   at HotChocolate.SchemaBuilder.Setup.Create(SchemaBuilder builder, LazySchema lazySchema, IDescriptorContext context)
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(NameString schemaName, RequestExecutorSetup options, RequestExecutorOptions executorOptions, IServiceProvider serviceProvider, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(NameString schemaName, RequestExecutorSetup options, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorNoLockAsync(NameString schemaName, CancellationToken cancellationToken)
   at Microsoft.Extensions.DependencyInjection.HotChocolateStitchingRequestExecutorExtensions.<>c__DisplayClass5_0.<<AddRemoteSchema>b__2>d.MoveNext()
--- End of stack trace from previous location ---
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(NameString schemaName, RequestExecutorSetup options, RequestExecutorOptions executorOptions, IServiceProvider serviceProvider, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(NameString schemaName, RequestExecutorSetup options, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorNoLockAsync(NameString schemaName, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorResolver.GetRequestExecutorAsync(NameString schemaName, CancellationToken cancellationToken)
   at HotChocolate.Execution.RequestExecutorProxy.GetRequestExecutorAsync(CancellationToken cancellationToken)
   at HotChocolate.AspNetCore.HttpPostMiddlewareBase.HandleRequestAsync(HttpContext context, AllowedContentType contentType)
   at HotChocolate.AspNetCore.HttpPostMiddlewareBase.InvokeAsync(HttpContext context)
   at Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions.<>c__DisplayClass13_0.<<UseCancellation>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Additional Context?

.NET 6

Product

Hot Chocolate

Version

12.13.2

AlexBar avatar Sep 15 '22 12:09 AlexBar

any ideas or workarounds on this?

AlexBar avatar Sep 26 '22 11:09 AlexBar

@AlexBar

builder.Services
           .AddGraphQLServer()
           .AddRemoteSchemaFromFile("TestSchema", @"schema.graphql")
           .AddType(new AnyType("ObjectId");

builder.Services.AddGraphQL("TestSchema").AddType(new AnyType("ObjectId"); 

PascalSenn avatar Sep 26 '22 14:09 PascalSenn

HotChocolate.Stitching is now in legacy mode and is replaced by HotChocolate.Fusion. I am closing this issue as we essentially froze the fusion code.

You can join the preview of Hot Chocolate Fusion now on Slack

michaelstaib avatar Mar 08 '23 20:03 michaelstaib