Skip to content

Commit

Permalink
Introduced subgraph consistency check. (#6493)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib authored Aug 30, 2023
1 parent 0375946 commit 990e08e
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<values>
<value name="StillAlive" type="qword">133378551816226300</value>
</values>
11 changes: 11 additions & 0 deletions src/HotChocolate/Fusion/src/Composition/LogEntryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ public static LogEntry FieldDependencyCannotBeResolved(
code: LogEntryCodes.FieldDependencyCannotBeResolved,
coordinate: coordinate,
schema: schema);

public static LogEntry TypeNotDeclared(MissingType type, Schema schema)
=> new(
string.Format(LogEntryHelper_TypeNotDeclared, type.Name, schema.Name),
LogEntryCodes.TypeNotDeclared,
severity: LogSeverity.Error,
coordinate: new SchemaCoordinate(type.Name),
member: type,
schema: schema);
}

static file class LogEntryCodes
Expand All @@ -133,4 +142,6 @@ static file class LogEntryCodes
public const string CoordinateNotAllowedForRequirements = "HF0007";

public const string FieldDependencyCannotBeResolved = "HF0008";

public const string TypeNotDeclared = "HF0009";
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using HotChocolate.Language;
using HotChocolate.Skimmed;
using HotChocolate.Skimmed.Serialization;
using static HotChocolate.Fusion.Composition.LogEntryHelper;
using IHasDirectives = HotChocolate.Skimmed.IHasDirectives;

namespace HotChocolate.Fusion.Composition.Pipeline;
Expand Down Expand Up @@ -29,6 +30,11 @@ public async ValueTask InvokeAsync(CompositionContext context, MergeDelegate nex
{
context.Subgraphs.Add(schema);
}

foreach (var missingType in schema.Types.OfType<MissingType>())
{
context.Log.Write(TypeNotDeclared(missingType, schema));
}
}

await next(context).ConfigureAwait(false);
Expand Down Expand Up @@ -112,7 +118,7 @@ private static void TryCreateMissingType<T>(
if (targetType.Kind != sourceType.Kind)
{
context.Log.Write(
LogEntryHelper.MergeTypeKindDoesNotMatch(
MergeTypeKindDoesNotMatch(
sourceType,
sourceType.Kind,
targetType.Kind));
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,7 @@ Source Arguments: {2}</value>
<data name="DirectivesHelper_GetRequireDirective_NoFieldArg" xml:space="preserve">
<value>The require directive must have a value for the argument field.</value>
</data>
<data name="LogEntryHelper_TypeNotDeclared" xml:space="preserve">
<value>The type `{0}` is not declared on subgraph {1}. Check the subgraph schema for consistency.</value>
</data>
</root>
109 changes: 109 additions & 0 deletions src/HotChocolate/Fusion/test/Composition.Tests/ErrorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using CookieCrumble;
using HotChocolate.Fusion.Shared;
using HotChocolate.Skimmed.Serialization;
using Xunit.Abstractions;

namespace HotChocolate.Fusion.Composition;

public class ErrorTests
{
private readonly ITestOutputHelper _output;
private readonly Func<ICompositionLog> _logFactory;

public ErrorTests(ITestOutputHelper output)
{
_output = output;
_logFactory = () => new TestCompositionLog(output);
}

[Fact]
public async Task Typo_In_Schema()
{
const string schema =
"""
type Author {
id: ID!
reviews: ReviewConnection
}
type Book {
id: ID!
reviews: ReviewConnection
}
input CreateReviewInput {
bookId: ID!
reviewerId: ID!
authorId: ID!
comment: String!
rating: Int!
}
input DeleteReviewInput {
id: ID!
}
type Review {
id: ID!
bookId: ID!
reviewerId: ID!
authorId: ID!
comment: String!
rating: Int!
}
type ReviewConnection {
items: [Review]
nextToken: String
}
type Mutation {
createReview(input: CreateReviewInput!): Review
deleteReview(input: DeleteReviewInput!): Review
}
type Query {
getReview(id: ID!): Review
listReviews(limit: Int, nextToken: String): ReviewConnection
queryReviewsByBook(bookId: ID!, limit: int, nextToken: String): ReviewConnection
queryReviewsByReviewer(reviewerId: ID!, limit: int, nextToken: String): ReviewConnection
queryReviewsByAuthor(authorId: ID!, limit: int, nextToken: String): ReviewConnection
}
schema {
query: Query,
mutation: Mutation
}
""";

var log = new ErrorCompositionLog();
var composer = new FusionGraphComposer(logFactory: () => log);

var fusionConfig = await composer.TryComposeAsync(
new[]
{
new SubgraphConfiguration(
"Test123",
schema,
Array.Empty<string>(),
new IClientConfiguration[]
{
new HttpClientConfiguration(new Uri("http://localhost"))
})
});

Assert.Null(fusionConfig);
Assert.True(log.HasErrors);
Assert.Collection(
log.Errors,
a =>
{
Assert.Equal(
"The type `int` is not declared on subgraph Test123. " +
"Check the subgraph schema for consistency.",
a.Message);
Assert.Equal("HF0009", a.Code);
});
}
}
17 changes: 17 additions & 0 deletions src/HotChocolate/Fusion/test/Shared/TestCompositionLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,20 @@ public void Write(LogEntry entry)
_output.WriteLine(entry.Message);
}
}

public sealed class ErrorCompositionLog : ICompositionLog
{
private readonly List<LogEntry> _errors = new();

public bool HasErrors => _errors.Count > 0;

public List<LogEntry> Errors => _errors;

public void Write(LogEntry entry)
{
if(entry.Severity == LogSeverity.Error)
{
_errors.Add(entry);
}
}
}

0 comments on commit 990e08e

Please sign in to comment.