Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hasura Subscriptions are not working in ngx-admin but working in other Angular projects #5987

Closed
1 of 3 tasks
bogi158 opened this issue May 30, 2023 · 1 comment
Closed
1 of 3 tasks

Comments

@bogi158
Copy link

bogi158 commented May 30, 2023

Issue type

  • bug report
  • feature request
  • question about the decisions made in the repository

Issue description

Current behavior:
Configuring Apollo to connect to Hasura and trying to setup a GraphQL subscription does not work. No errors or anything else, just does not work.

Expected behavior:
Results of the subscription should be received correctly

Steps to reproduce:
Clone ngx-admin, configure Apollo and try to setup a subscription.

In details:
I have created a simple Angular project (call it Base Demo) and configured Apollo and the subscriptions are indeed working. I am using the same node version and the same libraries and library versions of ngx-admin.

If I use the same exact code to configure GraphQL in ngx-admin (I just cloned the project to be sure I haven't added any code of mine), it just does not work. Nothing is displayed as result of a subscription, but I also do not get any error. The ws connection in the browser console looks exactly the same as in the Base Demo project.

Related code:

// GraphQLModule.ts
import {NgModule} from '@angular/core';
import {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular';
import {ApolloClientOptions, InMemoryCache, split} from '@apollo/client/core';
import {HttpLink} from 'apollo-angular/http';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
import { getMainDefinition } from '@apollo/client/utilities';

const uri = 'http://localhost:8080/v1/graphql';
const wsUri = 'ws://localhost:8080/v1/graphql';

export function createApollo(httpLink: HttpLink, http: HttpClient): ApolloClientOptions<any> {

var token = "<token>";
   
  const authLink = httpLink.create({
    uri,
    headers: !token ? new HttpHeaders() : 
      new HttpHeaders()
        .set('Authorization', `Bearer ${token}`)
        .set('x-hasura-role', "manager"),
  });

  const wsLink = new GraphQLWsLink(createClient({
    url: wsUri,
    connectionParams: {
      headers: !token ? {} : 
      {
        Authorization: `Bearer ${token}`,
        'x-hasura-role': "user",
      }
    }
  }));

  // The split function takes three parameters:
  //
  // * A function that's called for each operation to execute
  // * The Link to use for an operation if the function returns a "truthy" value
  // * The Link to use for an operation if the function returns a "falsy" value
  const splitLink = split(
    ({ query }) => {
      const definition = getMainDefinition(query);
      return (
        definition.kind === 'OperationDefinition' &&
        definition.operation === 'subscription'
      );
    },
    wsLink,
    authLink,
  );
  
  return {
    cache: new InMemoryCache({
      addTypename: false,
    }),
    link: splitLink,
  };
}

@NgModule({
  exports: [ApolloModule],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink, HttpClient],
    },
  ],
})
export class GraphQLModule {}
import { Component, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ApiService } from '../../../services/api.service';

@Component({
  selector: 'app-subscription-page',
  templateUrl: './subscription-page.component.html',
  styleUrls: ['./subscription-page.component.scss']
})
export class SubscriptionPageComponent implements OnInit {

  data: any;
  subscription?: Subscription;

  constructor(
    private api: ApiService,
  ) {}

  ngOnInit(): void {
    this.subscription = this.api.subscribe()
      .subscribe({
        next: (v) => this.data = v,
        error: (e) => console.error(e),
        complete: () => console.info('complete') 
    })
  }

  ngOnDestroy(): void {
    this.subscription?.unsubscribe();
  }

}

Other information:

npm, node, OS, Browser

Node, npm: node v14.21.3 (npm v6.14.18)
OS: Uubntu 18.04
Browser: Chrome, Firefox

Angular, Nebular

Angular 13.3.12
Nebular 9.1.0-rc.8
@bogi158
Copy link
Author

bogi158 commented May 30, 2023

After wasting more than 8 hrs between last week and today trying to find what was the problem, looking line by line every file and configuration and doing some tests, I have finally found the solution.
The culprit is pace-js, that is inlcuded in ngx-admin but in the end I have never used. pace-js tracking the websockets causes some problems, so the solution was to disable that tracking:

(window as any).paceOptions = {
  ajax: {
      trackWebSockets: false
  }
};

Now everything works. I will be actually completely eliminate pace-js as I am not using it anyway.

@bogi158 bogi158 closed this as completed May 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant