<commit_before>'use strict';

var Redis = require('./redis');
var utils = require('./utils');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var debug = require('debug')('ioredis:cluster');
var _ = require('lodash');
var Commander = require('./commander');

/**
 * Creates a Redis Cluster instance
 *
 * @constructor
 * @param {Object[]} startupNodes - An array of nodes in the cluster, [{ port: number, host: string }]
 * @param {Object} options
 * @param {boolean} [options.enableOfflineQueue=true] - See Redis class
 * @param {boolean} [options.lazyConnect=false] - See Redis class
 * @param {number} [options.maxRedirections=16] - When a MOVED or ASK error is received, client will redirect the
 * command to another node. This option limits the max redirections allowed to send a command.
 * @param {function} [options.clusterRetryStrategy] - See "Quick Start" section
 * @param {number} [options.retryDelayOnFailover=2000] - When an error is received when sending a command(e.g. "Connection is closed." when the target Redis node is down),
 * @param {number} [options.retryDelayOnClusterDown=1000] - When a CLUSTERDOWN error is received, client will retry if `retryDelayOnClusterDown` is valid delay time.
 * @extends [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
 * @extends Commander
 */
function Cluster (startupNodes, options) {
  EventEmitter.call(this);
  Commander.call(this);

  if (!Array.isArray(startupNodes) || startupNodes.length === 0) {
    throw new Error('`startupNodes` should contain at least one node.');
  }
  this.startupNodes = startupNodes;

  this.nodes = {};
  this.slots = [];
  this.connections = {};
  this.retryAttempts = 0;
  this.options = _.defaults(options || {}, this.options || {}, Cluster.defaultOptions);
  this.offlineQueue = [];

  this.connect();
}

/**
 * Default options
 *
 * @var defaultOptions
 * @protected
 */
Cluster.defaultOptions = _.assign({}, Redis.defaultOptions, {
  maxRedirections: 16,
  retryDelayOnFailover: 2000,
  retryDelayOnClusterDown: 1000,
  clusterRetryStrategy: function (times) {
    return Math.min(100 + times * 2, 2000);
  }
});

util.inherits(Cluster, EventEmitter);
_.extend(Cluster.prototype, Commander.prototype);

Cluster.prototype.connect = function () {
  this.setStatus('connecting');

  var _this = this;
  this.once('refresh', function () {
    _this.setStatus('connect');
  });
  this.once('connect', function () {
    _this.retryAttempts = 0;
    _this.manuallyClosing = false;
    _this.setStatus('ready');
    _this.executeOfflineCommands();
  });
  this.once('end', function () {
    var retryDelay;
    if (!_this.manuallyClosing && typeof _this.options.clusterRetryStrategy === 'function') {
      retryDelay = _this.options.clusterRetryStrategy(++_this.retryAttempts);
    }
    if (typeof retryDelay === 'number') {
      _this.setStatus('reconnecting');
      setTimeout(function () {
        debug('Cluster is disconnected. Retrying after %dms', retryDelay);
        _this.connect();
      }, retryDelay);
    } else {<commit_msg>Remove unnecessary listener<commit_after>'use strict';

var Redis = require('./redis');
var utils = require('./utils');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var debug = require('debug')('ioredis:cluster');
var _ = require('lodash');
var Commander = require('./commander');

/**
 * Creates a Redis Cluster instance
 *
 * @constructor
 * @param {Object[]} startupNodes - An array of nodes in the cluster, [{ port: number, host: string }]
 * @param {Object} options
 * @param {boolean} [options.enableOfflineQueue=true] - See Redis class
 * @param {boolean} [options.lazyConnect=false] - See Redis class
 * @param {number} [options.maxRedirections=16] - When a MOVED or ASK error is received, client will redirect the
 * command to another node. This option limits the max redirections allowed to send a command.
 * @param {function} [options.clusterRetryStrategy] - See "Quick Start" section
 * @param {number} [options.retryDelayOnFailover=2000] - When an error is received when sending a command(e.g. "Connection is closed." when the target Redis node is down),
 * @param {number} [options.retryDelayOnClusterDown=1000] - When a CLUSTERDOWN error is received, client will retry if `retryDelayOnClusterDown` is valid delay time.
 * @extends [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
 * @extends Commander
 */
function Cluster (startupNodes, options) {
  EventEmitter.call(this);
  Commander.call(this);

  if (!Array.isArray(startupNodes) || startupNodes.length === 0) {
    throw new Error('`startupNodes` should contain at least one node.');
  }
  this.startupNodes = startupNodes;

  this.nodes = {};
  this.slots = [];
  this.connections = {};
  this.retryAttempts = 0;
  this.options = _.defaults(options || {}, this.options || {}, Cluster.defaultOptions);
  this.offlineQueue = [];

  this.connect();
}

/**
 * Default options
 *
 * @var defaultOptions
 * @protected
 */
Cluster.defaultOptions = _.assign({}, Redis.defaultOptions, {
  maxRedirections: 16,
  retryDelayOnFailover: 2000,
  retryDelayOnClusterDown: 1000,
  clusterRetryStrategy: function (times) {
    return Math.min(100 + times * 2, 2000);
  }
});

util.inherits(Cluster, EventEmitter);
_.extend(Cluster.prototype, Commander.prototype);

Cluster.prototype.connect = function () {
  this.setStatus('connecting');

  var _this = this;
  this.once('refresh', function () {
    _this.retryAttempts = 0;
    _this.manuallyClosing = false;
    _this.setStatus('connect');
    _this.setStatus('ready');
    _this.executeOfflineCommands();
  });
  this.once('end', function () {
    var retryDelay;
    if (!_this.manuallyClosing && typeof _this.options.clusterRetryStrategy === 'function') {
      retryDelay = _this.options.clusterRetryStrategy(++_this.retryAttempts);
    }
    if (typeof retryDelay === 'number') {
      _this.setStatus('reconnecting');
      setTimeout(function () {
        debug('Cluster is disconnected. Retrying after %dms', retryDelay);
        _this.connect();
      }, retryDelay);
    } else {
{'fraction_non_alphanumeric': 0.14058699529755148, 'fraction_numerical': 0.01005351062104751, 'mean_word_length': 4.377506538796862, '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': '3165217', 'n_tokens_mistral': 1879, 'n_tokens_neox': 1844, 'n_words': 480}