<commit_before>var
  PendingRequest = require('../store/PendingRequest'),
  InternalError = require('kuzzle-common-objects').Errors.internalError;

/**
 * Backend constructor
 *
 * @param {WebSocket} backendSocket
 * @param {Context} context
 * @param {Number} backendTimeout
 * @constructor
 */
function Backend (backendSocket, context, backendTimeout) {
  /** @type {PendingRequest} */
  this.backendRequestStore = new PendingRequest(backendTimeout);

  /** @type {WebSocket} */
  this.socket = backendSocket;

  /** @type {Context} */
  this.context = context;

  /** @type {String} */
  this.socketIp = backendSocket.upgradeReq.connection.remoteAddress;

  /** @type {Number} */
  this.httpPort = null;

  /** @type {Function|null} */
  this.httpPortCallback = null;

  this.socket.on('close', this.onConnectionClose.bind(this));
  this.socket.on('error', this.onConnectionError.bind(this));
  this.socket.on('message', this.onMessage.bind(this));

  this.onMessageRooms = this.initializeMessageRooms();
}

/**
 * Triggered when a message is received
 *
 * @param {String} data
 */
Backend.prototype.onMessage = function (data) {
  var message;

  try {
    message = JSON.parse(data);
  }
  catch (error) {
    return console.error(`Bad message received from the backend : ${data}; Reason : ${error}`);
  }

  if (!message.room) {
    return console.error(`Room is not specified in message: ${data}`);
  }

  if (!this.onMessageRooms[message.room]) {
    return console.error(`Unknown message type ${message.room}`);
  }

  this.onMessageRooms[message.room](message);
};

Backend.prototype.initializeMessageRooms = function () {
  return {
    response: (message) => {
      if (this.backendRequestStore.existsByRequestId(message.data.requestId)) {
        this.backendRequestStore.getByRequestId(message.data.requestId).callback(null, message.data.response);
        this.backendRequestStore.removeByRequestId(message.data.requestId);
      }
    },
    joinChannel: (message) => {
      var client = this.context.clientConnectionStore.getByConnectionId(message.data.id);

      if (client && client.type) {
        this.context.pluginStore.getByProtocol(client.type).joinChannel(message.data);
      }
    },
    leaveChannel: (message) => {
      var client = this.context.clientConnectionStore.getByConnectionId(message.data.id);

      if (client && client.type) {
        this.context.pluginStore.getByProtocol(client.type).leaveChannel(message.data);
      }
    },
    notify: (message) => {
      var client = this.context.clientConnectionStore.getByConnectionId(message.data.id);

      if (client && client.type) {
        this.context.pluginStore.getByProtocol(client.type).notify(message.data);
      }
    },
    broadcast: (message) => {
      Object.keys(this.context.pluginStore.plugins).forEach(plugin => {
        this.context.pluginStore.plugins[plugin].broadcast(message.data);
      });
    },
    httpPortInitialization: (message) => {
      this.httpPort = message.data.httpPort;
      console.log(`Backend HTTP port of ${this.socketIp} received : ${this.httpPort}`);
      if (this.httpPortCallback) {
        this.httpPortCallback();
        this.httpPortCallback = null;
      }
    }
  };<commit_msg>prevents crash if a plugin fails<commit_after>var
  PendingRequest = require('../store/PendingRequest'),
  util = require('util'),
  InternalError = require('kuzzle-common-objects').Errors.internalError;

/**
 * Backend constructor
 *
 * @param {WebSocket} backendSocket
 * @param {Context} context
 * @param {Number} backendTimeout
 * @constructor
 */
function Backend (backendSocket, context, backendTimeout) {
  /** @type {PendingRequest} */
  this.backendRequestStore = new PendingRequest(backendTimeout);

  /** @type {WebSocket} */
  this.socket = backendSocket;

  /** @type {Context} */
  this.context = context;

  /** @type {String} */
  this.socketIp = backendSocket.upgradeReq.connection.remoteAddress;

  /** @type {Number} */
  this.httpPort = null;

  /** @type {Function|null} */
  this.httpPortCallback = null;

  this.socket.on('close', this.onConnectionClose.bind(this));
  this.socket.on('error', this.onConnectionError.bind(this));
  this.socket.on('message', this.onMessage.bind(this));

  this.onMessageRooms = this.initializeMessageRooms();
}

/**
 * Triggered when a message is received
 *
 * @param {String} data
 */
Backend.prototype.onMessage = function (data) {
  var message;

  try {
    message = JSON.parse(data);
  }
  catch (error) {
    return console.error(`Bad message received from the backend : ${data}; Reason : ${error}`);
  }

  if (!message.room) {
    return console.error(`Room is not specified in message: ${data}`);
  }

  if (!this.onMessageRooms[message.room]) {
    return console.error(`Unknown message type ${message.room}`);
  }

  this.onMessageRooms[message.room](message);
};

Backend.prototype.initializeMessageRooms = function () {
  return {
    response: (message) => {
      if (this.backendRequestStore.existsByRequestId(message.data.requestId)) {
        this.backendRequestStore.getByRequestId(message.data.requestId).callback(null, message.data.response);
        this.backendRequestStore.removeByRequestId(message.data.requestId);
      }
    },
    joinChannel: (message) => {
      var client = this.context.clientConnectionStore.getByConnectionId(message.data.id);

      if (client && client.type) {
        try {
          this.context.pluginStore.getByProtocol(client.type).joinChannel(message.data);
        }
        catch(e) {
          console.error(`[Join Channel] Plugin ${client.type} failed: ${e.message}`);
        }
      }
    },
    leaveChannel: (message) => {
      var client = this.context.clientConnectionStore.getByConnectionId(message.data.id);

      if (client && client.type) {
        try {
          this.context.pluginStore.getByProtocol(client.type).leaveChannel(message.data);
        }
        catch(e) {
          console.error(`[Leave Channel] Plugin ${client.type} failed: ${e.message}`);
        }
      }
    },
    notify: (message) => {
      var client = this.context.clientConnectionStore.getByConnectionId(message.data.id);

      if (client && client.type) {
        try {
          this.context.pluginStore.getByProtocol(client.type).notify(message.data);
        }
        catch(e) {
          console.error(`[Notify] Plugin ${client.type} failed: ${e.message}\nNotification data:\n`, util.inspect(message.data, {depth: null}));
        }
      }
    },
    broadcast: (message) => {
      Object.keys(this.context.pluginStore.plugins).forEach(plugin => {
        try {
          this.context.pluginStore.plugins[plugin].broadcast(message.data);
        }
        catch(e) {
          console.error(`[Broadcast] Plugin ${client.type} failed: ${e.message}\nNotification data:\n`, util.inspect(message.data, {depth: null}));
        }
      });
    },
    httpPortInitialization: (message) => {
      this.httpPort = message.data.httpPort;
      console.log(`Backend HTTP port of ${this.socketIp} received : ${this.httpPort}`);
      if (this.httpPortCallback) {
        this.httpPortCallback();
        this.httpPortCallback = null;
      }
    }
  };
{'fraction_non_alphanumeric': 0.14895095178546616, 'fraction_numerical': 0.0, 'mean_word_length': 3.323123123123123, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '476435', 'n_tokens_mistral': 2160, 'n_tokens_neox': 2143, 'n_words': 363}