question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Apollo Federation: buildFederatedSchema breaks Subscriptions

See original GitHub issue

Intro

First of all I want to say that I really like the Apollo Federation as an idea. And it works well now for all Queries and Mutations. Unfortunately, this isn’t the case for Subscriptions.

Problem

When I use buildFederatedSchema for ApolloServer config I get the Network Error on the client side: image

Interestingly, the same code works well with mergeTypes and mergeResolvers.

As I understand there is a server side problem. And I will explain this point below.

Description

I will show you two solutions. Working and not working ones. For simplicity, I will omit the splitting into files and unnecessary pieces of code.

Common code parts:

/* app.js */

const GraphQLConfig = require('./graphql.config');

const app = new Koa();

const apolloServer = new ApolloServer(GraphQLConfig);
apolloServer.applyMiddleware({
  app,
  path: '/graphql',
});

app.listen({ port: config.port }, () => { /* nothing important here */ });

const WS_PORT = 5000;
const websocketServer = createServer(app);

apolloServer.installSubscriptionHandlers(websocketServer);

websocketServer.listen(WS_PORT, () => { /* nothing important here */ });
/* graphql.config.js */

const gql = require('apollo-server-koa').gql;
const PubSub = require('graphql-subscriptions').PubSub;

const messageSchema = {};

messageSchema.typeDefs = gql`
  type Subscription {
    messageAdded: Message
  }

  type Message {
    text: String!
  }

  type Mutation {
    createMessage (text: String!) : Message
  }
`;

const pubsub = new PubSub();
const MESSAGE_ADDED = 'MESSAGE_ADDED';

messageSchema.resolvers = ({
  Subscription: {
    messageAdded: {
      subscribe: () => pubsub.asyncIterator(MESSAGE_ADDED),
    }
  },
  Mutation: {
    createMessage: () => {
      const message = ({ text: 'I must be sent.' });
      pubsub.publish(MESSAGE_ADDED, { messageAdded: message });
      return message;
    },
  },
});

module.exports = ({
  /* (typeDefs & resolvers) or schema */
  context: () => { /* ... */ },
  uploads: false,
  subscriptions: {
    path: '/graphql',
    onConnect: () => { /* ... */ },
    onDisconnect: () => { /* ... */ },
  },
  formatError: (err) => {
    console.log(err);
  },
});

Working case:

  const mergeTypes = require('merge-graphql-schemas').mergeTypes;
  const mergeResolvers = require('merge-graphql-schemas').mergeResolvers;

  /* code above */

 const typeDefs =  mergeTypes([
    MessageSchema.typeDefs,
   /* ... */
  ], { all: true });

 const resolvers =  mergeResolvers([
    MessageSchema.resolvers,
    /* ... */
 ]);

module.exports = ({
  typeDefs,
  resolvers,
  /* ... */
});

Not working one:

 const buildFederatedSchema = require('@apollo/federation').buildFederatedSchema;

  /* ... */

 const schema = buildFederatedSchema([
    MessageSchema,
    /* ... */
 ]);

module.exports = ({
  schema,
  /* ... */
});

Config’s formatError doesn’t catch any error here. But on the client side I can see Network Error by using this code:

 import { onError } from 'apollo-link-error';

 const link = /* ... */

 const errorLink = onError(({ graphQLErrors, networkError }) => {
   if (graphQLErrors) /* ... */
   if (networkError) {
     console.log('[Network error]', networkError);
   };
 }

 const client = new ApolloClient({
    link:  errorLink.concat(link),
 });
});

However, I managed to find the file in node_modules which throwing the error:

/* server/node_modules/graphql/subscription/subscribe.js */

/* ... */

function createSourceEventStream(schema, /* ... */) {
 const fieldDef = /* some actions with schema */;
  /* ... */
 const eventStream = /* some actions with fieldDef */
 /* ... */
 throw new Error('Subscription field must return Async Iterable. Received: ' + inspect(eventStream));
}

I tried to display the contents of the fieldDef on the console and it hasn’t subscribe field, so eventStream variable becomes undefined here! So network error is expected.

image

But where is my subscribe method? I know, that it’s defined well because:

console.log('I)', typeof resolvers.Subscription.messageAdded.subscribe);
console.log('II)', resolvers.Subscription.messageAdded.subscribe());

image

Packages (server):

 "dependencies": {
    "@apollo/federation": "^0.6.0",
    "apollo-server-koa": "^2.6.1",
    "graphql": "^14.3.1",
    "graphql-subscriptions": "^1.1.0",
    "koa": "^2.7.0",
    "merge-graphql-schemas": "^1.5.8",
    "subscriptions-transport-ws": "^0.9.16",
  },

Packages (client):

 "dependencies": {
    "apollo-boost": "^0.3.1",
    "apollo-cache-inmemory": "^1.6.0",
    "apollo-client": "^2.6.0-rc.3",
    "apollo-link": "^1.2.11",
    "apollo-link-http": "^1.5.14",
    "apollo-link-ws": "^1.0.17",
    "apollo-utilities": "^1.3.0",
    "graphql": "^14.3.1",
    "graphql-tag": "^2.10.1",
    "graphql-tools": "^4.0.4",
    "react": "^16.8.6",
    "react-apollo": "^2.5.6",
    "subscriptions-transport-ws": "^0.9.16",
  },

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:16
  • Comments:33 (2 by maintainers)

github_iconTop GitHub Comments

89reactions
mm7modcommented, Aug 23, 2019

is there an estimate for the new version release date that will support subscriptions with federation ? my app relies heavily on subscriptions but I want to use federations as my schema is getting big

77reactions
herenicknamecommented, Jun 21, 2019

Up. We waiting for subscriptions in federation 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Introduction to Apollo Federation - Apollo GraphQL Docs
Apollo Federation does not currently support GraphQL subscription operations. Combining subgraph schemas. Like any other GraphQL API, each subgraph has its own ...
Read more >
Implementing Federated GraphQL Microservices using Apollo ...
Implement a single distributed data graph across multiple services without creating any dependencies using Apollo federation. Learn more about it here.
Read more >
Getting Started with Apollo Federation and Gateway
The beauty of Apollo Federation is that it allows you to split an API ... rather than being limited to breaking up a...
Read more >
Your First Federated Schema with Apollo Server - YouTube
Talk by Mandi Wise, Author of Advanced GraphQL with Apollo & React and Owner, 8-Bit Press Inc.Since its launch last year, Apollo Federation...
Read more >
Nestjs GraphQL Apollo Federation - resolver has an object in ...
In short, I had two Interceptors that changed the response and broke the GraphQL API.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found