NestJS stops working after a few requests

Viewed 1399

I'm getting a serious issue. NestJS stops working after a few requests. I'm using postman to make a specific API call, and then, after less than 10 requests to the same route, it gets extremely slow and i'm getting timeout from Postman everytime.


main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import {Logger} from '@nestjs/common'
import * as rateLimit from 'express-rate-limit';
import { WrapContentInterceptor } from './dashboard/dashboard.interceptors';
const PORT = 5000
const TAG = 'main'
async function bootstrap() {
  const logger = new Logger(TAG)
  const app = await NestFactory.create(AppModule);
  // app.useGlobalInterceptors(new WrapContentInterceptor())
  app.enableCors()
  await app.listen(PORT);
  app.use(
    rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutes
      max: 1000, // limit each IP to 100 requests per windowMs
    }),
  );
  logger.log(`listening port::${PORT}`)
}
bootstrap();

controller where I'm getting the issue:

// some regular imports
@Controller('dashboard')
@UseGuards(AuthGuard()) // protecting routes
export class DashboardController {
    constructor(
        private dashboardService:DashboardService,

    ){}
   // other routes

    @Get('/cockpit/general-numbers') // route that i'm getting the issue
    async getNumbersForCockpit(
        @Query('desiredDate',ParseStringToDatePipe) desiredDay?:Date
    ):Promise<GeneralNumbersForCockpit>{
        this.logger.log(`getNumbersForCockpit::${desiredDay.toISOString()}`)
        let installation = await this.dashboardService.getInstallationsOfDay(desiredDay?desiredDay:undefined)
        let averageTicket = await this.dashboardService.getAverageTicketPlanFromInterval(
            desiredDay?getFirstDayOfMonth(desiredDay):undefined,
            desiredDay?desiredDay:undefined
        )
            
        return {
            averageTicket:averageTicket,
            installation:installation.result
        }
    }
}

Ps: I realized another thing: This error is happening in the routes where I'm using a pure SQL raw at the service layer to a MariaDB database running at Docker container. For example at the service layer: ```
async getData(dateField:Date=new Date()):Promise<SimpleNumericalData>{
    // this.logger.debug(`f::dateField:${dateField}`)
    this.logger.debug(`getData::dateField:${dateField.toISOString()}`)
    const queryRunner = this.connection.createQueryRunner()
    let res = await queryRunner.manager.query(`
        select count(*) as result from my_table
        where my_field ='I'
        and DATE(date_field) = DATE('${dateField.toISOString()}')    
    `)
    //await this.connection.close()
    // this.logger.debug(`Result:${JSON.stringify(res)}`)
    return {
        result:Number(res[0]['result'])
    }
}
1 Answers

I guess your issue come form the way you use the db connection. You created ~ 6 or 10 connections to db, but you did not release them, and the default limit of mariadb's connection pool is 10 (I guess).

Finally, new request want to create new connection, but it reach the limit, new request waiting for another connection be release, but it waiting forever.

In this case, you can extend the limit (not root cause but I think it is good to know).

Add connectionLimit under extra in ormconfig.json (or where you create db config)

{
  ...,
  "extra": { connectionLimit: 10, ... }
}

More information

And you have to release the new connection what you just created in getData function, right after the query finish (success or error) :

...
...
await queryRunner.release()

Note: Let's take care about when your query throw an error, you can use try/catch/finally

...
    let res = await queryRunner.manager.query(`
        select count(*) as result from my_table
        where my_field ='I'
        and DATE(date_field) = DATE('${dateField.toISOString()}')    
    `).finally(() => queryRunner.release())
...
Related