reliable-zeromq
Version:
A collection of reliable zeromq messaging constructs
205 lines • 18.3 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 });
const ava_1 = __importDefault(require("ava"));
const sinon = __importStar(require("sinon"));
const ts_mock_imports_1 = require("ts-mock-imports");
const Delay_1 = require("../../Src/Utils/Delay");
const JSONBigInt_1 = __importDefault(require("../../Src/Utils/JSONBigInt"));
const ZMQPublisher_1 = require("../../Src/ZMQPublisher");
const ZMQRequest_1 = require("../../Src/ZMQRequest");
const ZMQResponse_1 = require("../../Src/ZMQResponse");
const ZMQSubscriber_1 = require("../../Src/ZMQSubscriber/ZMQSubscriber");
const DummyEndpoints_data_1 = require("../Helpers/DummyEndpoints.data");
const test = ava_1.default;
test.before((t) => {
// Unnecessary
});
test.beforeEach((t) => {
t.context = {
ResponderEndpoint: "tcp://127.0.0.1:3241",
TestData: [
{
a: 100n,
b: 20n,
c: 0.5,
d: [
5n,
"myFunc()",
],
},
],
};
});
test.afterEach((t) => {
sinon.restore();
ts_mock_imports_1.ImportMock.restore();
});
test.serial("ZMQRequest: Start, Send, Receive, Close", async (t) => {
const lExpected = {
code: "success",
data: undefined,
};
const lResponse = new ZMQResponse_1.ZMQResponse(t.context.ResponderEndpoint, async (aMsg) => {
let lResult;
try {
lResult = JSONBigInt_1.default.Parse(aMsg);
}
catch (e) {
lResult = aMsg;
}
return JSONBigInt_1.default.Stringify({
code: "success",
data: lResult,
});
});
const lRequester = new ZMQRequest_1.ZMQRequest(t.context.ResponderEndpoint);
const lPromiseResult = await lRequester.Send(JSONBigInt_1.default.Stringify(t.context.TestData));
lExpected.data = t.context.TestData;
if (lPromiseResult.ResponseType === ZMQRequest_1.ERequestResponse.SUCCESS) {
t.deepEqual(JSONBigInt_1.default.Parse(lPromiseResult.Response), lExpected);
}
else {
t.fail(JSONBigInt_1.default.Stringify({
msg: "Request failed",
lPromiseResult,
}));
}
const lNotThrowResult = await lRequester.Send("this should not throw");
lExpected.data = "this should not throw";
if (lNotThrowResult.ResponseType === ZMQRequest_1.ERequestResponse.SUCCESS) {
t.deepEqual(JSONBigInt_1.default.Parse(lNotThrowResult.Response), lExpected);
}
else {
t.fail(JSONBigInt_1.default.Stringify({ msg: "Request failed", lNotThrowResult }));
}
lRequester.Close();
lResponse.Close();
});
test.serial("ZMQResponse: Start, Receive, Close", async (t) => {
let lResponder = async (aMsg) => "world";
const lResponderRouter = (aMsg) => {
return lResponder(aMsg); // Necessary so we can update lResponder throughout
};
t.context.ResponderEndpoint = "tcp://127.0.0.1:4276";
const lResponse = new ZMQResponse_1.ZMQResponse(t.context.ResponderEndpoint, lResponderRouter);
const lRequester = new ZMQRequest_1.ZMQRequest(t.context.ResponderEndpoint);
const lFirstResponse = await lRequester.Send("hello");
t.is(lFirstResponse.Response, "world");
t.is(lResponse["mCachedRequests"].size, 1);
lResponder = async (aMsg) => aMsg + " response";
const lSecondResponse = await lRequester.Send("hello");
t.is(lSecondResponse.Response, "hello response");
t.is(lResponse["mCachedRequests"].size, 2);
lResponse.Close();
lRequester.Close();
});
test.serial("ZMQPublisher & ZMQSubscriber", async (t) => {
const lStatusUpdatePublisher = new ZMQPublisher_1.ZMQPublisher({
PublisherAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress,
RequestAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.RequestAddress,
});
const lWeatherUpdatePublisher = new ZMQPublisher_1.ZMQPublisher({
PublisherAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.PublisherAddress,
RequestAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.RequestAddress,
});
const lSubscriber = new ZMQSubscriber_1.ZMQSubscriber();
await lStatusUpdatePublisher.Open();
await lWeatherUpdatePublisher.Open();
const lTestDataResult = {
[DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress]: {
Publisher: lStatusUpdatePublisher,
Topics: {},
},
[DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.PublisherAddress]: {
Publisher: lWeatherUpdatePublisher,
Topics: {},
},
};
lTestDataResult[DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress].Topics["TopicA"]
= { data: ["myTestMessage"], result: [] };
lTestDataResult[DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress].Topics["TopicB"]
= { data: ["myTestMessage"], result: [] };
lTestDataResult[DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress].Topics["TopicC"]
= { data: ["myTestMessage"], result: [] };
lTestDataResult[DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.PublisherAddress].Topics["Sydney"]
= { data: ["sunny"], result: [] };
lTestDataResult[DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.PublisherAddress].Topics["Newcastle"]
= { data: ["cloudy"], result: [] };
const lSaveResult = (aEndpoint, aTopic, aNonce, aMessage) => {
lTestDataResult[aEndpoint].Topics[aTopic].result[aNonce] = aMessage;
};
const lSubscribe = (aEndpoint, aTopic) => {
lSubscriber.Subscribe(aEndpoint, aTopic, (aMsg) => {
lTestDataResult[aEndpoint.PublisherAddress].Publisher["mMessageCaches"].get(aTopic).forEach((aValue, aKey) => {
if (aValue[ZMQPublisher_1.EPublishMessage.Message] === aMsg) {
lSaveResult(aEndpoint.PublisherAddress, aTopic, aKey, aMsg);
}
});
});
};
lSubscribe({
PublisherAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress,
RequestAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.RequestAddress,
}, "TopicA");
lSubscribe({
PublisherAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress,
RequestAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.RequestAddress,
}, "TopicB");
lSubscribe({
PublisherAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.PublisherAddress,
RequestAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.STATUS_UPDATES.RequestAddress,
}, "TopicC");
lSubscribe({
PublisherAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.PublisherAddress,
RequestAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.RequestAddress,
}, "Newcastle");
lSubscribe({
PublisherAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.PublisherAddress,
RequestAddress: DummyEndpoints_data_1.DUMMY_ENDPOINTS.WEATHER_UPDATES.RequestAddress,
}, "Sydney");
for (const aEndpoint in lTestDataResult) {
const lPublisher = lTestDataResult[aEndpoint].Publisher;
for (const aTopic in lTestDataResult[aEndpoint].Topics) {
for (const aData of lTestDataResult[aEndpoint].Topics[aTopic].data) {
lPublisher.Publish(aTopic, aData);
}
}
}
await Delay_1.Delay(50);
for (const aEndpoint in lTestDataResult) {
for (const aTopic in lTestDataResult[aEndpoint].Topics) {
const lTestData = lTestDataResult[aEndpoint].Topics[aTopic].data;
const lTestResult = lTestDataResult[aEndpoint].Topics[aTopic].result;
for (let i = 0; i < lTestData.length; ++i) {
t.is(lTestData[i], lTestResult[i]);
}
}
}
lSubscriber.Close();
lStatusUpdatePublisher.Close();
lWeatherUpdatePublisher.Close();
});
test.todo("Multiple Subscribers");
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiWk1RQWxsLm5ldHdvcmsuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9UZXN0L05ldHdvcmsvWk1RQWxsLm5ldHdvcmsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsOENBQWdEO0FBQ2hELDZDQUErQjtBQUMvQixxREFBNkM7QUFDN0MsaURBQThDO0FBQzlDLDRFQUFvRDtBQUNwRCx5REFBd0Y7QUFDeEYscURBQTBHO0FBQzFHLHVEQUFvRDtBQUNwRCx5RUFBOEY7QUFDOUYsd0VBQWlFO0FBUWpFLE1BQU0sSUFBSSxHQUFnQyxhQUFzQyxDQUFFO0FBRWxGLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFpQyxFQUFRLEVBQUU7SUFFcEQsY0FBYztBQUNsQixDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFpQyxFQUFRLEVBQUU7SUFFeEQsQ0FBQyxDQUFDLE9BQU8sR0FBRztRQUNSLGlCQUFpQixFQUFFLHNCQUFzQjtRQUN6QyxRQUFRLEVBQUU7WUFDTjtnQkFDSSxDQUFDLEVBQUUsSUFBSTtnQkFDUCxDQUFDLEVBQUUsR0FBRztnQkFDTixDQUFDLEVBQUUsR0FBRztnQkFDTixDQUFDLEVBQUU7b0JBQ0MsRUFBRTtvQkFDRixVQUFVO2lCQUNiO2FBQ0o7U0FDSjtLQUNKLENBQUM7QUFDTixDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFpQyxFQUFRLEVBQUU7SUFFdkQsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2hCLDRCQUFVLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDekIsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsTUFBTSxDQUFDLHlDQUF5QyxFQUFFLEtBQUssRUFBQyxDQUFpQyxFQUFpQixFQUFFO0lBRTdHLE1BQU0sU0FBUyxHQUNmO1FBQ0ksSUFBSSxFQUFFLFNBQVM7UUFD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