Search code examples
graphqlhotchocolate

HotChocolate merge two services that have the same schema


I'd like to use HotChocolate to create an API composition gateway stitching GraphQL from multiple services. This works great when each service has their own schema. However, I also have a case that two services are serving up items with the same schema. Can I do this?

For example, imagine two different library services, both serving up books. I'd like the gateway in this case to forward requests for the Book schema to all services and merge the results. Here's some code snippets for what I've tried.

Server setup:

var builder = WebApplication.CreateBuilder();
builder.Services.AddGraphQLServer()
    .AddRemoteSchema(WellKnownSchemaNames.Books)
    .AddRemoteSchema(WellKnownSchemaNames.Authors)    
    .AddTypeExtensionsFromFile("./Stitching.graphql");

builder.Services.AddHttpClient(WellKnownSchemaNames.Books, c => c.BaseAddress = new Uri("http://localhost:7011/graphql"));
builder.Services.AddHttpClient(WellKnownSchemaNames.Authors, c => c.BaseAddress = new Uri("http://localhost:7012/graphql"));
// Notice this client has the same schema but a different port
builder.Services.AddHttpClient(WellKnownSchemaNames.Books, c => c.BaseAddress = new Uri("http://localhost:7013/graphql"));

var app = builder.Build();
app.MapGraphQL();
app.Run($"http://localhost:7010");

The schema and query for book is pretty straightforward:

public class Book
{
    public string Id { get; set; }    
    public string Title { get; set; }
}
public class BooksQuery
{    
    public static Book[] _books;  // Set during initialization, differently on the two endpoints.
    public Book[] Books => _books;
    public Book GetBook(string id) => _books.Single(b => b.Id == id);
}

Ideally:

  • books => Query both endpoints, merge and return the results.
  • book(id: "x") => Query both endpoints, if any endpoint returns a non-error, return its results.

HotChocolate appears to only hit one of the two Books endpoints.


Solution

  • If you have 2 schema with the same query and they are stitched together, the second query will have its query name changed to start with the schema name.

    See more about collision resolver here: https://chillicream.com/docs/hotchocolate/v13/distributed-schema/schema-configuration#rename-types