UNPKG

reliable-zeromq

Version:

A collection of reliable zeromq messaging constructs

220 lines 22.5 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 }); /* tslint:disable: no-string-literal */ 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 ZMQResponse_1 = require("../../Src/ZMQResponse"); const AsyncTools_1 = require("../Helpers/AsyncTools"); const test = ava_1.default; test.before((t) => { // Unnecessary }); test.beforeEach((t) => { const lResolvers = []; function FakeIterator() { return { async next() { return new Promise((aResolve) => { lResolvers.push(aResolve); }); }, }; } const lMockManager = ts_mock_imports_1.ImportMock.mockClass(zmq, "Router"); // @ts-ignore const lAsyncIteratorMock = lMockManager.mock(Symbol.asyncIterator); lAsyncIteratorMock.callsFake(FakeIterator); t.context = { ResponderEndpoint: "tcp://127.0.0.1:3001", RouterMock: lMockManager, SendToReceiver: (aIndex, aMessage) => { lResolvers[aIndex]({ value: aMessage, done: false }); }, }; }); test.afterEach((t) => { sinon.restore(); ts_mock_imports_1.ImportMock.restore(); }); test.serial("Start, Receive, Close", async (t) => { let lResponder = async (aMsg) => "world"; const lResponderRouter = (aMsg) => { return lResponder(aMsg); // Necessary so we can update lResponder throughout }; const lSendMock = t.context.RouterMock.mock("send", Promise.resolve()); const lBindMock = t.context.RouterMock.mock("bind", Promise.resolve()); const lResponse = new ZMQResponse_1.ZMQResponse(t.context.ResponderEndpoint, lResponderRouter); await AsyncTools_1.YieldToEventLoop(); // Listening to asyncIterator occurs asynchronously, so we need to yield t.is(lResponse.Endpoint, t.context.ResponderEndpoint); t.is(lBindMock.callCount, 1); // Send first message to ZMQResponse t.context.SendToReceiver(0, [ "sender", "unique_sender_id", "0", "hello", ]); await AsyncTools_1.YieldToEventLoop(); let lRouterSendCalls = 0; t.is(lSendMock.callCount, ++lRouterSendCalls); t.is(lResponse["mCachedRequests"].size, 1); t.deepEqual(lSendMock.getCall(lRouterSendCalls - 1).args[0], ["sender", "0", "world"]); lResponder = async (aMsg) => aMsg + " response"; t.context.SendToReceiver(1, [ "sender", "unique_sender_id", "1", "this should not throw", ]); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, ++lRouterSendCalls); t.is(lResponse["mCachedRequests"].size, 2); t.deepEqual(lSendMock.getCall(lRouterSendCalls - 1).args[0], ["sender", "1", "this should not throw response"]); t.context.SendToReceiver(2, [ "sender", "unique_sender_id", "1", "this should not throw", ]); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, ++lRouterSendCalls); t.is(lResponse["mCachedRequests"].size, 2); t.deepEqual(lSendMock.getCall(lRouterSendCalls - 1).args[0], ["sender", "1", "this should not throw response"]); t.context.SendToReceiver(3, [ "sender", "unique_sender_id", "1", "this should not throw", ]); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, ++lRouterSendCalls); t.is(lResponse["mCachedRequests"].size, 2); t.deepEqual(lSendMock.getCall(lRouterSendCalls - 1).args[0], ["sender", "1", "this should not throw response"]); t.context.SendToReceiver(4, [ "sender", "unique_sender_id", "3", "this should not throw", ]); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, ++lRouterSendCalls); t.is(lResponse["mCachedRequests"].size, 3); t.deepEqual(lSendMock.getCall(lRouterSendCalls - 1).args[0], ["sender", "3", "this should not throw response"]); t.context.SendToReceiver(5, [ "sender", "unique_sender_id", "2", "this should not throw", ]); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, ++lRouterSendCalls); t.is(lResponse["mCachedRequests"].size, 4); t.deepEqual(lSendMock.getCall(lRouterSendCalls - 1).args[0], ["sender", "2", "this should not throw response"]); // Test LowestUnseenNonce garbage cleaning t.is(lResponse["mSeenMessages"].get("unique_sender_id").Has(0), true); t.is(lResponse["mSeenMessages"].get("unique_sender_id").Has(1), true); t.is(lResponse["mSeenMessages"].get("unique_sender_id").Has(2), true); t.is(lResponse["mSeenMessages"].get("unique_sender_id").Has(3), true); t.is(lResponse["mSeenMessages"].get("unique_sender_id").Has(4), false); lResponse.Close(); }); test.serial("Errors & Warns", async (t) => { const clock = sinon.useFakeTimers(); let lResponder = (aMsg) => Promise.resolve(aMsg + " RES"); const lResponderRouter = (aMsg) => { return lResponder(aMsg); // Necessary so we can update lResponder throughout }; const lEndpoint = t.context.ResponderEndpoint; const lSendMock = t.context.RouterMock.mock("send", Promise.resolve()); t.context.RouterMock.mock("bind", Promise.resolve()); const lWarnings = []; const lResponse = new ZMQResponse_1.ZMQResponse(lEndpoint, lResponderRouter); const lCustomResponse = new ZMQResponse_1.ZMQResponse(lEndpoint, lResponderRouter, { HighWaterMarkWarning: (aWarning) => { lWarnings.push(aWarning); }, }); await AsyncTools_1.YieldToEventLoop(); // Listening to asyncIterator occurs asynchronously, so we need to yield t.context.SendToReceiver(0, ["sender", "uid", "0", "hello"]); await AsyncTools_1.YieldToEventLoop(); let lCallsToSend = 0; t.deepEqual(lSendMock.getCall(lCallsToSend++).args[0], ["sender", "0", "hello RES"]); clock.tick(3 * Config_1.default.MaximumLatency); t.context.SendToReceiver(2, ["sender", "uid", "0", "hello again"]); await AsyncTools_1.YieldToEventLoop(); t.deepEqual(lSendMock.getCall(lCallsToSend++).args[0], ["sender", "0", "hello RES"]); clock.tick(500); // 500ms is the buffer added on by ExpiryMap t.context.SendToReceiver(3, ["sender", "uid", "0", "hello again"]); await AsyncTools_1.YieldToEventLoop(); t.deepEqual(lSendMock.getCall(lCallsToSend++).args[0], ["sender", "0", ZMQResponse_1.RESPONSE_CACHE_EXPIRED]); lSendMock .onCall(lCallsToSend).returns(Promise.reject({ code: "EAGAIN", })) .onCall(lCallsToSend + 1).returns(Promise.reject({ code: "EAGAIN", })); t.context.SendToReceiver(4, ["sender", "uid", "1", "warning suppress"]); await AsyncTools_1.YieldToEventLoop(); t.context.SendToReceiver(1, ["custom_sender", "uid", "0", "warning handler"]); await AsyncTools_1.YieldToEventLoop(); // UPDATE RESPONDER FOR NEXT STAGE let lCallCount = 0; lResponder = () => { ++lCallCount; return new Promise((aResolve) => { setTimeout(() => aResolve("DELAY DONE"), 50); }); }; t.context.SendToReceiver(5, ["sender", "uid", "0", "this will be another cache error"]); await AsyncTools_1.YieldToEventLoop(); t.deepEqual(lSendMock.getCall(lCallsToSend++).args[0], ["sender", "1", "warning suppress RES"]); t.deepEqual(lSendMock.getCall(lCallsToSend++).args[0], ["custom_sender", "0", "warning handler RES"]); t.deepEqual(lSendMock.getCall(lCallsToSend++).args[0], ["sender", "0", ZMQResponse_1.RESPONSE_CACHE_EXPIRED]); t.is(lWarnings.length, 1); t.deepEqual(lWarnings[0], { Requester: "uid", Nonce: 0, Message: "warning handler RES" }); t.is(lCallCount, 0); t.context.SendToReceiver(7, ["sender", "uid", "2", "START DELAY"]); await AsyncTools_1.YieldToEventLoop(); t.is(lCallCount, 1); t.context.SendToReceiver(8, ["sender", "uid", "2", "START DELAY"]); await AsyncTools_1.YieldToEventLoop(); t.is(lCallCount, 1); t.is(lSendMock.callCount, lCallsToSend); clock.tick(50); await AsyncTools_1.YieldToEventLoop(); t.is(lSendMock.callCount, lCallsToSend + 1); t.deepEqual(lSendMock.getCall(lCallsToSend++).args[0], ["sender", "2", "DELAY DONE"]); lResponse.Close(); lCustomResponse.Close(); t.context.SendToReceiver(9, [undefined, "SUPPRESS THIS"]); await AsyncTools_1.YieldToEventLoop(); t.context.SendToReceiver(9, [undefined, "SUPPRESS THIS"]); await AsyncTools_1.YieldToEventLoop(); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWk1RUmVzcG9uc2UudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL1Rlc3QvU3JjL1pNUVJlc3BvbnNlLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQXVDO0FBQ3ZDLDhDQUFnRDtBQUVoRCw2Q0FBK0I7QUFFL0IscURBQTBEO0FBQzFELDRDQUE4QjtBQUM5Qiw4REFBc0M7QUFFdEMsdURBQTRFO0FBQzVFLHNEQUF5RDtBQVV6RCxNQUFNLElBQUksR0FBZ0MsYUFBc0MsQ0FBRTtBQUVsRixJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBaUMsRUFBUSxFQUFFO0lBRXBELGNBQWM7QUFDbEIsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBaUMsRUFBUSxFQUFFO0lBRXhELE1BQU0sVUFBVSxHQUFrRCxFQUFFLENBQUM7SUFDckUsU0FBUyxZQUFZO1FBRWpCLE9BQU87WUFDSCxLQUFLLENBQUMsSUFBSTtnQkFFTixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsUUFBZ0QsRUFBUSxFQUFFO29CQUUxRSxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUM5QixDQUFDLENBQUMsQ0FBQztZQUNQLENBQUM7U0FDSixDQUFDO0lBQ04sQ0FBQztJQUVELE1BQU0sWUFBWSxHQUE0Qiw0QkFBVSxDQUFDLFNBQVMsQ0FBYSxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDOUYsYUFBYTtJQUNiLE1BQU0sa0JBQWtCLEdBQW9CLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3BGLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUUzQyxDQUFDLENBQUMsT0FBTyxHQUFHO1FBQ1IsaUJBQWlCLEVBQUUsc0JBQXNCO1FBQ3pDLFVBQVUsRUFBRSxZQUFZO1FB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