Skip to content

Commit

Permalink
Node.js clustering with Nest application
Browse files Browse the repository at this point in the history
  • Loading branch information
csuvajit committed Sep 19, 2023
1 parent 3da635a commit 525ad3b
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 13 deletions.
4 changes: 2 additions & 2 deletions apps/service-app/test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { Test, TestingModule } from '@nestjs/testing';
import request from 'supertest';
import { AppModule } from '../src/app.module';

describe('AppController (e2e)', () => {
Expand Down
4 changes: 2 additions & 2 deletions apps/service-capital/test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { Test, TestingModule } from '@nestjs/testing';
import request from 'supertest';
import { ServiceCapitalModule } from './../src/service-capital.module';

describe('ServiceCapitalController (e2e)', () => {
Expand Down
4 changes: 2 additions & 2 deletions apps/service-clans/test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { Test, TestingModule } from '@nestjs/testing';
import request from 'supertest';
import { ServiceClansModule } from './../src/service-clans.module';

describe('ServiceClansController (e2e)', () => {
Expand Down
4 changes: 2 additions & 2 deletions apps/service-wars/test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { Test, TestingModule } from '@nestjs/testing';
import request from 'supertest';
import { ServiceWarsModule } from './../src/service-wars.module';

describe('ServiceWarsController (e2e)', () => {
Expand Down
5 changes: 3 additions & 2 deletions libs/auth/src/decorators/current-user.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { TokenType } from '@app/constants';
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { Request } from 'express';

export interface JwtUser {
sub: string;
Expand All @@ -10,7 +11,7 @@ export interface JwtUser {
}

export const CurrentUser = createParamDecorator((data: unknown, context: ExecutionContext) => {
return context.switchToHttp().getRequest().user.sub;
return context.switchToHttp().getRequest<Request>().user!.sub;
});

declare module 'express' {
Expand Down
42 changes: 42 additions & 0 deletions libs/helper/src/app-cluster.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Injectable, Logger } from '@nestjs/common';
import cluster from 'cluster';
import os from 'os';

const numCPUs = os.cpus().length;

/**
* @example
* ```ts
* AppClusterService.clustering(bootstrap);
* ```
*/
@Injectable()
export class AppClusterService {
static logger = new Logger(AppClusterService.name);

static async clustering(callback: () => unknown): Promise<unknown> {
if (cluster.isPrimary) {
this.logger.log(`Master server started on ${process.pid}`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
await this.delay(5000);
}

cluster.on('exit', (worker, code, signal) => {
this.logger.log(
`Worker ${worker.process.pid} died with code ${code} and signal ${signal}.`,
);
cluster.fork();
});
} else {
callback();
this.logger.log(`Cluster server started on ${process.pid}`);
}

return {};
}

static delay(ms: number) {
return new Promise((res) => setTimeout(res, ms));
}
}
1 change: 1 addition & 0 deletions libs/helper/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './app-cluster.service';
export * from './helper.module';
export * from './helper.service';
6 changes: 3 additions & 3 deletions libs/redis/src/redis.module.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Tokens } from '@app/constants';
import { Module, Provider } from '@nestjs/common';
import { createClient } from 'redis';
import { RedisService } from './redis.service';
import * as Redis from 'redis';

export type RedisClient = ReturnType<typeof Redis.createClient>;
export type RedisClient = ReturnType<typeof createClient>;

const RedisProvider: Provider = {
provide: Tokens.REDIS,
useFactory: async (): Promise<RedisClient> => {
const redis = Redis.createClient({
const redis = createClient({
url: process.env.REDIS_URL,
database: Number(process.env.REDIS_DATABASE || 0),
});
Expand Down
2 changes: 2 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"importHelpers": true,
"target": "ES2021",
"sourceMap": true,
"outDir": "./dist",
Expand Down

0 comments on commit 525ad3b

Please sign in to comment.