<commit_before>var socketIo = require('socket.io');

var commands = [
  'status',
  'search',
  'createtable',
  'removetable',
  'createcolumn',
  'removecolumn',
  'loadrecord',
  'loadrecords',
];
exports.commands = commands;

function deepClone(base) {
  if (!base || typeof base != 'object')
    return base;

  var cloned = Object.create(null);
  Object.keys(base).forEach(function(key) {
    cloned[key] = deepClone(base[key]);
  });
  return cloned;
}

function buildResultData(envelope) {
  return {
    statusCode: envelope.statusCode,
    body: deepClone(envelope.body)
  };
}
exports.buildResultData = buildResultData;

exports.register = function(application, server, params) {
  params = params || {};
  var connection = params.connection;
  if (!connection)
    throw new Error('Connection to the backend is required!');

  function createRequestHandler(command, socket) {
    return (function(data) {
      connection.emitMessage(command, data);
    });
  }

  function createResultHandler(command, socket) {
    return (function(envelope) {
      if (/\.result/.test(envelope.type)) {
        var data = buildResultData(envelope);
        socket.emit(envelope.type, data);
      }
    });
  }

  var io = socketIo.listen(server);
  io.sockets.on('connection', function(socket) {
    commands.concat(params.extraCommands || [])
      .forEach(function(command) {
        socket.on(command, createRequestHandler(command, socket));
        connection.on('message', createResultHandler(command, socket));
      });
  });
}
<commit_msg>Remove message handlers attached to the connection when a socket.io client is disconnected<commit_after>var socketIo = require('socket.io');

var commands = [
  'status',
  'search',
  'createtable',
  'removetable',
  'createcolumn',
  'removecolumn',
  'loadrecord',
  'loadrecords',
];
exports.commands = commands;

function deepClone(base) {
  if (!base || typeof base != 'object')
    return base;

  var cloned = Object.create(null);
  Object.keys(base).forEach(function(key) {
    cloned[key] = deepClone(base[key]);
  });
  return cloned;
}

function buildResultData(envelope) {
  return {
    statusCode: envelope.statusCode,
    body: deepClone(envelope.body)
  };
}
exports.buildResultData = buildResultData;

exports.register = function(application, server, params) {
  params = params || {};
  var connection = params.connection;
  if (!connection)
    throw new Error('Connection to the backend is required!');

  function createRequestHandler(command, socket) {
    return (function(data) {
      connection.emitMessage(command, data);
    });
  }

  function createResultHandler(command, socket) {
    return (function(envelope) {
      if (/\.result/.test(envelope.type)) {
        var data = buildResultData(envelope);
        socket.emit(envelope.type, data);
      }
    });
  }

  var io = socketIo.listen(server);
  io.sockets.on('connection', function(socket) {
    var messageHandlers = [];
    commands.concat(params.extraCommands || [])
      .forEach(function(command) {
        socket.on(command, createRequestHandler(command, socket));
        var handler = createResultHandler(command, socket);
        messageHandlers.push(handler);
        connection.on('message', handler);
      });

    socket.on('disconnect', function() {
      messageHandlers.forEach(function(handler) {
        connection.removeListener('message', handler);
      });
      socket.removeAllListeners();
    });
  });
}

{'fraction_non_alphanumeric': 0.14137633170169883, 'fraction_numerical': 0.0, 'mean_word_length': 3.7137042062415198, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '907963', 'n_tokens_mistral': 1035, 'n_tokens_neox': 1024, 'n_words': 208}