Apollo Federation

"Implement a single data graph across multiple services"

Specification

Scope

Tanka GraphQL implements the service section of the Apollo Federation specification allowing GraphQL service implemented using it to be joined into graph managed by Gateway.

Installation

Support is provided as an NuGet package.

dotnet add package Tanka.GraphQL.Extensions.ApolloFederation

Usage

Creating a service requires two steps:

  1. Define entities in service schema
  2. Create federation service from schema

First step is achived by extending the schema with federation directives which allow you to define your entities. Extending is done by first adding the directives to schema using AddFederationDirectives SchemaBuilder extension method. Use @key directive to mark object or interface as an entity and specify key fields.

Second step is after you have your basic schema with entities specified and it will add the required extension points to schema, mainly additional fields to query root type.

Example

        public static ISchema Create()
        {
            var builder = new SchemaBuilder()
                .AddFederationDirectives();

            var typeDefs = @"
type Review @key(fields: ""id"") {
    id: ID!
    body: String
    author: User @provides(fields: ""username"")
    product: Product
}

type User @key(fields: ""id"") @extends {
    id: ID! @external
    username: String @external
    reviews: [Review]
}

type Product @key(fields: ""upc"") @extends {
    upc: String! @external
    reviews: [Review]
}

type Query {
}
";

            builder.Sdl(typeDefs);

            builder.UseResolversAndSubscribers(
                new ObjectTypeMap
                {
                    ["User"] = new FieldResolversMap
                    {
                        {"id", Resolve.PropertyOf<User>(u => u.ID)},
                        {"username", UserUsername},
                        {"reviews", UserReviews}
                    },
                    ["Review"] = new FieldResolversMap
                    {
                        {"id", Resolve.PropertyOf<Review>(r => r.ID)},
                        {"body", Resolve.PropertyOf<Review>(r => r.Body)},
                        {"author", ReviewAuthor},
                        {"product", Resolve.PropertyOf<Review>(r => r.Product)}
                    },
                    ["Product"] = new FieldResolversMap
                    {
                        {"upc", Resolve.PropertyOf<Product>(p => p.Upc)},
                        {"reviews", ProductReviews}
                    }
                });

            var schema = builder.Build();

            // create federated service from builder and add 
            // reference resolvers
            var federationBuilder = Federation.ServiceFrom(
                schema,
                new DictionaryReferenceResolversMap
                {
                    ["User"] = UserReference,
                    ["Product"] = ProductReference
                });

            return SchemaTools.MakeExecutableSchemaWithIntrospection(federationBuilder);
        }

Demo

Demo is provided as an fork of the federation demo. It's modified to use Tanka.GraphQL.Dev.Reviews project as an replacement for reviews service.

git clone https://github.com/pekkah/tanka-graphql.git

cd tanka-graphql/dev/GraphQL.Dev.Reviews
dotnet run
git clone https://github.com/pekkah/federation-demo.git
cd federation-demo
git switch tanka-graphql-reviews-service
npm run start-services

# in a yet another prompt
npm run start-gateway

# open http://localhost:4000 in your browser to test the service