[Question]: Subscriptions don't close and don't receive data
I'm running into issues using subscriptions-transport-ws with this. The subscriptions never close and don't seem to be getting data.
import { SubscriptionClient } from 'subscriptions-transport-ws'
// ...
const client = new SubscriptionClient('/api/graphql', {
reconnect: true
})
function getSubscribeFn(client) {
return (operation, variables) => {
return client.request({ query: operation.text, variables, operationName: operation.name })
}
}
// ...
{
subscribeFn: getSubscribeFn(client)
}
}
It would be nice to export a subscribeFn to properly handle subscriptions.
It could easily just accept a SubscriptionClient instance.
This doesn't seem like the correct solution but it is now properly closing subscriptions. Can someone confirm or provide a correct solution?
{
subscribeFn: (operation, variables) => {
return Observable.create(sink =>
// @ts-ignore
client.request({ query: operation.text, variables, operationName: operation.name }).subscribe(sink)
)
}
}
This is the solution we're using, I clipped out our authentication and error handling. I haven't used Observables enough to say if it is equivalent to the solution you are using.
const client = new SubscriptionClient(wsUrl, { lazy: true, reconnect: true });
const subscribeFn = (operation, variables) => {
const query = operation.text;
if (!query) return;
const request = client.request({ query, variables });
return {
subscribe: observer => {
const subscription = request.subscribe(observer);
observer.start(subscription);
},
};
};
@AnotherHermit Thanks for the example of how you're handling it. It worked for me as well.
I did have some issues with the typings that said that dispose was required. Is there any interest in offering a minimal function that accepts a SubscriptionClient and returning a subscribeFn so users don't have to worry about this stuff?
This is basically what I'm thinking about.
function getSubscribeFn(client: SubscriptionClient) {
return (operation: ConcreteBatch, variables: Variables) => {
const query = operation.text
if (!query) return
const request = client.request({
query,
variables,
operationName: operation.name,
})
return {
subscribe: observer => {
const subscription = request.subscribe(observer)
observer.start(subscription)
},
dispose: () => {
client.unsubscribeAll()
client.close()
},
}
}
}
I've followed an article and ended up with this:
import { execute } from 'apollo-link';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import { WebSocketLink } from 'apollo-link-ws';
const subscriptionClient = new SubscriptionClient('ws://localhost:4000/graphql', {
lazy: true,
reconnect: true,
});
const webSocketLink = new WebSocketLink(subscriptionClient);
const subscribeFn = (operation, variables) =>
execute(webSocketLink, {
query: operation.text,
variables,
});
Haven't deployed to production yet, but it seems to work well.