hazelcast-client
Version:
Hazelcast - open source In-Memory Data Grid - client for NodeJS
249 lines • 10.5 kB
JavaScript
"use strict";
/*
* Copyright (c) 2008-2018, Hazelcast, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Promise = require("bluebird");
var ClientAddMembershipListenerCodec_1 = require("../codec/ClientAddMembershipListenerCodec");
var LoggingService_1 = require("../logging/LoggingService");
var events_1 = require("events");
var ClientInfo_1 = require("../ClientInfo");
var Address = require("../Address");
var HazelcastError_1 = require("../HazelcastError");
var assert = require("assert");
var MEMBER_ADDED = 1;
var MEMBER_REMOVED = 2;
var EMIT_MEMBER_ADDED = 'memberAdded';
var EMIT_MEMBER_REMOVED = 'memberRemoved';
var EMIT_ATTRIBUTE_CHANGE = 'memberAttributeChange';
var ATTRIBUTE_CHANGE = {
1: 'put',
2: 'remove'
};
/**
* Manages the relationship of this client with the cluster.
*/
var ClusterService = /** @class */ (function (_super) {
__extends(ClusterService, _super);
function ClusterService(client) {
var _this = _super.call(this) || this;
/**
* The unique identifier of the owner server node. This node is responsible for resource cleanup
*/
_this.ownerUuid = null;
/**
* The unique identifier of this client instance. Assigned by owner node on authentication
*/
_this.uuid = null;
_this.knownAddresses = [];
_this.members = [];
_this.logger = LoggingService_1.LoggingService.getLoggingService();
_this.client = client;
_this.members = [];
return _this;
}
/**
* Starts cluster service.
* @returns
*/
ClusterService.prototype.start = function () {
this.initHeartbeatListener();
this.initConnectionListener();
return this.connectToCluster();
};
/**
* Connects to cluster. It uses the addresses provided in the configuration.
* @returns
*/
ClusterService.prototype.connectToCluster = function () {
var _this = this;
if (this.members.length > 0) {
this.knownAddresses = new Array();
this.members.forEach(function (member) {
_this.knownAddresses.push(member.address);
});
}
else {
this.knownAddresses = this.client.getConfig().networkConfig.addresses;
}
if (this.knownAddresses.length === 0) {
this.knownAddresses.push(new Address('127.0.0.1', 5701));
}
var attemptLimit = this.client.getConfig().networkConfig.connectionAttemptLimit;
var attemptPeriod = this.client.getConfig().networkConfig.connectionAttemptPeriod;
return this.tryAddresses(0, attemptLimit, attemptPeriod);
};
/**
* Returns the list of members in the cluster.
* @returns
*/
ClusterService.prototype.getMembers = function (selector) {
if (selector === undefined) {
return this.members;
}
else {
var members_1 = [];
this.members.forEach(function (member) {
if (selector.select(member)) {
members_1.push(member);
}
});
return members_1;
}
};
/**
* Returns the number of nodes in cluster.
* @returns {number}
*/
ClusterService.prototype.getSize = function () {
return this.members.length;
};
/**
* Returns information about this client.
* @returns {ClientInfo}
*/
ClusterService.prototype.getClientInfo = function () {
var info = new ClientInfo_1.ClientInfo();
info.uuid = this.uuid;
info.localAddress = this.getOwnerConnection().getLocalAddress();
return info;
};
ClusterService.prototype.initHeartbeatListener = function () {
this.client.getHeartbeat().addListener({
onHeartbeatStopped: this.onHeartbeatStopped.bind(this)
});
};
ClusterService.prototype.initConnectionListener = function () {
this.client.getConnectionManager().on('connectionClosed', this.onConnectionClosed.bind(this));
};
ClusterService.prototype.onConnectionClosed = function (connection) {
this.logger.warn('ClusterService', 'Connection closed to ' + connection.toString());
if (connection.isAuthenticatedAsOwner()) {
this.ownerConnection = null;
this.connectToCluster().catch(this.client.shutdown.bind(this.client));
}
};
ClusterService.prototype.onHeartbeatStopped = function (connection) {
this.logger.warn('ClusterService', connection.toString() + ' stopped heartbeating.');
if (connection.isAuthenticatedAsOwner()) {
this.client.getConnectionManager().destroyConnection(connection.getAddress());
}
};
ClusterService.prototype.tryAddresses = function (index, attemptLimit, attemptPeriod) {
var _this = this;
if (this.knownAddresses.length <= index) {
attemptLimit = attemptLimit - 1;
if (attemptLimit === 0) {
var error = new HazelcastError_1.IllegalStateError('Unable to connect to any of the following addresses: ' +
this.knownAddresses.map(function (element) {
return element.toString();
}).join(', '));
return Promise.reject(error);
}
else {
var deferred_1 = Promise.defer();
setTimeout(function () {
_this.tryAddresses(0, attemptLimit, attemptPeriod).then(function () {
deferred_1.resolve();
}).catch(function (e) {
deferred_1.reject(e);
});
}, attemptPeriod);
return deferred_1.promise;
}
}
else {
var currentAddress = this.knownAddresses[index];
return this.client.getConnectionManager().getOrConnect(currentAddress, true).then(function (connection) {
if (connection == null) {
throw new Error('Could not connect to ' + currentAddress.toString());
}
connection.setAuthneticatedAsOwner(true);
_this.ownerConnection = connection;
return _this.initMemberShipListener();
}).catch(function (e) {
_this.logger.warn('ClusterService', e);
return _this.tryAddresses(index + 1, attemptLimit, attemptPeriod);
});
}
};
/**
* Returns the connection associated with owner node of this client.
* @returns {ClientConnection}
*/
ClusterService.prototype.getOwnerConnection = function () {
return this.ownerConnection;
};
ClusterService.prototype.initMemberShipListener = function () {
var _this = this;
var request = ClientAddMembershipListenerCodec_1.ClientAddMembershipListenerCodec.encodeRequest(false);
var handler = function (m) {
var handleMember = _this.handleMember.bind(_this);
var handleMemberList = _this.handleMemberList.bind(_this);
var handleAttributeChange = _this.handleMemberAttributeChange.bind(_this);
ClientAddMembershipListenerCodec_1.ClientAddMembershipListenerCodec.handle(m, handleMember, handleMemberList, handleAttributeChange, null);
};
return this.client.getInvocationService().invokeOnConnection(this.getOwnerConnection(), request, handler)
.then(function (resp) {
_this.logger.trace('ClusterService', 'Registered listener with id '
+ ClientAddMembershipListenerCodec_1.ClientAddMembershipListenerCodec.decodeResponse(resp).response);
});
};
ClusterService.prototype.handleMember = function (member, eventType) {
if (eventType === MEMBER_ADDED) {
this.logger.info('ClusterService', member.toString() + ' added to cluster');
this.memberAdded(member);
}
else if (eventType === MEMBER_REMOVED) {
this.logger.info('ClusterService', member.toString() + ' removed from cluster');
this.memberRemoved(member);
}
this.client.getPartitionService().refresh();
};
ClusterService.prototype.handleMemberList = function (members) {
this.members = members;
this.client.getPartitionService().refresh();
this.logger.info('ClusterService', 'Members received.', this.members);
};
ClusterService.prototype.handleMemberAttributeChange = function (uuid, key, operationType, value) {
this.emit(EMIT_ATTRIBUTE_CHANGE, uuid, key, ATTRIBUTE_CHANGE[operationType], value);
};
ClusterService.prototype.memberAdded = function (member) {
this.members.push(member);
this.emit(EMIT_MEMBER_ADDED, member);
};
ClusterService.prototype.memberRemoved = function (member) {
var memberIndex = this.members.findIndex(member.equals, member);
if (memberIndex !== -1) {
var removedMemberList = this.members.splice(memberIndex, 1);
assert(removedMemberList.length === 1);
}
this.client.getConnectionManager().destroyConnection(member.address);
this.emit(EMIT_MEMBER_REMOVED, member);
};
return ClusterService;
}(events_1.EventEmitter));
exports.ClusterService = ClusterService;
//# sourceMappingURL=ClusterService.js.map