hazelcast-client
Version:
Hazelcast - open source In-Memory Data Grid - client for NodeJS
234 lines • 12.1 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var Promise = require("bluebird");
var events_1 = require("events");
var HazelcastError_1 = require("./HazelcastError");
var ClientEventRegistration_1 = require("./invocation/ClientEventRegistration");
var InvocationService_1 = require("./invocation/InvocationService");
var RegistrationKey_1 = require("./invocation/RegistrationKey");
var LoggingService_1 = require("./logging/LoggingService");
var Util_1 = require("./Util");
var UuidUtil_1 = require("./util/UuidUtil");
var ListenerService = /** @class */ (function () {
function ListenerService(client) {
this.logger = LoggingService_1.LoggingService.getLoggingService();
this.isShutdown = false;
this.client = client;
this.isSmartService = this.client.getConfig().networkConfig.smartRouting;
this.internalEventEmitter = new events_1.EventEmitter();
this.internalEventEmitter.setMaxListeners(0);
this.activeRegistrations = new Map();
this.failedRegistrations = new Map();
this.userRegistrationKeyInformation = new Map();
this.connectionRefreshTaskInterval = 2000;
}
ListenerService.prototype.start = function () {
this.client.getConnectionManager().on('connectionOpened', this.onConnectionAdded.bind(this));
this.client.getConnectionManager().on('connectionClosed', this.onConnectionRemoved.bind(this));
if (this.isSmart()) {
this.connectionRefreshTask = this.connectionRefreshHandler();
}
};
ListenerService.prototype.onConnectionAdded = function (connection) {
this.reregisterListenersOnConnection(connection);
};
ListenerService.prototype.onConnectionRemoved = function (connection) {
this.removeRegistrationsOnConnection(connection);
};
ListenerService.prototype.onHeartbeatRestored = function (connection) {
var _this = this;
var failedRegistrationsOnConn = this.failedRegistrations.get(connection);
failedRegistrationsOnConn.forEach(function (userKey, ignored) {
_this.invokeRegistrationFromRecord(userKey, connection);
});
};
ListenerService.prototype.reregisterListeners = function () {
var connections = this.client.getConnectionManager().getActiveConnections();
for (var connAddress in connections) {
this.reregisterListenersOnConnection(connections[connAddress]);
}
};
ListenerService.prototype.reregisterListenersOnConnection = function (connection) {
var _this = this;
this.activeRegistrations.forEach(function (registrationMap, userKey) {
if (registrationMap.has(connection)) {
return;
}
_this.invokeRegistrationFromRecord(userKey, connection).then(function (eventRegistration) {
registrationMap.set(connection, eventRegistration);
}).catch(function (e) {
_this.logger.warn('ListenerService', e);
});
}, this);
};
ListenerService.prototype.removeRegistrationsOnConnection = function (connection) {
var _this = this;
this.failedRegistrations.delete(connection);
this.activeRegistrations.forEach(function (registrationsOnUserKey, userKey) {
var eventRegistration = registrationsOnUserKey.get(connection);
if (eventRegistration !== undefined) {
_this.client.getInvocationService().removeEventHandler(eventRegistration.correlationId.toNumber());
}
});
};
ListenerService.prototype.invokeRegistrationFromRecord = function (userRegistrationKey, connection) {
var _this = this;
var deferred = Promise.defer();
var activeRegsOnUserKey = this.activeRegistrations.get(userRegistrationKey);
if (activeRegsOnUserKey !== undefined && activeRegsOnUserKey.has(connection)) {
deferred.resolve(activeRegsOnUserKey.get(connection));
return deferred.promise;
}
var registrationKey = this.userRegistrationKeyInformation.get(userRegistrationKey);
var registerRequest = registrationKey.getRegisterRequest();
var codec = registrationKey.getCodec();
var invocation = new InvocationService_1.Invocation(this.client, registerRequest);
invocation.handler = registrationKey.getHandler();
invocation.connection = connection;
this.client.getInvocationService().invoke(invocation).then(function (responseMessage) {
var correlationId = responseMessage.getCorrelationId();
var response = codec.decodeAddResponse(responseMessage);
var eventRegistration = new ClientEventRegistration_1.ClientEventRegistration(response, correlationId, invocation.connection, codec);
_this.logger.debug('ListenerService', 'Listener ' + userRegistrationKey + ' re-registered on ' + connection.toString());
deferred.resolve(eventRegistration);
}).catch((function (e) {
var failedRegsOnConnection = _this.failedRegistrations.get(connection);
if (failedRegsOnConnection === undefined) {
failedRegsOnConnection = new Set();
failedRegsOnConnection.add(userRegistrationKey);
_this.failedRegistrations.set(connection, failedRegsOnConnection);
}
else {
failedRegsOnConnection.add(userRegistrationKey);
}
deferred.reject(new HazelcastError_1.HazelcastError('Could not add listener[' + userRegistrationKey +
'] to connection[' + connection.toString() + ']', e));
}));
return deferred.promise;
};
ListenerService.prototype.registerListener = function (codec, registerHandlerFunc) {
var _this = this;
var readyToRegisterPromise;
if (this.isSmart()) {
readyToRegisterPromise = this.trySyncConnectToAllConnections();
}
else {
// No need for preparation, just return a resolved promise
readyToRegisterPromise = Promise.resolve();
}
return readyToRegisterPromise.then(function () {
return _this.registerListenerInternal(codec, registerHandlerFunc);
});
};
ListenerService.prototype.deregisterListener = function (userRegistrationKey) {
var _this = this;
var deferred = Promise.defer();
var registrationsOnUserKey = this.activeRegistrations.get(userRegistrationKey);
if (registrationsOnUserKey === undefined) {
deferred.resolve(false);
return deferred.promise;
}
registrationsOnUserKey.forEach(function (eventRegistration, connection) {
var clientMessage = eventRegistration.codec.encodeRemoveRequest(eventRegistration.serverRegistrationId);
var invocation = new InvocationService_1.Invocation(_this.client, clientMessage);
invocation.connection = eventRegistration.subscriber;
_this.client.getInvocationService().invoke(invocation).then(function (responseMessage) {
registrationsOnUserKey.delete(connection);
_this.client.getInvocationService().removeEventHandler(eventRegistration.correlationId.low);
_this.logger.debug('ListenerService', 'Listener ' + userRegistrationKey + ' unregistered from ' + invocation.connection.toString());
_this.activeRegistrations.delete(userRegistrationKey);
_this.userRegistrationKeyInformation.delete(userRegistrationKey);
deferred.resolve(true);
});
});
return deferred.promise;
};
ListenerService.prototype.isSmart = function () {
return this.isSmartService;
};
ListenerService.prototype.shutdown = function () {
this.isShutdown = true;
clearTimeout(this.connectionRefreshTask);
};
ListenerService.prototype.connectionRefreshHandler = function () {
var _this = this;
if (this.isShutdown) {
return;
}
this.trySyncConnectToAllConnections().catch(function (e) {
}).finally(function () {
_this.connectionRefreshTask =
setTimeout(_this.connectionRefreshHandler.bind(_this), _this.connectionRefreshTaskInterval);
});
};
ListenerService.prototype.registerListenerInternal = function (codec, listenerHandlerFunc) {
var _this = this;
var activeConnections = Util_1.copyObjectShallow(this.client.getConnectionManager().getActiveConnections());
var userRegistrationKey = UuidUtil_1.UuidUtil.generate().toString();
var connectionsOnUserKey;
var deferred = Promise.defer();
var registerRequest = codec.encodeAddRequest(this.isSmart());
connectionsOnUserKey = this.activeRegistrations.get(userRegistrationKey);
if (connectionsOnUserKey === undefined) {
connectionsOnUserKey = new Map();
this.activeRegistrations.set(userRegistrationKey, connectionsOnUserKey);
this.userRegistrationKeyInformation.set(userRegistrationKey, new RegistrationKey_1.RegistrationKey(userRegistrationKey, codec, registerRequest, listenerHandlerFunc));
}
var _loop_1 = function (address) {
if (connectionsOnUserKey.has(activeConnections[address])) {
return "continue";
}
var invocation = new InvocationService_1.Invocation(this_1.client, registerRequest);
invocation.handler = listenerHandlerFunc;
invocation.connection = activeConnections[address];
this_1.client.getInvocationService().invoke(invocation).then(function (responseMessage) {
var correlationId = responseMessage.getCorrelationId();
var response = codec.decodeAddResponse(responseMessage);
var clientEventRegistration = new ClientEventRegistration_1.ClientEventRegistration(response, correlationId, invocation.connection, codec);
_this.logger.debug('ListenerService', 'Listener ' + userRegistrationKey + ' registered on ' + invocation.connection.toString());
connectionsOnUserKey.set(activeConnections[address], clientEventRegistration);
}).then(function () {
deferred.resolve(userRegistrationKey);
}).catch(function (e) {
if (invocation.connection.isAlive()) {
_this.deregisterListener(userRegistrationKey);
deferred.reject(new HazelcastError_1.HazelcastError('Listener cannot be added!', e));
}
});
};
var this_1 = this;
for (var address in activeConnections) {
_loop_1(address);
}
return deferred.promise;
};
ListenerService.prototype.trySyncConnectToAllConnections = function () {
var _this = this;
assert(this.isSmart());
var members = this.client.getClusterService().getMembers();
var promises = [];
members.forEach(function (member) {
promises.push(_this.client.getConnectionManager().getOrConnect(member.address));
});
return Promise.all(promises).thenReturn();
};
return ListenerService;
}());
exports.ListenerService = ListenerService;
//# sourceMappingURL=ListenerService.js.map