0

In the graphql server, i use this code to setup:

app.module.ts

GraphQLModule.forRoot({
      playground: true,
      typePaths: ['./**/*.graphql'],
      driver: ApolloDriver,
      installSubscriptionHandlers: true,
      subscriptions: {
        'graphql-ws': true,
        'subscriptions-transport-ws': true,
      },
    }),

cache-invalidation.resolver.ts

@Subscription(Constant.TOUR_CACHE_INVALIDATION_EVENT, {
    resolve: (payload) => {
      return payload;
    },
  })
  registerCacheInvalidation() {
    this.logger.log('registerCacheInvalidation');
    return this.pubSub.asyncIterator(Constant.TOUR_CACHE_INVALIDATION_EVENT);
  }

In the nestjs server used as apollo client, i used this code:

import { Injectable, Logger } from '@nestjs/common';
import {
  ApolloClient,
  ApolloLink,
  HttpLink,
  InMemoryCache,
  split,
} from '@apollo/client/core';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { Cron, CronExpression } from '@nestjs/schedule';
import { Constant } from 'src/common/constant';
import { createClient } from 'graphql-ws';
import { getMainDefinition } from '@apollo/client/utilities';
import WebSocket from 'ws';
import fetch from 'cross-fetch';

@Injectable()
export class SubscribeService {
  private readonly logger = new Logger(SubscribeService.name);
  private readonly wsLink: GraphQLWsLink;
  private readonly httpLink: HttpLink;
  private readonly splitLink: ApolloLink;
  private client: ApolloClient<any>;
  constructor() {
    this.wsLink =
      typeof window !== 'undefined'
        ? new GraphQLWsLink(
            createClient({
              webSocketImpl: WebSocket,
              url: process.env.WS_MAIN_WRITE_API,
            }),
          )
        : null;
    this.httpLink = new HttpLink({
      uri: process.env.MAIN_WRITE_API,
      fetch,
    });
    this.splitLink =
      typeof window !== 'undefined' && this.wsLink
        ? split(
            ({ query }) => {
              const definition = getMainDefinition(query);
              return (
                definition.kind === 'OperationDefinition' &&
                definition.operation === 'subscription'
              );
            },
            this.wsLink,
            this.httpLink,
          )
        : this.httpLink;
  }
  @Cron(CronExpression.EVERY_5_SECONDS)
  handleCron() {
    // this.logger.log('Called every 5 seconds');
  }

  @Cron(CronExpression.EVERY_5_SECONDS)
  subscribeCacheInvalidationEvent() {
    if (!this.client) {
      this.client = new ApolloClient({
        // ssrMode: true,
        link: this.splitLink,
        cache: new InMemoryCache(),
      });
      this.client
        .subscribe({
          query: Constant.INVALIDATION_CACHE_SUBSCRIPTION,
        })
        .subscribe({
          next: (data) => {
            this.logger.log(data);
          },
        });
    }

    this.client
      .mutate({
        mutation: Constant.PING_MUTATION,
      })
      .then((res) => {
        this.logger.log(res);
      });
  }
}

However I always received

{
  "data": {
    "tourCacheInvalidation": null
  }
}

How can I fixed this problem? The nestjs apollo client even didn't received the subscription request. Could someone provide me the solution for cache invalidation event using pub/sub pattern? Thanks.

Hung Vo
  • 66
  • 1
  • 10

0 Answers0