tukusejssirs

nest_microservice_wait_for_other_apps_to_be_online

Oct 7th, 2022
1,636
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import {createServer} from 'node:net'
  2. import {IsNumber, IsOptional, IsString, Max, Min} from 'class-validator'
  3. import {PortCheckDto} from '../dto/port-check.dto'
  4.  
  5. export class PortCheckDto {
  6.     @IsString()
  7.     @IsOptional()
  8.     host?: string = 'localhost'
  9.  
  10.     /**
  11.      * Smallest port number is `0`, although it is reserverd by IANA.
  12.      *
  13.      * Largest port number is an unsigned short (`65335`).
  14.      */
  15.     @IsNumber()
  16.     @Min(0)
  17.     @Max(65335)
  18.     port: number
  19. }
  20.  
  21. export class PortCheckErrorDto extends PortCheckDto {
  22.     error: any
  23.     status: 'failure' | 'open'
  24. }
  25.  
  26. /**
  27.  * Determines whether the specified port on a host is used
  28.  *
  29.  * @param    dto - DTO
  30.  * @returns  `true` if port is used (on `EADDRINUSE` or `EACCES` errors), `false` if port is open, `null` on other errors.
  31.  */
  32. export async function isPortUsed(dto: PortCheckDto): Promise<boolean> {
  33.     return new Promise((resolve, reject) => {
  34.         const server = createServer()
  35.  
  36.         const onError = (e: {code: string}): void => {
  37.             server.removeListener('listening', onListen)
  38.             server.close()
  39.  
  40.             if (e.code == 'EADDRINUSE' || e.code == 'EACCES') {
  41.                 return resolve(true)
  42.             } else {
  43.                 return reject({
  44.                     ...dto,
  45.                     error: e,
  46.                     status: 'failure'
  47.                 })
  48.             }
  49.         }
  50.  
  51.         const onListen = (): void => {
  52.             server.removeListener('error', onError)
  53.             server.close()
  54.             return reject({
  55.                 ...dto,
  56.                 status: 'open'
  57.             })
  58.         }
  59.  
  60.         server.once('error', onError)
  61.         server.once('listening', onListen)
  62.         server.once('error', onError)
  63.         server.once('listening', onListen)
  64.  
  65.         server.listen(...Object.values(dto))
  66.     })
  67. }
  68.  
  69. /////////
  70.  
  71. // Example `main.ts`
  72. import {NestFactory} from '@nestjs/core'
  73. import {MicroserviceOptions, Transport} from '@nestjs/microservices'
  74.  
  75. import {CacheModule} from './cache/cache.module'
  76.  
  77. // Add additional array items with variables for other microservices on which current app depends
  78. const portDepends = [
  79.     {host: 'localhost', port: 1234}
  80. ]
  81.  
  82. // How long should we wait before checking if the dependecies are up
  83. const waitTime = 1000
  84.  
  85. async function bootstrap(): Promise<void> {
  86.     const interval = setInterval(async () => {
  87.         try {
  88.             await Promise.all(portDepends.map(port => isPortUsed(port)))
  89.             clearInterval(interval)
  90.             const app = await NestFactory.createMicroservice<MicroserviceOptions>(CacheModule, CACHE_TCP)
  91.             app.useLogger(logger)
  92.             await app.listen()
  93.         } catch (e) {
  94.             const err = e as PortCheckErrorDto
  95.             console.warn(`Microservice on '${err?.host ? `${err.host}:` : ''}${err.port}' is offline.`)
  96.         }
  97.     }, waitTime)
  98. }
  99.  
  100. bootstrap().catch(e => console.log(e))
Advertisement
Add Comment
Please, Sign In to add comment