<commit_before>module.exports = Member;

var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Happn = require('happn');
var Promise = require('bluebird');
var clone = require('clone');

var property = require('../../utils/property');
var getter = require('../../utils/getter');

function Member(parameters) {
  var _this = this;

  var member = parameters.member;
  var memberFromLogin = parameters.memberFromLogin;
  var orchestrator = parameters.orchestrator;
  var localClient = parameters.localClient;
  var mapper = parameters.eventMapper;
  var clusterName = parameters.clusterName;

  property(this, 'orchestrator', orchestrator);
  property(this, 'log', orchestrator.log);
  property(this, 'eventMapper', mapper);
  property(this, 'clusterName', clusterName);

  // this member represents self in the cluster
  this.self = false;

  // happn.name
  this.name = null;

  // this member's id (remote swim host)
  this.memberId = null;

  // true when swim discovers
  this.member = false;

  // login in progress
  this.connectingTo = true;

  // got happn connection to remote happn
  this.connectedTo = false;

  // got happn connection from remote happn
  this.connectedFrom = false;

  // set to false on subscription success
  this.subscribedTo = false;

  // TODO: not truly stabilised until we know the remote has subscribed to us
  this.subscribedFrom = true; // (not possible to detect yet)

  // orchestrator.stabilized() discovers this error and this
  // whole cluster node fails to start because it could not
  // login to one of the other members
  //
  // populate it with happn login error or subscribe error
  this.error = null;

  if (localClient) {
    this.self = true;
    this.name = this.orchestrator.happn.name;
    this.connectedTo = true; // member does not connect to...
    this.connectedFrom = true; // ...or from itself
    this.connectingTo = false;
    this.subscribedTo = true; // member does not replicate itself
    getter(this, 'client', localClient);
  }

  // member present only if SWIM got first notice of new member
  if (member) {
    this.memberId = member.memberId;
    this.member = true;
    this.connect(member);
  }

  // memberFromLogin present only if happn got first notice of new member (via inbound login)
  if (memberFromLogin) {
    this.memberId = memberFromLogin.memberId;
    this.name = memberFromLogin.name;
    this.connect(memberFromLogin);
  }

}

util.inherits(Member, EventEmitter);

Member.prototype.connect = function (member) {
  var _this = this;
  var login = clone(this.orchestrator.loginConfig);

  this.log.debug('connect to (->) %s', member.url);

  login.config.url = member.url;

  // login.config.username = '_ADMIN';
  // login.config.password = '<PASSWORD>';

  Happn.client.create(login, function (error, client) {

    _this.connectingTo = false;
    _this.connectedTo = true;

    if (error) {
      _this.error = error;
      _this.log.fatal('could not login to %s', login.config.url, error);
      return;
    }

    getter(_this, 'client', client);
    _this.name = client.serverInfo.name;

    property(_this, '__disconnectSubscriptionId',
      client.onEvent('connection-ended', _this.__onHappnDisconnect.bind(_this))
    );
<commit_msg>handle joining with simultaneous other departing<commit_after>module.exports = Member;

var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Happn = require('happn');
var Promise = require('bluebird');
var clone = require('clone');

var property = require('../../utils/property');
var getter = require('../../utils/getter');

function Member(parameters) {
  var _this = this;

  var member = parameters.member;
  var memberFromLogin = parameters.memberFromLogin;
  var orchestrator = parameters.orchestrator;
  var localClient = parameters.localClient;
  var mapper = parameters.eventMapper;
  var clusterName = parameters.clusterName;

  property(this, 'orchestrator', orchestrator);
  property(this, 'log', orchestrator.log);
  property(this, 'eventMapper', mapper);
  property(this, 'clusterName', clusterName);

  // this member represents self in the cluster
  this.self = false;

  // happn.name
  this.name = null;

  // this member's id (remote swim host)
  this.memberId = null;

  // true when swim discovers
  this.member = false;

  // login in progress
  this.connectingTo = true;

  // got happn connection to remote happn
  this.connectedTo = false;

  // got happn connection from remote happn
  this.connectedFrom = false;

  // set to false on subscription success
  this.subscribedTo = false;

  // TODO: not truly stabilised until we know the remote has subscribed to us
  this.subscribedFrom = true; // (not possible to detect yet)

  // orchestrator.stabilized() discovers this error and this
  // whole cluster node fails to start because it could not
  // login to one of the other members
  //
  // populate it with happn login error or subscribe error
  this.error = null;

  if (localClient) {
    this.self = true;
    this.name = this.orchestrator.happn.name;
    this.connectedTo = true; // member does not connect to...
    this.connectedFrom = true; // ...or from itself
    this.connectingTo = false;
    this.subscribedTo = true; // member does not replicate itself
    getter(this, 'client', localClient);
  }

  // member present only if SWIM got first notice of new member
  if (member) {
    this.memberId = member.memberId;
    this.member = true;
    this.connect(member);
  }

  // memberFromLogin present only if happn got first notice of new member (via inbound login)
  if (memberFromLogin) {
    this.memberId = memberFromLogin.memberId;
    this.name = memberFromLogin.name;
    this.connect(memberFromLogin);
  }

}

util.inherits(Member, EventEmitter);

Member.prototype.connect = function (member) {
  var _this = this;
  var login = clone(this.orchestrator.loginConfig);

  this.log.debug('connect to (->) %s', member.url);

  login.config.url = member.url;

  // login.config.username = '_ADMIN';
  // login.config.password = '<PASSWORD>';

  Happn.client.create(login, function (error, client) {

    if (error) {

      if (error.code == 'ECONNREFUSED') {
        // This happens when we join, get list of remotes and simultaneously
        // one of them shuts down. We don't get the notification from swim
        // in time to know not to login.
        //
        // And we don't want to fail starting this node because another shut down
        // at the same time as we joined.
        _this.log.warn('FAILED connection to departed %s', login.config.url);
        _this.orchestrator.__removeMember(_this);
        return;
      }

      // ignore second error after ECONNREFUSED
      // https://github.com/happner/happn/issues/138
      if (!_this.orchestrator.members[_this.memberId]) return;

      _this.error = error;
      _this.log.fatal('could not login to %s', login.config.url, error);
      return;
    }

    _this.connectingTo = false;
    _this.connectedTo = true;

    getter(_this, 'client', client);
    _this.name = client.serverInfo.name;

    property(_this, '__disconnectSubscriptionId',
      client.onEvent('connection-ended', _this.__onHappnDisconnect.bind(_this))
    );

{'fraction_non_alphanumeric': 0.1157880209770908, 'fraction_numerical': 0.0004140215291195142, 'mean_word_length': 3.2479484173505275, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 1, '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': '2869618', 'n_tokens_mistral': 2199, 'n_tokens_neox': 2131, 'n_words': 647}