UNPKG

hazelcast-client

Version:

Hazelcast - open source In-Memory Data Grid - client for NodeJS

263 lines 11.5 kB
"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 HazelcastError_1 = require("../HazelcastError"); var assert = require("assert"); var Util_1 = require("../Util"); 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; return this.getPossibleMemberAddresses().then(function (res) { _this.knownAddresses = []; res.forEach(function (value) { _this.knownAddresses.push(Util_1.createAddressFromString(value)); }); var attemptLimit = _this.client.getConfig().networkConfig.connectionAttemptLimit; var attemptPeriod = _this.client.getConfig().networkConfig.connectionAttemptPeriod; return _this.tryConnectingToAddresses(0, attemptLimit, attemptPeriod); }); }; ClusterService.prototype.getPossibleMemberAddresses = function () { var addresses = new Set(); this.getMembers().forEach(function (member) { addresses.add(member.address.toString()); }); var providerAddresses = new Set(); var promises = []; this.client.getConnectionManager().addressProviders.forEach(function (addressProvider) { var _this = this; promises.push(addressProvider.loadAddresses().then(function (res) { providerAddresses = new Set(Array.from(providerAddresses).concat(res)); }).catch(function (err) { _this.logger.warning('Error from AddressProvider: ' + addressProvider, err); })); }); return Promise.all(promises).then(function () { return Array.from(new Set(Array.from(addresses).concat(Array.from(providerAddresses)))); }); }; /** * 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; }; /** * 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.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.tryConnectingToAddresses = function (index, remainingAttemptLimit, attemptPeriod, cause) { var _this = this; this.logger.debug('ClusterService', 'Trying to connect to addresses, remaining attempt limit: ' + remainingAttemptLimit + 'attempt period: ' + attemptPeriod); if (this.knownAddresses.length <= index) { remainingAttemptLimit = remainingAttemptLimit - 1; if (remainingAttemptLimit === 0) { var errorMessage = 'Unable to connect to any of the following addresses: ' + this.knownAddresses.map(function (element) { return element.toString(); }).join(', '); this.logger.debug('ClusterService', errorMessage); var error = new HazelcastError_1.IllegalStateError(errorMessage, cause); return Promise.reject(error); } else { var deferred_1 = Promise.defer(); setTimeout(function () { _this.tryConnectingToAddresses(0, remainingAttemptLimit, 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) { connection.setAuthenticatedAsOwner(true); _this.ownerConnection = connection; return _this.initMemberShipListener(); }).catch(function (e) { _this.logger.warn('ClusterService', e); return _this.tryConnectingToAddresses(index + 1, remainingAttemptLimit, attemptPeriod, e); }); } }; 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