multiple subscriptions failed to complete in one websocket session
stevezhang-dstring opened this issue · 2 comments
Describe the bug
My client is Apollo react.js and the backend is graphql-java-kickstart. I have 5 GraphQL subscriptions, when the Apollo react client starts to subscript, all 5 subscriptions requests were sent to the backend server (the wireshark confirmed 5 websocket messages were sent out), but only the 1st subscript request got processed.
To Reproduce
- client side code:
const cache = new InMemoryCache();
const httpLink = new HttpLink({
uri: "http://localhost:8080/apis/graphql",
});
const authLink = setContext((request, previousContext) => ({
headers: {
...previousContext.headers,
userid: localStorage.getItem('CurrentUserId')||0,
},
}));
const wsLink = new WebSocketLink({
uri:"ws://localhost:8080/subscriptions",
options: {
reconnect: true
}
});
const link = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
authLink.concat(httpLink)
);
const client = new ApolloClient({
cache,
link,
});
..........
async componentDidMount() {
// setup the subscription on new board
var dataset = this.dataset;
// setup the subscription on new row
this.rowAddSubscription = await client
.subscribe({
query: gql(onRowAdd),
variables: {},
})
.subscribe({
next (payload) {
dataset.onRowAdd(payload.data.onRowAdd);
},
error(err) {console.error('xxx', err);},
});
// setup the subscription on new board
this.boardAddSubscription = await client
.subscribe({
query: gql(onBoardAdd),
variables: {},
}).subscribe({
next (payload) {
dataset.onBoardAdd(payload.data.onBoardAdd);
},
error(err) {console.error('xxx', err);}
});
// setup the subscription on row deletion
this.rowDeleteSubscription = await client
.subscribe({
query: gql(onRowDelete),
variables: {},
}).subscribe({
next (payload) {
dataset.onRowDelete(payload.data.onRowDelete);
},
error(err) {console.error('xxx', err);}
});
// setup the subscription on data creation
this.dataAddSubscription = await client
.subscribe({
query: gql(onDataAdd),
variables: {},
}).subscribe({
next (payload) {
dataset.onDataAdd(payload.data.onDataAdd);
},
error(err) {console.error('xxx', err);}
});
// setup the subscription on data update
this.dataUpdateSubscription = await client
.subscribe({
query: gql(onDataUpdate),
variables: {},
}).subscribe({
next (payload) {
dataset.onDataUpdate(payload.data.onDataUpdate);
},
error(err) {console.error('xxx', err);}
});
}
- at the backend server side,
when the client initiate the subscript requests, only the 1st request "rowAddSubscription" was processed.
GraphQL schema:
subscription {
onRowAdd {
id
groupID
boardID
creatorID
}
}
subscription {
onBoardAdd {
id
creatorID
rank
createdAt
}
}
subscription {
onRowDelete {
id
creatorID
rank
createdAt
}
}
subscription {
onDataAdd {
id
rowID
columnID
boardID
creatorID
value
creatorID
}
}
subscription {
onDataUpdate {
id
rowID
columnID
boardID
creatorID
value
creatorID
}
}
Expected behavior
We would like to see all the 5 subscriptions requests were processed at the backend.
Additional context
when the client initiate the request first, only the 1st subscription request was processed.
It is interesting that if we refresh the web browser connection and initiate the request again, then the 1st and 2nd subscription requests were processed;
similarly, if we refresh the web browser connection again and initiate the request again, then the 1st, 2nd, and the 3rd subscription requests were processed.
It seems apollo client issue. I have to create one ApolloClient (has a WebsocketLink) per each subscription; so each ApolloClient will maintain its own client socket with the subscription, then it works well with that subscription. So an ApolloClient can not work with multiple subscriptions?
It seems that both the Apollo client and the graphql-java-servlet server side codes are correct. I can use one ApolloClient to handle the multiple subscriptions, and the subscription resolver should use threading to handle (just like the example at https://github.com/graphql-java-kickstart/graphql-spring-boot/blob/master/example-graphql-subscription/src/main/java/graphql/kickstart/spring/web/boot/publishers/StockTickerRxPublisher.java)
I will close the bug.