hazelcast-client
Version:
Hazelcast - open source In-Memory Data Grid - client for NodeJS
215 lines • 10.2 kB
JavaScript
;
/*
* 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 LoggingService_1 = require("../logging/LoggingService");
var events_1 = require("events");
var HazelcastError_1 = require("../HazelcastError");
var ClientConnection_1 = require("./ClientConnection");
var ConnectionAuthenticator_1 = require("./ConnectionAuthenticator");
var net = require("net");
var tls = require("tls");
var Util_1 = require("../Util");
var BasicSSLOptionsFactory_1 = require("../connection/BasicSSLOptionsFactory");
var EMIT_CONNECTION_CLOSED = 'connectionClosed';
var EMIT_CONNECTION_OPENED = 'connectionOpened';
/**
* Maintains connections between the client and members of the cluster.
*/
var ClientConnectionManager = /** @class */ (function (_super) {
__extends(ClientConnectionManager, _super);
function ClientConnectionManager(client, addressTranslator, addressProviders) {
var _this = _super.call(this) || this;
_this.establishedConnections = {};
_this.pendingConnections = {};
_this.logger = LoggingService_1.LoggingService.getLoggingService();
_this.client = client;
_this.addressTranslator = addressTranslator;
_this.addressProviders = addressProviders;
return _this;
}
ClientConnectionManager.prototype.getActiveConnections = function () {
return this.establishedConnections;
};
/**
* Returns the {@link ClientConnection} with given {@link Address}. If there is no such connection established,
* it first connects to the address and then return the {@link ClientConnection}.
* @param address
* @param asOwner Sets the connected node as owner of this client if true.
* @returns {Promise<ClientConnection>|Promise<T>}
*/
ClientConnectionManager.prototype.getOrConnect = function (address, asOwner) {
var _this = this;
if (asOwner === void 0) { asOwner = false; }
var addressIndex = address.toString();
var connectionResolver = Promise.defer();
var establishedConnection = this.establishedConnections[addressIndex];
if (establishedConnection) {
connectionResolver.resolve(establishedConnection);
return connectionResolver.promise;
}
var pendingConnection = this.pendingConnections[addressIndex];
if (pendingConnection) {
return pendingConnection.promise;
}
this.pendingConnections[addressIndex] = connectionResolver;
var processResponseCallback = function (data) {
_this.client.getInvocationService().processResponse(data);
};
this.addressTranslator.translate(address).then(function (addr) {
if (addr == null) {
throw new RangeError('Address Translator could not translate address ' + addr.toString());
}
_this.triggerConnect(addr, asOwner).then(function (socket) {
var clientConnection = new ClientConnection_1.ClientConnection(_this.client, addr, socket);
return _this.initiateCommunication(clientConnection).then(function () {
return clientConnection.registerResponseCallback(processResponseCallback);
}).then(function () {
return _this.authenticate(clientConnection, asOwner);
}).then(function () {
_this.establishedConnections[clientConnection.getAddress().toString()] = clientConnection;
_this.onConnectionOpened(clientConnection);
connectionResolver.resolve(clientConnection);
});
}).catch(function (e) {
connectionResolver.reject(e);
}).finally(function () {
delete _this.pendingConnections[addressIndex];
});
});
var connectionTimeout = this.client.getConfig().networkConfig.connectionTimeout;
if (connectionTimeout !== 0) {
return connectionResolver.promise.timeout(connectionTimeout, new HazelcastError_1.HazelcastError('Connection timed-out'));
}
return connectionResolver.promise;
};
/**
* Destroys the connection with given node address.
* @param address
*/
ClientConnectionManager.prototype.destroyConnection = function (address) {
var addressStr = address.toString();
if (this.pendingConnections.hasOwnProperty(addressStr)) {
this.pendingConnections[addressStr].reject(null);
}
if (this.establishedConnections.hasOwnProperty(addressStr)) {
var conn = this.establishedConnections[addressStr];
delete this.establishedConnections[addressStr];
conn.close();
this.onConnectionClosed(conn);
}
};
ClientConnectionManager.prototype.shutdown = function () {
for (var pending in this.pendingConnections) {
this.pendingConnections[pending].reject(new HazelcastError_1.ClientNotActiveError('Client is shutting down!'));
}
for (var conn in this.establishedConnections) {
this.establishedConnections[conn].close();
}
};
ClientConnectionManager.prototype.triggerConnect = function (address, asOwner) {
var _this = this;
if (!asOwner) {
if (this.client.getClusterService().getOwnerConnection() == null) {
var error = new HazelcastError_1.IllegalStateError('Owner connection is not available!');
return Promise.reject(error);
}
}
if (this.client.getConfig().networkConfig.sslOptions) {
var opts = this.client.getConfig().networkConfig.sslOptions;
return this.connectTLSSocket(address, opts);
}
else if (this.client.getConfig().networkConfig.sslOptionsFactoryConfig) {
var factoryConfig = this.client.getConfig().networkConfig.sslOptionsFactoryConfig;
var factoryProperties = this.client.getConfig().networkConfig.sslOptionsFactoryProperties;
var factory_1;
if (factoryConfig.path) {
factory_1 = new (Util_1.loadNameFromPath(factoryConfig.path, factoryConfig.exportedName))();
}
else {
factory_1 = new BasicSSLOptionsFactory_1.BasicSSLOptionsFactory();
}
return factory_1.init(factoryProperties).then(function () {
return _this.connectTLSSocket(address, factory_1.getSSLOptions());
});
}
else {
return this.connectNetSocket(address);
}
};
ClientConnectionManager.prototype.connectTLSSocket = function (address, configOpts) {
var _this = this;
var connectionResolver = Promise.defer();
var socket = tls.connect(address.port, address.host, configOpts);
socket.once('secureConnect', function () {
connectionResolver.resolve(socket);
});
socket.on('error', function (e) {
_this.logger.warn('ClientConnectionManager', 'Could not connect to address ' + address.toString(), e);
connectionResolver.reject(e);
if (e.code === 'EPIPE' || e.code === 'ECONNRESET') {
_this.destroyConnection(address);
}
});
return connectionResolver.promise;
};
ClientConnectionManager.prototype.connectNetSocket = function (address) {
var _this = this;
var connectionResolver = Promise.defer();
var socket = net.connect(address.port, address.host);
socket.once('connect', function () {
connectionResolver.resolve(socket);
});
socket.on('error', function (e) {
_this.logger.warn('ClientConnectionManager', 'Could not connect to address ' + address.toString(), e);
connectionResolver.reject(e);
if (e.code === 'EPIPE' || e.code === 'ECONNRESET') {
_this.destroyConnection(address);
}
});
return connectionResolver.promise;
};
ClientConnectionManager.prototype.initiateCommunication = function (connection) {
// Send the protocol version
var buffer = new Buffer(3);
buffer.write('CB2');
return connection.write(buffer);
};
ClientConnectionManager.prototype.onConnectionClosed = function (connection) {
this.emit(EMIT_CONNECTION_CLOSED, connection);
};
ClientConnectionManager.prototype.onConnectionOpened = function (connection) {
this.emit(EMIT_CONNECTION_OPENED, connection);
};
ClientConnectionManager.prototype.authenticate = function (connection, ownerConnection) {
var authenticator = new ConnectionAuthenticator_1.ConnectionAuthenticator(connection, this.client);
return authenticator.authenticate(ownerConnection);
};
return ClientConnectionManager;
}(events_1.EventEmitter));
exports.ClientConnectionManager = ClientConnectionManager;
//# sourceMappingURL=ClientConnectionManager.js.map