Skip to content

Commit 1f0b160

Browse files
[Fusion] Properly handle partial schema-settings.json and configuration in code (#9766)
1 parent c94c8e2 commit 1f0b160

2 files changed

Lines changed: 75 additions & 6 deletions

File tree

src/HotChocolate/Fusion/src/Fusion.Execution/Execution/FusionRequestExecutorManager.cs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -863,18 +863,20 @@ private SourceSchemaClientConfigurations CreateClientConfigurations(
863863
JsonElement settings)
864864
{
865865
var configurations = new List<ISourceSchemaClientConfiguration>();
866+
List<string>? unclaimedSourceSchemas = null;
866867

867868
if (settings.TryGetProperty("sourceSchemas", out var sourceSchemas))
868869
{
869870
foreach (var sourceSchema in sourceSchemas.EnumerateObject())
870871
{
871-
if (!TryClaimSourceSchema(schema, sourceSchema, setup, out var sourceConfigurations))
872+
if (TryClaimSourceSchema(schema, sourceSchema, setup, out var sourceConfigurations))
872873
{
873-
throw new InvalidOperationException(
874-
$"No parser claimed source schema '{sourceSchema.Name}'.");
874+
configurations.AddRange(sourceConfigurations);
875+
}
876+
else
877+
{
878+
(unclaimedSourceSchemas ??= []).Add(sourceSchema.Name);
875879
}
876-
877-
configurations.AddRange(sourceConfigurations);
878880
}
879881
}
880882

@@ -883,6 +885,25 @@ private SourceSchemaClientConfigurations CreateClientConfigurations(
883885
configurations.Add(configure.Invoke(applicationServices));
884886
}
885887

888+
if (unclaimedSourceSchemas is not null)
889+
{
890+
var configuredNames = new HashSet<string>(StringComparer.Ordinal);
891+
foreach (var configuration in configurations)
892+
{
893+
configuredNames.Add(configuration.Name);
894+
}
895+
896+
foreach (var name in unclaimedSourceSchemas)
897+
{
898+
if (!configuredNames.Contains(name))
899+
{
900+
throw new InvalidOperationException(
901+
$"The source schema configuration of '{name}' could not be parsed "
902+
+ "and no client configuration was registered for it in code.");
903+
}
904+
}
905+
}
906+
886907
// Register configurations that need post-Seal projection. The
887908
// per-type completions (Lookup.FieldType, FieldRequirements.Requirements)
888909
// were registered earlier during type completion; appending here

src/HotChocolate/Fusion/test/Fusion.Execution.Tests/Configuration/DefaultGraphQLClientConfigurationParserTests.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,55 @@ public async Task CreateClientConfigurations_Should_Throw_When_No_Parser_Claims_
387387

388388
// assert
389389
var exception = await Assert.ThrowsAsync<InvalidOperationException>(Act);
390-
Assert.Equal("No parser claimed source schema 'a'.", exception.Message);
390+
Assert.Equal(
391+
"The source schema configuration of 'a' could not be parsed and no client "
392+
+ "configuration was registered for it in code.",
393+
exception.Message);
394+
}
395+
396+
[Fact]
397+
public async Task CreateClientConfigurations_Should_Not_Throw_When_Modifier_Provides_Missing_Configuration()
398+
{
399+
// arrange
400+
// settings carry only a non-http transport, but a client configuration for "a"
401+
// is supplied in code via AddHttpClientConfiguration.
402+
var config = CreateConfigurationWithSettings(
403+
"""
404+
{
405+
"sourceSchemas": {
406+
"a": {
407+
"transports": {
408+
"xyz": { "url": "xyz://localhost" }
409+
}
410+
}
411+
}
412+
}
413+
""");
414+
415+
var configProvider = new TestFusionConfigurationProvider(config);
416+
417+
var services =
418+
new ServiceCollection()
419+
.AddGraphQLGateway()
420+
.AddConfigurationProvider(_ => configProvider)
421+
.AddHttpClientConfiguration(
422+
new HttpSourceSchemaClientConfiguration(
423+
name: "a",
424+
httpClientName: HttpSourceSchemaClientConfiguration.DefaultClientName,
425+
baseAddress: new Uri("http://localhost:5000/graphql")))
426+
.Services
427+
.BuildServiceProvider();
428+
429+
var manager = services.GetRequiredService<FusionRequestExecutorManager>();
430+
431+
// act
432+
var executor = await manager.GetExecutorAsync();
433+
434+
// assert
435+
var clientConfigs = executor.Schema.Features.GetRequired<SourceSchemaClientConfigurations>();
436+
Assert.True(clientConfigs.TryGet("a", OperationType.Query, out var queryConfig));
437+
var http = Assert.IsType<HttpSourceSchemaClientConfiguration>(queryConfig);
438+
Assert.Equal(new Uri("http://localhost:5000/graphql"), http.BaseAddress);
391439
}
392440

393441
[Fact]

0 commit comments

Comments
 (0)