DEV Community

Joseph Sutton
Joseph Sutton

Posted on • Edited on

1

Polyglot Microservices: Federated GraphQL Subscriptions in Golang, Rust, and Nest.js, Pt. 3

Series Navigation

  1. Golang Microservices (spells)
  2. Rust Microservice (messages)
  3. Node.js Microservice (players)
  4. Gateway

Player Subgraph (Node.js)

Now, let's create the Nest.js subgraph

nx add @nx/nest
nx g @nx/nest:app apps/player-service
Enter fullscreen mode Exit fullscreen mode

Let's add some dependencies:

pnpm i @nestjs/graphql graphql graphql-yoga @graphql-yoga/nestjs-federation 
Enter fullscreen mode Exit fullscreen mode

We're going to be using the GraphQL Yoga server here, because NestJS's federated Apollo configuration doesn't allow for subscriptions -- fun fact (mainly because Apollo charges for federated subscriptions, and we can get that for free if we use Hive Gateway over the Apollo Router).

If you need higher throughput on your router, Wundergraph's Router is free and it's in Golang. I've used it before, but my use-case only required Hive Gateway -- for now.

Anyhow, here's how we set up our src/app.module.ts with the GraphQL module configured for graphql-yoga:

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import {
  YogaFederationDriver,
  YogaFederationDriverConfig,
} from '@graphql-yoga/nestjs-federation';
import { PlayerModule } from './player/player.module';

@Module({
  imports: [
    GraphQLModule.forRoot<YogaFederationDriverConfig>({
      driver: YogaFederationDriver,
      autoSchemaFile: {
        federation: {
          version: 2,
          // required for federated subscriptions
          importUrl: 'https://specs.apollo.dev/federation/v2.4',
        },
      },
      subscriptions: true,
    }),
    PlayerModule,
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

For our player module, we need our resolver in src/player/player.resolver.ts:

import { Args, Mutation, Resolver, Subscription } from '@nestjs/graphql';
import { Player } from './player.model';
import { createPubSub, Repeater } from 'graphql-yoga';

const pubSub = createPubSub();

@Resolver(() => Player)
export class PlayerResolver {
  @Mutation(() => Player)
  enterArea(
    @Args('playerId') playerId: string,
    @Args('area') area: string
  ): Player {
    pubSub.publish(`${area}`, { id: playerId });
    return { id: playerId };
  }

  @Subscription(() => Player, {
    nullable: true,
    resolve: (value: Player) => value,
  })
  nearbyPlayers(@Args('area') area: string): Repeater<Player> {
    return pubSub.subscribe(`${area}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, we need our entity that we're resolving in src/player/player.model.ts:

import { Field, ID, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class Player {
  @Field(() => ID)
  id: string;
}
Enter fullscreen mode Exit fullscreen mode

Let's tie it together in src/player/player.module.ts:

import { Module } from '@nestjs/common';
import { PlayerResolver } from './player.resolver';

@Module({
  providers: [PlayerResolver],
})
export class PlayerModule {}
Enter fullscreen mode Exit fullscreen mode

As with the above services, you'll boot this up and migrate to the proper URL and test it out with multiple browser tabs open:

subscription NearbyPlayers {
  nearbyPlayers(area: "forest") {
    id
  }
}
Enter fullscreen mode Exit fullscreen mode
mutation {
  enterArea(playerId: "1243", area: "forest"){
    id
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, let's move onto the final part: tying it all together with Hive Gateway in part 4!

Neon image

Resources for building AI applications with Neon Postgres 🤖

Core concepts, starter applications, framework integrations, and deployment guides. Use these resources to build applications like RAG chatbots, semantic search engines, or custom AI tools.

Explore AI Tools →

Top comments (0)

Jetbrains image

Don’t Become a Data Breach Headline

57% of organizations have suffered from a security incident related to DevOps toolchain exposures. Is your CI/CD protected? Check out these nine practical tips to keep your CI/CD secure—without adding friction.

Learn more

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay