Apollo Federation: buildFederatedSchema breaks Subscriptions
See original GitHub issueIntro
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:
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.
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());
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:
- Created 4 years ago
- Reactions:16
- Comments:33 (2 by maintainers)
Top GitHub Comments
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
Up. We waiting for subscriptions in federation 😃