UNPKG

reliable-zeromq

Version:

A collection of reliable zeromq messaging constructs

168 lines 13.7 kB
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWk1RUHVibGlzaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vU3JjL1pNUVB1Ymxpc2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbUVBQStDO0FBQy9DLDRDQUE4QjtBQUM5QixzREFBOEI7QUFDOUIscUNBQTRGO0FBQzVGLGtFQUEwQztBQUMxQyxvRUFBNEM7QUFDNUMsK0NBQTRDO0FBRy9CLFFBQUEsdUJBQXVCLEdBQVcsMkNBQTJDLENBQUM7QUFFM0YsSUFBWSxZQUlYO0FBSkQsV0FBWSxZQUFZO0lBRXBCLHVDQUF1QixDQUFBO0lBQ3ZCLG1DQUFtQixDQUFBO0FBQ3ZCLENBQUMsRUFKVyxZQUFZLEdBQVosb0JBQVksS0FBWixvQkFBWSxRQUl2QjtBQUVELElBQVksZUFNWDtBQU5ELFdBQVksZUFBZTtJQUV2Qix1REFBSyxDQUFBO0lBQ0wsbUVBQVcsQ0FBQTtJQUNYLHVEQUFLLENBQUE7SUFDTCwyREFBTyxDQUFBO0FBQ1gsQ0FBQyxFQU5XLGVBQWUsR0FBZix1QkFBZSxLQUFmLHVCQUFlLFFBTTFCO0FBY0QsTUFBYSxZQUFZO0lBWXJCLFlBQW1CLFNBQWlDLEVBQUUsY0FBMkM7UUFQaEYsbUJBQWMsR0FBb0QsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUU1RSxrQkFBYSxHQUEyQixJQUFJLDhCQUFLLEVBQUUsQ0FBQztRQUU3RCxtQkFBYyxHQUFZLElBQUksQ0FBQztRQUN0QixrQkFBYSxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBbUMvRCxrQkFBYSxHQUFHLENBQUMsUUFBZ0IsRUFBbUIsRUFBRTtZQUUxRCxNQUFNLFFBQVEsR0FBcUIsb0JBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDOUQsTUFBTSxNQUFNLEdBQVcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRW5DLE1BQU0sZUFBZSxHQUFhLEVBQUUsQ0FBQztZQUNyQyxLQUFLLElBQUksQ0FBQyxHQUFXLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFDaEQ7Z0JBQ0ksZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBVyxDQUFDLENBQUMsQ0FBRSwrRUFBK0U7YUFDbEk7WUFFRCxNQUFNLGtCQUFrQixHQUF1QixFQUFFLENBQUM7WUFDbEQsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFDbkM7Z0JBQ0ksS0FBSyxJQUFJLENBQUMsR0FBVyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEVBQ3ZEO29CQUNJLE1BQU0sVUFBVSxHQUFXLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDOUMsTUFBTSxRQUFRLEdBQWdDLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztvQkFDL0Ysa0JBQWtCLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLCtCQUF1QixDQUFDLENBQUMsQ0FBQztpQkFDbEU7YUFDSjtZQUVELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxvQkFBVSxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7UUFDckUsQ0FBQyxDQUFBO1FBdERHLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxJQUFJLDZDQUFvQyxDQUFDO1FBRTdFLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELElBQVcsUUFBUTtRQUVmLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQztJQUMzQyxDQUFDO0lBRU8sS0FBSyxDQUFDLGVBQWU7UUFFekIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFxQixFQUFFLFNBQWlCLEVBQVEsRUFBRTtZQUUxRSxJQUFJLE1BQU0sQ0FBQyxzQkFBc0IsR0FBRyxnQkFBTSxDQUFDLGlCQUFpQixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFDMUU7Z0JBQ0ksSUFBSSxDQUFDLFlBQVksQ0FDYjtvQkFDSSxTQUFTO29CQUNULFlBQVksQ0FBQyxTQUFTO29CQUN0QixNQUFNLENBQUMsa0JBQWtCO29CQUN6QixFQUFFO2lCQUNMLENBQ0osQ0FBQzthQUNMO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsZ0JBQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3hGLENBQUM7SUEyQk8scUJBQXFCLENBQUMsTUFBVyxFQUFFLGlCQUEyQjtRQUVsRSxJQUFJLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUNyRDtZQUNJLElBQUksQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUM7Z0JBQ3JDLEtBQUssRUFBRSxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDO2dCQUMvQyxLQUFLLEVBQUUsTUFBTSxDQUFDLGlCQUFpQixDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDdkQsT0FBTyxFQUFFLGlCQUFpQixDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUM7YUFDdEQsQ0FBQyxDQUFDO1NBQ047YUFFRDtZQUNJLE1BQU0sTUFBTSxDQUFDO1NBQ2hCO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjO1FBRXhCLE1BQU0sU0FBUyxHQUFnQyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO1FBRXpFLElBQUksU0FBUyxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQ3BDO1lBQ0ksTUFBTSxpQkFBaUIsR0FBYSxTQUFxQixDQUFDLENBQUUsdURBQXVEO1lBQ25ILGlCQUFpQixDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7WUFFL0YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztZQUM1QixJQUNBO2dCQUNJLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztnQkFFOUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFFLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUUsMENBQTBDO2FBQ3JKO1lBQ0QsT0FBTyxNQUFNLEVBQ2I7Z0JBQ0ksSUFBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO2FBQ3pEO1lBQ0QsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7WUFFM0IsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1NBQ3pCO0lBQ0wsQ0FBQztJQUVPLFlBQVksQ0FBQyxRQUF5QjtRQUUxQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVNLEtBQUs7UUFFUixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLFlBQVksQ0FBQyxJQUFJLENBQUMsaUJBQWtCLENBQUMsQ0FBQztRQUV0QyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQTBDLEVBQUUsRUFBRTtZQUV2RSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVUsQ0FBQztJQUNqQyxDQUFDO0lBRU0sS0FBSyxDQUFDLElBQUk7UUFFYixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUkseUJBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDcEYsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUM7UUFDcEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQzlCLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRTVELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRU0sT0FBTyxDQUFDLE1BQWMsRUFBRSxLQUFhO1FBRXhDLElBQUksTUFBTSxHQUFtRCxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM3RixJQUFJLENBQUMsTUFBTSxFQUNYO1lBQ0ksTUFBTSxHQUFHLElBQUksbUJBQVMsQ0FBQyxDQUFDLEdBQUcsZ0JBQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNsRCxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDM0M7UUFFRCxJQUFJLGFBQWEsR0FBOEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDOUUsSUFBSSxDQUFDLGFBQWEsRUFDbEI7WUFDSSxhQUFhO2dCQUNiO29CQUNJLGtCQUFrQixFQUFFLENBQUMsQ0FBQztvQkFDdEIsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO2lCQUM3QixDQUFDO1lBQ0YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1NBQ2pEO1FBRUQsTUFBTSxhQUFhLEdBQVcsRUFBRSxhQUFhLENBQUMsa0JBQWtCLENBQUM7UUFDakUsTUFBTSxRQUFRLEdBQ2Q7WUFDSSxNQUFNO1lBQ04sWUFBWSxDQUFDLE9BQU87WUFDcEIsYUFBYTtZQUNiLEtBQUs7U0FDUixDQUFDO1FBQ0YsTUFBTSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDcEMsYUFBYSxDQUFDLHNCQUFzQixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUVsRCxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7Q0FDSjtBQWpMRCxvQ0FpTEMifQ==