/sangria-federated

Running a sangria server as federated

Primary LanguageScalaApache License 2.0Apache-2.0

Sangria Logo

sangria-federated

Continuous Integration Maven Central License Scaladocs Join the chat at https://gitter.im/sangria-graphql/sangria

sangria-federated is a library that allows sangria users to implement services that adhere to Apollo's Federation Specification, and can be used as part of a federated data graph.

SBT Configuration:

libraryDependencies += "org.sangria-graphql" %% "sangria-federated" % "<latest version>"

How does it work?

The library adds Apollo's Federation Specification on top of the provided sangria graphql schema.

To make it possible to use _Any as a scalar, the library upgrades the used marshaller.

Implementation of the Apollo Federation Subgraph Compatibility

A good example showing all different features is the sangria implementation of the Apollo Federation Subgraph Compatibility.

Example how to use it

All the code of this example is available here.

To be able to communicate with Apollo's federation gateway, the graphql sangria service should be using both the federated schema and unmarshaller.

As an example, let's consider the following services:

  • a review service provides a subgraph for review
  • a state service provides a subgraph for states. This state is used by reviews.
  • both subgraphs are composed into one supergraph that is the only graph exposed to users. With that, users can interact with reviews and states as if they were implemented in one service.

The state service

The state service defines the state entity annotated with @key("id").

For each entity, we need to define an entity resolver.

It's highly recommended to use Deferred Value Resolution in those resolvers to batch the fetching of the entities.

Implementation of the State GraphQL API.

The entity resolver implements:

  • the deserialization of the fields in _Any object to the EntityArg.
  • how to fetch the proper Entity (in our case State) based on the EntityArg.

In the definition of the GraphQL server, we federate the Query type and the unmarshaller while supplying the entity resolvers. Then, we use both the federated schema and unmarshaller as arguments for the server:

def graphQL[F[_]: Async]: GraphQL[F, StateService] = {
  val (schema, um) = Federation.federate[StateService, Any, Json](
    Schema(StateAPI.Query),
    sangria.marshalling.circe.CirceInputUnmarshaller,
    stateResolver)

  GraphQL(schema, DeferredResolver.fetchers(StateGraphQLSchema.states), ctx.pure[F])(Async[F], um)
}

The stateResolver delegates the resolution of the state entities to a Fetcher, allowing the state service to resolve the state entities based on the provided ids in one batch.

The GraphQL server uses the provided schema and unmarshaller as arguments for the sangria executor: implementation

The review service

  • The review service defines the Review type, which has a reference to the State type.

    implementation of Review GraphQL API

  • As State is implemented by the state service, we don't need to implement the whole state in the review service. Instead, for each entity implemented by another service, a stub type should be created (containing just the minimal information that will allow to reference the entity).

    implementation of the stub type State (notice the usage of the @external directive).

  • In the end, the same code used to federate the state service is used to federate the review service.

Federation router

The federation router can expose the GraphQL endpoint, and resolve any GraphQL query using our sangria GraphQL services.

The sangria GraphQL services endpoints are configured in the supergraph configuration, used by rover to compose the supergraph:

federation_version: 2
subgraphs:
  state:
    schema:
      subgraph_url: http://localhost:9081/api/graphql
  review:
    schema:
      subgraph_url: http://localhost:9082/api/graphql

Caution 🚨🚨

  • This is a technology preview. We are actively working on it and cannot promise a stable API yet.
  • It's highly recommended to use Deferred Value Resolution in the EntityResolver to batch the fetching of the entities.
  • The library upgrades the marshaller to map values scalars (e.g. json objects as scalars). This can lead to security issues as discussed here.

Contribute

Contributions are warmly desired 🤗. Please follow the standard process of forking the repo and making PRs 🤓

License

sangria-federated is licensed under Apache License, Version 2.0.