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.

client.stop() should call close on websocket link

See original GitHub issue

Intended outcome:

As per the documentation of the function Client.stop, it should be ready to recycle the client once it is called. Meaning the websocket connection should be closed.

Actual outcome:

Currently, the websocket connection is NOT closed. This is problematic since a very common use case if to recycle the client when the authorization token changes. If a user is not careful, he will end up creating a lot of websocket connections to the backend.

How to reproduce the issue:

  1. Create a client with the WebsocketLink
  2. Call stop on the client
  3. Observe the network tab, the connection is not closed

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:11
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

6reactions
vsylvestrecommented, Nov 13, 2020

While we’re waiting for an official implementation (and for anyone who’s looking at the issue https://github.com/apollographql/apollo-link/issues/197 and still wondering how to refresh connectionParams), here’s how my team and I were finally able to do it in React:

import * as React from "react";
import { ApolloClient, HttpLink, InMemoryCache, split } from "@apollo/client";
import { WebSocketLink } from "@apollo/client/link/ws";
import { SubscriptionClient } from "subscriptions-transport-ws";
import { getMainDefinition } from "@apollo/client/utilities";

const client = new ApolloClient({
  cache: new InMemoryCache()
});

export default function useClient(userId: string) {
  const subscriptionClient = React.useRef<SubscriptionClient>(null);

  React.useEffect(() => {
    if (userId) {
      if (subscriptionClient.current) {
        subscriptionClient.current.close();
      }
      subscriptionClient.current = new SubscriptionClient(
        "ws://localhost:3000/graphql",
        {
          reconnect: true,
          connectionParams: { userId }
        }
      );
    }
  }, [userId]);

  const splitLink = React.useMemo(() => {
    const httpLink = new HttpLink({
      uri: `http://localhost:3000//graphql`
    });

    if (userId && subscriptionClient.current) {
      const websocketLink = new WebSocketLink(subscriptionClient.current);

      return split(
        ({ query }) => {
          const definition = getMainDefinition(query);
          return (
            definition.kind === "OperationDefinition" &&
            definition.operation === "subscription"
          );
        },
        websocketLink,
        httpLink
      );
    }

    return httpLink;
  }, [userId]);

  React.useEffect(() => {
    client.setLink(splitLink);
  }, [splitLink]);

  return client;
}

The main trick was to use SubscriptionClient as the parameter to the WebSocketLink instance. This gives us the option to close the connection when we need it, directly using the subscription client. In the above scenario, that’s also the mechanism we use in order to refresh our connection params.

3reactions
enisdenjocommented, Nov 16, 2020

Hey @Sytten, maybe you can give graphql-ws a spin. 😄

Offering a completely different Protocol you’d have to use the same lib server side too; but, no stress - there are recipes in the readme for using it with Apollo both server and client side!

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to terminate a WebSocket connection? - Stack Overflow
According to the ws documentation, you need to call websocket.close() to terminate a connection. let server = new WebSocketServer(options); ...
Read more >
WebSocket.close() - Web APIs - MDN Web Docs
close() method closes the WebSocket connection or connection attempt, if any. If the connection is already CLOSED , this method does nothing.
Read more >
How to Close a WebSocket (Correctly) - Forty Years of Code
Either the client or the server sends a Close frame (WebSockets borrow ... its own Close frame in response, and then both parties...
Read more >
Close the client to avoid the connections limit - Amazon Neptune
It is important to close the client when you are finished with it to ensure that the WebSocket connections are closed by the...
Read more >
WebSockets - Closing a Connection - Tutorialspoint
Close event marks the end of a communication between the server and the client. Closing a connection is possible with the help of...
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