Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gateway throws error when federated schema contains Subscription type #3357

Open
jsangilve opened this issue Sep 30, 2019 · 3 comments
Open

Gateway throws error when federated schema contains Subscription type #3357

jsangilve opened this issue Sep 30, 2019 · 3 comments

Comments

@jsangilve
Copy link

@jsangilve jsangilve commented Sep 30, 2019

  • Package: @apollo/gateway (but the error is caused by @apollo/federation)
  • Version: since @apollo/federation v0.9.1
  • Last known working version: v0.6.x

When a federated service's schema contains a Subscription type and it's loaded by the Apollo Gateway, the following error is returned:

GraphQLSchemaValidationError: [accounts] Subscription -> `Subscription` is an extension type, but `Subscription` is not defined

I understand Subscriptions aren't supported by Federation yet, but having them in the downstream service shouldn't affect the creation of the federated graph.

While debugging the problem, I realized the Gateway was processing the Subscription as an extension type (the same way it does with Query/Mutation), but it's not adding an empty definition type for Subscription.

To reproduce it, just run the federation demo adding a Subscription to the accounts service:

const typeDefs = gql`
  extend type Query {
    me: User
  }

  type User @key(fields: "id") {
    id: ID!
    name: String
    username: String
  }

  type Subscription {
    somethingHappened(input: String!): String!
  }
`;

Fork including the change above: https://github.com/jsangilve/federation-demo/blob/wip/example_with_subscription/services/accounts/index.js

@abernix

This comment has been minimized.

Copy link
Member

@abernix abernix commented Oct 3, 2019

Thanks for opening #3358, but I've closed it until we can discuss it a bit more. I'm curious — given the fact that subscriptions aren't supported by Apollo Gateway — if you can provide more details on the use-case where this does more than move failure from one point to another.

Elaborating: Execution of a graph with subscriptions in it is still going to be problematic, and we don't suggest exposing downstream services on their own so it feels like this just moves a failure from an earlier point to a later point, which seems like it sets false expectations for a developer which might result in disappointment after they've already put time into it.

@jsangilve

This comment has been minimized.

Copy link
Author

@jsangilve jsangilve commented Oct 6, 2019

Hey @abernix, thanks for taking the time to review the PR and look into this issue.

We have been using Apollo Federation since version 0.6.x. Our architecture is composed by different micro-services exposing GraphQL APIs; these APIs are composed together by the Apollo Gateway.

That's our basic setup — probably the most common between teams adopting Apollo Federation — and it worked, until we needed to provide real-time updates to our clients. We liked the idea of providing clients with all the info they needed through a single GQL Schema. However, given that Apollo Gateway does not support subscriptions, we looked for alternatives.

There are many ways, but I wrote down 4 different ways to overcome this issue:

  1. Directly exposing downstream service(s) for subscriptions: as you mentioned, this is not ideal. The main issue here is that each subscription might be provided by a different service (because domain boundaries) and you don't want to expose your infrastructure to clients, so you probably still want a... Gateway :).
  2. Creating a separate endpoint for Subscriptions: use a separate Apollo Server to expose Subscriptions. The Subscriptions data still comes from the micro-services — aka downstream services — but instead of directly exposing GraphQL subscriptions, they just publish the data into Redis/Postgres/GooglePubsub or any channel compatible with the PubSubEngine implementations. The Apollo server listens a resolves subscriptions.
  3. Enriching the Apollo Gateway with Subcription resolvers: until version 0.6.x, the Federated Graph composed by Apollo Gateway included the subscriptions types, but they didn't work. If you added resolvers for GQL Subscriptions at the Gateway level i.e. to the Apollo Server running the Gateway, it worked. Data for the Subscriptions was still provided by downstream services but the WebSockets and PubSub was solely handle by the ApolloServer at gateway.
  4. Not using Subscriptions at all and provide real-time updated through a different channel.

We decided to try 3, because it allowed us to give a single GQL Schema to our clients, while keeping the responsibility of defining the schema to the downstream services. Furthermore, considering that subscription resolvers were really simple — just some basic filtering based on the input parameters — we dynamically generated the resolvers after calling gateway.load().

Last week I updated to the latest version of Apollo Gateway and found the problem described on this issue. Having Subscription types in the downstream services causes a GraphQLSchemaValidationError.

GraphQLSchemaValidationError: [accounts] Subscription -> `Subscription` is an extension 
type, but `Subscription` is not defined

The error is confusing because it doesn't give a clue about Subscription not being supported by Apollo Gateway. In fact, it's actually not fully related and that's why I open the PR.

IMHO, given that Apollo Gateway doesn't support subscriptions, I would have expected the following behaviour:

If subscriptions are set to false, as described in the docs (see below), Apollo Server would just remove any Subscription type from the Federated Graph.

// https://www.apollographql.com/docs/apollo-server/federation/implementing/
const server = new ApolloServer({  
  gateway,

  // Currently, subscriptions are enabled by default with Apollo Server, however,
  // subscriptions are not compatible with the gateway.  We hope to resolve this
  // limitation in future versions of Apollo Server.  Please reach out to us on
  // https://spectrum.chat/apollo/apollo-server if this is critical to your adoption!
  subscriptions: false,
});

Otherwise, the subscription type would be composed into the Federated graph and a warning explaining that Subscriptions won't work is logged.

Reasoning: It would be easier to adopt Apollo Gateway if teams using Apollo Server don't need to change anything on the existing services (unless they want to extend other service's types), and they should only know that subscriptions won't work at the Gateway (the warning would make this clear).

As explained above, there are alternative to get subscriptions working, but that's completely optional.

Once subscriptions are supported by Apollo Gateway, the warning is removed and teams using Apollo Gateway would need to decide whether they expose them through the gateway or not (subscriptions: false).

I created a Codesandbox forking James Baxley's gateway example. You will need to fork it and change something on index.js to trigger the reload and see the GraphQLSchemaValidationError in the terminal. I had to manually load the Gateway to avoid the error thrown when gateway is defined and subscription is not false.

https://codesandbox.io/s/federation-gateway-error-with-subscriptions-6s7bt

Edit: the GraphQLSchemaValidationError is thrown, regardless of Apollo Server initialized with gateway and subscription: false properties: https://codesandbox.io/s/federation-gateway-without-loading-manually-hwzbl

@astenmies

This comment has been minimized.

Copy link

@astenmies astenmies commented Jan 28, 2020

I get this error without subscription. I'm at the first stage of debugging this so I can't provide much more info.

It only occurs in production (I can't reproduce locally yet), with pm2 running multiple instances in cluster mode.

'[tracker] Registration -> Registration is an extension type, but Registration is not defined in any service'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.