hazelcast-client
Version:
Hazelcast - open source In-Memory Data Grid - client for NodeJS
199 lines • 8.55 kB
JavaScript
"use strict";
var ClientMessage = require("../ClientMessage");
var Promise = require("bluebird");
var Long = require("long");
var Address = require("../Address");
var ExceptionCodec = require("../codec/ExceptionCodec");
var BitsUtil_1 = require("../BitsUtil");
var LoggingService_1 = require("../logging/LoggingService");
var events_1 = require("events");
var EXCEPTION_MESSAGE_TYPE = 109;
var INVOCATION_TIMEOUT = 120000;
var INVOCATION_RETRY_DELAY = 1000;
var Invocation = (function () {
function Invocation(request) {
this.deadline = new Date(new Date().getTime() + INVOCATION_TIMEOUT);
this.request = request;
}
Invocation.prototype.hasPartitionId = function () {
return this.hasOwnProperty('partitionId') && this.partitionId >= 0;
};
return Invocation;
}());
exports.Invocation = Invocation;
var InvocationService = (function () {
function InvocationService(hazelcastClient) {
this.correlationCounter = 1;
this.eventHandlers = {};
this.pending = {};
this.logger = LoggingService_1.LoggingService.getLoggingService();
this.client = hazelcastClient;
this.smartRoutingEnabled = hazelcastClient.getConfig().networkConfig.smartRouting;
if (hazelcastClient.getConfig().networkConfig.smartRouting) {
this.invoke = this.invokeSmart;
}
else {
this.invoke = this.invokeNonSmart;
}
}
InvocationService.prototype.invokeOnConnection = function (connection, request, handler) {
var invocation = new Invocation(request);
invocation.connection = connection;
if (handler) {
invocation.handler = handler;
}
return this.invoke(invocation);
};
InvocationService.prototype.invokeOnPartition = function (request, partitionId) {
var invocation = new Invocation(request);
invocation.partitionId = partitionId;
return this.invoke(invocation);
};
InvocationService.prototype.invokeOnTarget = function (request, target) {
var invocation = new Invocation(request);
invocation.address = target;
return this.invoke(invocation);
};
InvocationService.prototype.invokeOnRandomTarget = function (request) {
return this.invoke(new Invocation(request));
};
InvocationService.prototype.invokeSmart = function (invocation) {
if (invocation.hasOwnProperty('connection')) {
return this.send(invocation, invocation.connection);
}
else if (invocation.hasPartitionId()) {
var address = this.client.getPartitionService().getAddressForPartition(invocation.partitionId);
return this.sendToAddress(invocation, address);
}
else if (invocation.hasOwnProperty('address')) {
return this.sendToAddress(invocation, invocation.address);
}
else {
return this.send(invocation, this.client.getClusterService().getOwnerConnection());
}
};
InvocationService.prototype.invokeNonSmart = function (invocation) {
if (invocation.hasOwnProperty('connection')) {
return this.send(invocation, invocation.connection);
}
else {
return this.send(invocation, this.client.getClusterService().getOwnerConnection());
}
};
InvocationService.prototype.sendToAddress = function (invocation, address) {
var _this = this;
return this.client.getConnectionManager().getOrConnect(address)
.then(function (connection) {
return _this.send(invocation, connection);
});
};
InvocationService.prototype.send = function (invocation, connection) {
var correlationId = this.correlationCounter++;
var message = invocation.request;
message.setCorrelationId(Long.fromNumber(correlationId));
if (invocation.hasPartitionId()) {
message.setPartitionId(invocation.partitionId);
}
else {
message.setPartitionId(-1);
}
invocation.deferred = Promise.defer();
if (invocation.hasOwnProperty('handler')) {
this.eventHandlers[correlationId] = invocation;
}
this.pending[correlationId] = invocation;
var logger = this.logger;
connection.write(invocation.request.getBuffer(), function (err) {
if (err) {
logger.warn('InvocationService', 'Error sending message to ' + Address.encodeToString(connection.address) + ' ' + err);
invocation.deferred.reject(err);
}
});
return invocation.deferred.promise;
};
InvocationService.prototype.removeEventHandler = function (id) {
if (this.eventHandlers.hasOwnProperty('' + id)) {
delete this.eventHandlers[id];
}
};
InvocationService.prototype.processResponse = function (buffer) {
var _this = this;
var clientMessage = new ClientMessage(buffer);
var correlationId = clientMessage.getCorrelationId().toNumber();
var messageType = clientMessage.getMessageType();
if (clientMessage.hasFlags(BitsUtil_1.BitsUtil.LISTENER_FLAG)) {
setImmediate(function () {
_this.eventHandlers[correlationId].handler(clientMessage);
});
return;
}
var invocationFinished = true;
var pendingInvocation = this.pending[correlationId];
var deferred = pendingInvocation.deferred;
if (messageType === EXCEPTION_MESSAGE_TYPE) {
var remoteException = ExceptionCodec.decodeResponse(clientMessage);
var boundToConnection = pendingInvocation.connection;
var deadlineExceeded = new Date().getTime() > pendingInvocation.deadline.getTime();
var shouldRetry = !boundToConnection && !deadlineExceeded && remoteException.isRetryable();
if (shouldRetry) {
invocationFinished = false;
setTimeout(function () {
_this.invoke(pendingInvocation);
}, INVOCATION_RETRY_DELAY);
}
else {
this.logger.trace('InvocationService', 'Received exception as response', remoteException);
deferred.reject(remoteException);
}
}
else {
deferred.resolve(clientMessage);
}
if (invocationFinished) {
delete this.pending[correlationId];
}
};
return InvocationService;
}());
exports.InvocationService = InvocationService;
var ListenerService = (function () {
function ListenerService(client) {
this.listenerIdToCorrelation = {};
this.client = client;
this.internalEventEmitter = new events_1.EventEmitter();
this.internalEventEmitter.setMaxListeners(0);
}
ListenerService.prototype.registerListener = function (request, handler, decoder, key) {
var _this = this;
if (key === void 0) { key = undefined; }
var deferred = Promise.defer();
var invocation = new Invocation(request);
invocation.handler = handler;
this.client.getInvocationService().invoke(invocation).then(function (responseMessage) {
var correlationId = responseMessage.getCorrelationId();
var response = decoder(responseMessage);
_this.listenerIdToCorrelation[response.response] = correlationId;
deferred.resolve(response.response);
});
return deferred.promise;
};
ListenerService.prototype.deregisterListener = function (request, decoder) {
var _this = this;
var deferred = Promise.defer();
var invocation = new Invocation(request);
var listenerIdToCorrelation = this.listenerIdToCorrelation;
this.client.getInvocationService().invoke(invocation).then(function (responseMessage) {
var correlationId = responseMessage.getCorrelationId().toString();
if (listenerIdToCorrelation.hasOwnProperty(correlationId)) {
_this.client.getInvocationService().removeEventHandler(listenerIdToCorrelation[correlationId].low);
delete listenerIdToCorrelation[correlationId];
}
var response = decoder(responseMessage);
deferred.resolve(response.response);
});
return deferred.promise;
};
return ListenerService;
}());
exports.ListenerService = ListenerService;
//# sourceMappingURL=InvocationService.js.map