Unhandled GraphQL subscription error, when using apollos subscribeToMore method in an angular chat component for subscription

Unhandled GraphQL subscription error, when using apollos subscribeToMore method in an angular chat component for subscription


5

Problem Description

I have a chat component in angular that gets messages from the backend via a graphql query.
On the same query, I subscribe to updates when a new message is added via a graphql mutation.

The messages subscription is coded as a method of the chat component so that I can invoke it in the angular life cycle method when the component first renders.

This is the usual set up for a subscription as per the documentation in apollo:
https://apollo-angular.com/docs/data/subscriptions

when I invoke the method that has the subscription coded into it, I get the following error:

"Cannot use GraphQLSchema "[object GraphQLSchema]" from another module or realm.
Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.
https://yarnpkg.com/en/docs/selective-version-resolutions
Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results."

I know that the error came from the invocation of that method, when I comment out the invocation, the error disappears.
The subscription does not query the backend, so I know that the issue is on the client-side.

Expected Behaviour

When a user sends a new message in the chat, the server is notified that a message update has occurred on the subscription resolver (server-side), it will fire back in realtime all the messages to the front end, and the messages should be returned via the subscribe to more method.

Steps I took to solve this issue

I tried to look at this question:
Duplicate "graphql" modules cannot be used

which led me to this link:
https://github.com/graphql/graphql-js/issues/491

there was a workaround there for people that use yarn as their package manager, but that does not concern me since I use npm.

I thought maybe there was a duplicate graphql module, so I tried to clean up my package.json file, deleting the node modules and re-installing them, but that did not work.

Code Examples

Chat Component

import { Component, OnInit } from '@angular/core';
import { Apollo, QueryRef, gql } from 'apollo-angular';

const MESSAGES_SUBSCRIPTION = gql`
   subscription {
     messagesAdded {
      id
      content
      user
    }
  }
`;

const GET_MESSAGES = gql`
   query messages{
     messages {
      id
      content
      user
    }
  } `;


 const POST_MESSAGE = gql`
   mutation($user: String!, $content: String!) {
           postMessage(user: $user, content: $content)
   }`;

export class ChatComponent implements OnInit {

 msgsQuery: QueryRef<any>;
 isShowen: boolean = false;  
 isMinimized: boolean = false;
 msgs: any;
 content:String = '';

 constructor(private apollo: Apollo) {
  this.msgsQuery = this.apollo.watchQuery({
    query: GET_MESSAGES
  });

  this.msgsQuery.valueChanges
  .subscribe(({data}:any) => {
    this.msgs = data.messages;
  });
 }

 ngOnInit(): void {
   //this.subscribeToNewMsgs(); //Error is logged when invoked
 }

 subscribeToNewMsgs() {
   this.msgsQuery.subscribeToMore({
    document: MESSAGES_SUBSCRIPTION,
    updateQuery: (prev, {subscriptionData}) => {
     if (!subscriptionData.data) {
       return prev;
     }

     const newMsgs = subscriptionData.data.messages;
     console.log(newMsgs)

     return {
      entry: {
        msgs: [...newMsgs, ...prev.entry.messages]
      }
     };
    }
  });
 }

 sendMsg(){
  this.apollo.mutate({
    mutation: POST_MESSAGE,
    variables: {
      user: 'Test',
      content: this.content
    }
  }).subscribe(({ data }) => {
    console.log('got data', data);
  },(error) => {
    console.log('there was an error sending the query', error);
  });
 }

}

Dependencies from the package.json file

{  
 "dependencies": {
    "@angular/animations": "~10.1.3",
    "@angular/common": "~10.1.3",
    "@angular/compiler": "~10.1.3",
    "@angular/core": "~10.1.3",
    "@angular/forms": "~10.1.3",
    "@angular/platform-browser": "~10.1.3",
    "@angular/platform-browser-dynamic": "~10.1.3",
    "@angular/router": "~10.1.3",
    "@apollo/client": "^3.3.3",
    "@cloudinary/angular-5.x": "^1.3.3",
    "apollo-angular": "^2.2.0",
    "apollo-angular-link-http": "^1.11.0",
    "apollo-cache-inmemory": "^1.6.6",
    "apollo-utilities": "^1.3.4",
    "cloudinary-core": "^2.11.3",
    "graphql": "^15.4.0",
    "ng-image-slider": "^2.6.4",
    "ng2-file-upload": "^1.4.0",
    "react": "^17.0.1",
    "rxjs": "~6.6.0",
    "subscriptions-transport-ws": "^0.9.18",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2"
 },
}

The Client-side subscription setup is coded according to the apollo documentation:
[See Client setup] (https://apollo-angular.com/docs/data/subscriptions)

I did not include the server-side code since subscribeToMore never sends data back when a new message is sent since it is met with the described error.
I am using Angular v 10.1.6.

1 Answer
1


0

One potential place where you can look at is in the server index double check the URL of the WebSocket. For example I had a error that was caused inside this code:

const wsServer = new WebSocketServer({
server: httpServer,
path: 'graphql/subscriptions',
})

Not in the above the address is wrong and should be fixed by including "/" as the following:

    path: '/graphql/subscriptions',

That is one idea where one can look at. Another place that I had minor omission is returning the Subscription inside the resolver

return pubsub.asyncIterator ..... 

had missing return.



Leave a Reply

Your email address will not be published. Required fields are marked *