# All files / microservices/server server-tcp.ts

91.67% Statements 33/36
86.67% Branches 13/15
75% Functions 9/12
94.29% Lines 33/35

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    981x
    1x
    1x

    1x

    1x

    1x

    10x
    10x

    10x
    10x
    10x

    10x

    1x

    1x
    1x

    1x
    1x

    2x

    2x

    2x
    1x

    1x
    1x

    1x

    2x

    4x

    3x

    1x
    1x
    1x

    10x
    10x
    10x

     import { isString } from '@nestjs/common/utils/shared.utils';
    import * as JsonSocket from 'json-socket';
    import * as net from 'net';
    import { Server as NetSocket } from 'net';
    import { Observable } from 'rxjs';
    import {
      CLOSE_EVENT,
      ERROR_EVENT,
      MESSAGE_EVENT,
      NO_PATTERN_MESSAGE,
      TCP_DEFAULT_PORT,
    } from '../constants';
    import { CustomTransportStrategy, PacketId, ReadPacket } from '../interfaces';
    import {
      MicroserviceOptions,
      TcpOptions,
    } from '../interfaces/microservice-configuration.interface';
    import { Server } from './server';

    export class ServerTCP extends Server implements CustomTransportStrategy {
      private readonly port: number;
      private server: NetSocket;
      private isExplicitlyTerminated = false;
      private retryAttemptsCount = 0;

      constructor(private readonly options: MicroserviceOptions['options']) {
        super();
        this.port =
          this.getOptionsProp<TcpOptions>(options, 'port') || TCP_DEFAULT_PORT;
        this.init();
      }

      public listen(callback: () => void) {
        this.server.listen(this.port, callback);
      }

      public close() {
        this.isExplicitlyTerminated = true;
        this.server.close();
      }

      public bindHandler(socket) {
        const readSocket = this.getSocketInstance(socket);
        readSocket.on(MESSAGE_EVENT, async msg =>
          this.handleMessage(readSocket, msg),
        );
      }

      public async handleMessage(socket, packet: ReadPacket & PacketId) {
        const pattern = !isString(packet.pattern)
          ? JSON.stringify(packet.pattern)
          : packet.pattern;
        const status = 'error';

        if (!this.messageHandlers[pattern]) {
          return socket.sendMessage({
            id: packet.id,
            status,
            err: NO_PATTERN_MESSAGE,
          });
        }
        const handler = this.messageHandlers[pattern];
        const response$ = this.transformToObservable(
          await handler(packet.data),
        ) as Observable<any>;
        response$ &&
          this.send(response$, data =>
            socket.sendMessage(Object.assign(data, { id: packet.id })),
          );
      }

      public handleClose(): undefined | number | NodeJS.Timer {
        if (
          this.isExplicitlyTerminated ||
          !this.getOptionsProp<TcpOptions>(this.options, 'retryAttempts') ||
          this.retryAttemptsCount >=
            this.getOptionsProp<TcpOptions>(this.options, 'retryAttempts')
        ) {
          return undefined;
        }
        ++this.retryAttemptsCount;
        return setTimeout(
          () => this.server.listen(this.port),
          this.getOptionsProp<TcpOptions>(this.options, 'retryDelay') || 0,
        );
      }

      private init() {
        this.server = net.createServer(this.bindHandler.bind(this));
        this.server.on(ERROR_EVENT, this.handleError.bind(this));
        this.server.on(CLOSE_EVENT, this.handleClose.bind(this));
      }

      private getSocketInstance(socket): JsonSocket {
        return new JsonSocket(socket);
      }
    }