UNPKG

reliable-zeromq

Version:

A collection of reliable zeromq messaging constructs

249 lines 24.1 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 }); const ava_1 = __importDefault(require("ava")); const Sinon = __importStar(require("sinon")); const ts_mock_imports_1 = require("ts-mock-imports"); const zmq = __importStar(require("zeromq")); const Config_1 = __importDefault(require("../../Src/Config")); const JSONBigInt_1 = __importDefault(require("../../Src/Utils/JSONBigInt")); const ZMQPublisher_1 = require("../../Src/ZMQPublisher"); const ZMQResponse = __importStar(require("../../Src/ZMQResponse")); const AsyncTools_1 = require("../Helpers/AsyncTools"); const DummyEndpoints_data_1 = require("../Helpers/DummyEndpoints.data"); const test = ava_1.default; test.before((t) => { // Unnecessary }); test.beforeEach((t) => { const lResponderMock = ts_mock_imports_1.ImportMock.mockClass(ZMQResponse, "ZMQResponse"); const lPublisherMock = ts_mock_imports_1.ImportMock.mockClass(zmq, "Publisher"); t.context = { PublisherMock: lPublisherMock, ResponderMock: lResponderMock, TestData: [ { a: 100n, b: 20n, c: 0.5, d: [ 5n, "myFunc()", ], }, ], Endpoints: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES, }; }); test.afterEach((t) => { Sinon.restore(); ts_mock_imports_1.ImportMock.restore(); }); test.serial("Start, Publish, Respond, Close", async (t) => { const clock = Sinon.useFakeTimers(); const lZmqPublisher = t.context.PublisherMock; const lPublisher = new ZMQPublisher_1.ZMQPublisher(t.context.Endpoints); lZmqPublisher.mock("bind", Promise.resolve()); await lPublisher.Open(); t.is(lPublisher.Endpoint, DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress); const lSendMock = lZmqPublisher.mock("send", Promise.resolve()); lPublisher.Publish("myTopicA", "myFirstMessage"); t.is(lSendMock.callCount, 1); t.deepEqual(lSendMock.getCall(0).args[0], ["myTopicA", ZMQPublisher_1.EMessageType.PUBLISH, "0", "myFirstMessage"]); t.is(lPublisher["mMessageCaches"].size, 1); t.is(lPublisher["mMessageCaches"].get("myTopicA").size, 1); t.is(lPublisher["mTopicDetails"].size, 1); lPublisher.Publish("myTopicA", JSONBigInt_1.default.Stringify(t.context.TestData)); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, 2); t.deepEqual(lSendMock.getCall(1).args[0], ["myTopicA", ZMQPublisher_1.EMessageType.PUBLISH, "1", JSONBigInt_1.default.Stringify(t.context.TestData)]); t.is(lPublisher["mMessageCaches"].size, 1); t.is(lPublisher["mMessageCaches"].get("myTopicA").size, 2); t.is(lPublisher["mTopicDetails"].size, 1); const lRecoveryRequest = [ "myTopicA", 0, 1, ]; const lRecoveryResponse = await lPublisher["HandleRequest"](JSONBigInt_1.default.Stringify(lRecoveryRequest)); const lExpectedRecoveryResponse = [ lSendMock.getCall(0).args[0], lSendMock.getCall(1).args[0], ]; t.deepEqual(JSONBigInt_1.default.Parse(lRecoveryResponse), lExpectedRecoveryResponse); const lInvalidRecoveryRequest = [ -1, 0, ]; const lInvalidRecoveryResponse = await lPublisher["HandleRequest"](JSONBigInt_1.default.Stringify(lInvalidRecoveryRequest)); t.deepEqual(JSONBigInt_1.default.Parse(lInvalidRecoveryResponse), []); const lTestData = [ ["newTopicA", "myMessageA"], ["newTopicA", "myMessageB"], ["newTopicA", "myMessageC"], ["newTopic1", "myMessage~"], ["newTopic1", "myMessage~"], ]; lPublisher.Publish("newTopicA", "myMessageA"); lPublisher.Publish("newTopicA", "myMessageB"); lPublisher.Publish("newTopicA", "myMessageC"); lPublisher.Publish("newTopic1", "myMessage~"); lPublisher.Publish("newTopic1", "myMessage~"); await AsyncTools_1.YieldToEventLoop(); for (let i = 0; i < 5; ++i) { t.is(lSendMock.getCall(i + 2).args[0][ZMQPublisher_1.EPublishMessage.Topic], lTestData[i][0]); t.is(lSendMock.getCall(i + 2).args[0][ZMQPublisher_1.EPublishMessage.Message], lTestData[i][1]); } const lSecondRecoveryRequest = [ "newTopicA", 0, 1, 2, ]; const lThirdRecoveryRequest = [ "newTopic1", 0, 1, ]; const lSecondRecoveryResponse = await lPublisher["HandleRequest"](JSONBigInt_1.default.Stringify(lSecondRecoveryRequest)); const lThirdRecoveryResponse = await lPublisher["HandleRequest"](JSONBigInt_1.default.Stringify(lThirdRecoveryRequest)); const lExpectedSecondResponse = [ lSendMock.getCall(2).args[0], lSendMock.getCall(3).args[0], lSendMock.getCall(4).args[0], ]; const lExpectedThirdResponse = [ lSendMock.getCall(5).args[0], lSendMock.getCall(6).args[0], ]; t.deepEqual(JSONBigInt_1.default.Parse(lSecondRecoveryResponse), lExpectedSecondResponse); t.deepEqual(JSONBigInt_1.default.Parse(lThirdRecoveryResponse), lExpectedThirdResponse); t.is(lSendMock.callCount, 7); t.is(lPublisher["mTopicDetails"].size, 3); clock.tick(Config_1.default.HeartBeatInterval); await AsyncTools_1.YieldToEventLoop(); const lHeartbeats = [ lSendMock.getCall(7).args[0], lSendMock.getCall(8).args[0], lSendMock.getCall(9).args[0], ]; const lExpectedHeartbeats = [ ["myTopicA", ZMQPublisher_1.EMessageType.HEARTBEAT, "1", ""], ["newTopicA", ZMQPublisher_1.EMessageType.HEARTBEAT, "2", ""], ["newTopic1", ZMQPublisher_1.EMessageType.HEARTBEAT, "1", ""], ]; t.deepEqual(lHeartbeats, lExpectedHeartbeats); t.is(lSendMock.callCount, 10); clock.tick(Config_1.default.HeartBeatInterval); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, 13); lPublisher.Close(); }); test.serial("Errors & Warns", async (t) => { const clock = Sinon.useFakeTimers(); const lZmqPublisher = t.context.PublisherMock; // Set Config for Test: Config_1.default.MaximumLatency = 1000; Config_1.default.HeartBeatInterval = 500; const lSendMock = lZmqPublisher.mock("send", Promise.resolve()); lZmqPublisher.mock("bind", Promise.resolve()); const lWarnings = []; const lPublisher = new ZMQPublisher_1.ZMQPublisher(t.context.Endpoints); const lCustomPublisher = new ZMQPublisher_1.ZMQPublisher(t.context.Endpoints, { HighWaterMarkWarning: (aWarning) => { lWarnings.push(aWarning); }, }); await lCustomPublisher.Open(); await lPublisher.Open(); lPublisher.Publish("myTopicA", "myFirstMessage"); t.is(lSendMock.callCount, 1); t.deepEqual(lSendMock.getCall(0).args[0], ["myTopicA", ZMQPublisher_1.EMessageType.PUBLISH, "0", "myFirstMessage"]); const lFirstRecoveryRequest = [ "myTopicA", 0, 1, ]; const lFirstRecoveryResponse = JSONBigInt_1.default.Parse(await lPublisher["HandleRequest"](JSONBigInt_1.default.Stringify(lFirstRecoveryRequest))); const lFirstExpectedResponse = [ lSendMock.getCall(0).args[0], [ZMQPublisher_1.PUBLISHER_CACHE_EXPIRED], ]; t.deepEqual(lFirstRecoveryResponse, lFirstExpectedResponse); lPublisher.Publish("myTopicA", "mySecondMessage"); // Message 1 & 2 published on timestamp: 0 clock.tick(501); // const EXPIRY_BUFFER: number = 500; lPublisher.Publish("myTopicA", "myThirdMessage"); // Message 3 & 4 published on timestamp: 1 lPublisher.Publish("myTopicA", "myFourthMessage"); // Expire messages 1 & 2 clock.tick(Config_1.default.MaximumLatency * 3); await AsyncTools_1.YieldToEventLoop(); const lSecondRecoveryRequest = [ "myTopicA", 0, 1, 2, 3, ]; const lSecondRecoveryResponse = JSONBigInt_1.default.Parse(await lPublisher["HandleRequest"](JSONBigInt_1.default.Stringify(lSecondRecoveryRequest))); const lSecondExpectedResponse = [ [ZMQPublisher_1.PUBLISHER_CACHE_EXPIRED], [ZMQPublisher_1.PUBLISHER_CACHE_EXPIRED], lSendMock.getCall(3).args[0], lSendMock.getCall(4).args[0], ]; t.deepEqual(lSecondRecoveryResponse, lSecondExpectedResponse); lSendMock.returns(Promise.reject({ code: "EAGAIN", })); // Test HWMWarning clock.tick(100); t.is(lWarnings.length, 0); t.is(lSendMock.callCount, 10); lPublisher.Publish("myTopicA", "myFifthMessage"); await AsyncTools_1.YieldToEventLoop(); t.is(lWarnings.length, 0); t.is(lSendMock.callCount, 11); lCustomPublisher.Publish("myTopicB", "myFirstMessage"); await AsyncTools_1.YieldToEventLoop(); t.is(lWarnings.length, 1); t.is(lSendMock.callCount, 12); t.deepEqual(lWarnings[0], { Topic: "myTopicB", Nonce: 0, Message: "myFirstMessage" }); clock.tick(Config_1.default.HeartBeatInterval - 101); // Trigger old timeout clock.tick(Config_1.default.HeartBeatInterval); // Trigger new timeout await AsyncTools_1.YieldToEventLoop(); t.is(lWarnings.length, 2); t.is(lSendMock.callCount, 14); t.deepEqual(lWarnings[1], { Topic: "myTopicB", Nonce: 0, Message: "" }); lSendMock.returns(Promise.resolve()); clock.tick(Config_1.default.HeartBeatInterval); await AsyncTools_1.YieldToEventLoop(); const lActual = [lSendMock.getCall(12).args[0], lSendMock.getCall(13).args[0]].sort(); const lExpected = [["myTopicA", "HEARTBEAT", "4", ""], ["myTopicB", "HEARTBEAT", "0", ""]]; t.deepEqual(lActual, lExpected); lPublisher.Close(); await AsyncTools_1.YieldToEventLoop(); // Reset Config Config_1.default.SetGlobalConfig(); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWk1RUHVibGlzaGVyLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9UZXN0L1NyYy9aTVFQdWJsaXNoZXIudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFQSw4Q0FBZ0Q7QUFDaEQsNkNBQStCO0FBQy9CLHFEQUEwRDtBQUMxRCw0Q0FBOEI7QUFDOUIsOERBQXNDO0FBRXRDLDRFQUFvRDtBQUNwRCx5REFBOEc7QUFDOUcsbUVBQXFEO0FBRXJELHNEQUF5RDtBQUN6RCx3RUFBaUU7QUFVakUsTUFBTSxJQUFJLEdBQWdDLGFBQXNDLENBQUU7QUFFbEYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQWlDLEVBQVEsRUFBRTtJQUVwRCxjQUFjO0FBQ2xCLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQWlDLEVBQVEsRUFBRTtJQUV4RCxNQUFNLGNBQWMsR0FDZCw0QkFBVSxDQUFDLFNBQVMsQ0FBMEIsV0FBVyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ2hGLE1BQU0sY0FBYyxHQUErQiw0QkFBVSxDQUFDLFNBQVMsQ0FBZ0IsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBRXpHLENBQUMsQ0FBQyxPQUFPLEdBQUc7UUFDUixhQUFhLEVBQUUsY0FBYztRQUM3QixhQUFhLEVBQUUsY0FBYztRQUM3QixRQUFRLEVBQUU7WUFDTjtnQkFDSSxDQUFDLEVBQUUsSUFBSTtnQkFDUCxDQUFDLEVBQUUsR0FBRztnQkFDTixDQUFDLEVBQUUsR0FBRztnQkFDTixDQUFDLEVBQUU7b0JBQ0MsRUFBRTtvQkFDRixVQUFVO2lCQUNiO2FBQ0o7U0FDSjtRQUNELFNBQVMsRUFBRSxxQ0FBZSxDQUFDLGNBQWM7S0FDNUMsQ0FBQztBQUNOLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQWlDLEVBQVEsRUFBRTtJQUV2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