reliable-zeromq
Version:
A collection of reliable zeromq messaging constructs
168 lines • 13.7 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ZMQPublisher = exports.EPublishMessage = exports.EMessageType = exports.PUBLISHER_CACHE_EXPIRED = void 0;
const typescript_collections_1 = require("typescript-collections");
const zmq = __importStar(require("zeromq"));
const Config_1 = __importDefault(require("./Config"));
const Errors_1 = require("./Errors");
const ExpiryMap_1 = __importDefault(require("./Utils/ExpiryMap"));
const JSONBigInt_1 = __importDefault(require("./Utils/JSONBigInt"));
const ZMQResponse_1 = require("./ZMQResponse");
exports.PUBLISHER_CACHE_EXPIRED = "ZMQ_PUBLISHER ERROR: MESSAGE NOT IN CACHE";
var EMessageType;
(function (EMessageType) {
EMessageType["HEARTBEAT"] = "HEARTBEAT";
EMessageType["PUBLISH"] = "PUBLISH";
})(EMessageType = exports.EMessageType || (exports.EMessageType = {}));
var EPublishMessage;
(function (EPublishMessage) {
EPublishMessage[EPublishMessage["Topic"] = 0] = "Topic";
EPublishMessage[EPublishMessage["MessageType"] = 1] = "MessageType";
EPublishMessage[EPublishMessage["Nonce"] = 2] = "Nonce";
EPublishMessage[EPublishMessage["Message"] = 3] = "Message";
})(EPublishMessage = exports.EPublishMessage || (exports.EPublishMessage = {}));
class ZMQPublisher {
constructor(aEndpoint, aErrorHandlers) {
this.mMessageCaches = new Map();
this.mPublishQueue = new typescript_collections_1.Queue();
this.mSafeToPublish = true;
this.mTopicDetails = new Map();
this.HandleRequest = (aMessage) => {
const lRequest = JSONBigInt_1.default.Parse(aMessage);
const lTopic = lRequest[0];
const lDecodedRequest = [];
for (let i = 1; i < lRequest.length; ++i) {
lDecodedRequest.push((lRequest[i])); // TRecoveryRequest is [string, ...number[]], so values at index 1+ are numbers
}
const lRequestedMessages = [];
if (this.mMessageCaches.has(lTopic)) {
for (let i = 0; i < lDecodedRequest.length; ++i) {
const lMessageId = lDecodedRequest[i];
const lMessage = this.mMessageCaches.get(lTopic).get(lMessageId);
lRequestedMessages.push(lMessage ?? [exports.PUBLISHER_CACHE_EXPIRED]);
}
}
return Promise.resolve(JSONBigInt_1.default.Stringify(lRequestedMessages));
};
this.mEndpoint = aEndpoint;
this.mErrorHandlers = aErrorHandlers ?? Errors_1.DEFAULT_ZMQ_PUBLISHER_ERROR_HANDLERS;
this.CheckHeartbeats = this.CheckHeartbeats.bind(this);
}
get Endpoint() {
return this.mEndpoint.PublisherAddress;
}
async CheckHeartbeats() {
this.mTopicDetails.forEach((aValue, aTopicKey) => {
if (aValue.LatestMessageTimestamp + Config_1.default.HeartBeatInterval <= Date.now()) {
this.QueuePublish([
aTopicKey,
EMessageType.HEARTBEAT,
aValue.LatestMessageNonce,
"",
]);
}
});
this.mHeartbeatTimeout = setTimeout(this.CheckHeartbeats, Config_1.default.HeartBeatInterval);
}
HandleZMQPublishError(aError, aFormattedMessage) {
if (aError && aError.code && aError.code === "EAGAIN") {
this.mErrorHandlers.HighWaterMarkWarning({
Topic: aFormattedMessage[EPublishMessage.Topic],
Nonce: Number(aFormattedMessage[EPublishMessage.Nonce]),
Message: aFormattedMessage[EPublishMessage.Message],
});
}
else {
throw aError;
}
}
async ProcessPublish() {
const lNextSend = this.mPublishQueue.peek();
if (lNextSend && this.mSafeToPublish) {
const lFormattedMessage = lNextSend; // We replace the number with a string on the next line
lFormattedMessage[EPublishMessage.Nonce] = lFormattedMessage[EPublishMessage.Nonce].toString();
this.mPublishQueue.dequeue();
this.mSafeToPublish = false;
try {
await this.mPublisher.send(lFormattedMessage);
this.mTopicDetails.get(lFormattedMessage[EPublishMessage.Topic]).LatestMessageTimestamp = Date.now(); // Update for the purposes of heartbeating
}
catch (aError) {
this.HandleZMQPublishError(aError, lFormattedMessage);
}
this.mSafeToPublish = true;
this.ProcessPublish();
}
}
QueuePublish(aMessage) {
this.mPublishQueue.enqueue(aMessage);
this.ProcessPublish();
}
Close() {
this.mResponse.Close();
clearTimeout(this.mHeartbeatTimeout);
this.mMessageCaches.forEach((aCache) => {
aCache.clear();
});
this.mPublisher.linger = 0;
this.mPublisher.close();
this.mPublisher = undefined;
}
async Open() {
this.mResponse = new ZMQResponse_1.ZMQResponse(this.mEndpoint.RequestAddress, this.HandleRequest);
this.mPublisher = new zmq.Publisher;
this.mPublisher.noDrop = true;
await this.mPublisher.bind(this.mEndpoint.PublisherAddress);
this.CheckHeartbeats();
}
Publish(aTopic, aData) {
let lCache = this.mMessageCaches.get(aTopic);
if (!lCache) {
lCache = new ExpiryMap_1.default(3 * Config_1.default.MaximumLatency);
this.mMessageCaches.set(aTopic, lCache);
}
let lTopicDetails = this.mTopicDetails.get(aTopic);
if (!lTopicDetails) {
lTopicDetails =
{
LatestMessageNonce: -1,
LatestMessageTimestamp: -1,
};
this.mTopicDetails.set(aTopic, lTopicDetails);
}
const lMessageNonce = ++lTopicDetails.LatestMessageNonce;
const lMessage = [
aTopic,
EMessageType.PUBLISH,
lMessageNonce,
aData,
];
lCache.set(lMessageNonce, lMessage);
lTopicDetails.LatestMessageTimestamp = Date.now();
this.QueuePublish(lMessage);
}
}
exports.ZMQPublisher = ZMQPublisher;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWk1RUHVibGlzaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vU3JjL1pNUVB1Ymxpc2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbUVBQStDO0FBQy9DLDRDQUE4QjtBQUM5QixzREFBOEI7QUFDOUIscUNBQTRGO0FBQzVGLGtFQUEwQztBQUMxQyxvRUFBNEM7QUFDNUMsK0NBQTRDO0FBRy9CLFFBQUEsdUJBQXVCLEdBQVcsMkNBQTJDLENBQUM7QUFFM0YsSUFBWSxZQUlYO0FBSkQsV0FBWSxZQUFZO0lBRXBCLHVDQUF1QixDQUFBO0lBQ3ZCLG1DQUFtQixDQUFBO0FBQ3ZCLENBQUMsRUFKVyxZQUFZLEdBQVosb0JBQVksS0FBWixvQkFBWSxRQUl2QjtBQUVELElBQVksZUFNWDtBQU5ELFdBQVksZUFBZTtJQUV2Qix1REFBSyxDQUFBO0lBQ0wsbUVBQVcsQ0FBQTtJQUNYLHVEQUFLLENBQUE7SUFDTCwyREFBTyxDQUFBO0FBQ1gsQ0FBQyxFQU5XLGVBQWUsR0FBZix1QkFBZSxLQUFmLHVCQUFlLFFBTTFCO0FBY0QsTUFBYSxZQUFZO0lBWXJCLFlBQW1CLFNBQWlDLEVBQUUsY0FBMkM7UUFQaEYsbUJBQWMsR0FBb0QsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUU1RSxrQkFBYSxHQUEyQixJQUFJLDhCQUFLLEVBQUUsQ0FBQztRQUU3RCxtQkFBYyxHQUFZLElBQUksQ0FBQztRQUN0QixrQkFBYSxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBbUMvRCxrQkFBYSxHQUFHLENBQUMsUUFBZ0IsRUFBbUIsRUFBRTtZQUUxRCxNQUFNLFFBQVEsR0FBcUIsb0JBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDOUQsTUFBTSxNQUFNLEdBQVcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRW5DLE1BQU0sZUFBZSxHQUFhLEVBQUUsQ0FBQztZQUNyQyxLQUFLLElB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