systemlynx 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/API.md +142 -0
  2. package/LICENSE +21 -0
  3. package/README.md +180 -0
  4. package/index.js +40 -0
  5. package/index.test.js +121 -0
  6. package/package.json +41 -0
  7. package/systemlynx/App/App.js +76 -0
  8. package/systemlynx/App/components/SystemObject.js +9 -0
  9. package/systemlynx/App/components/initializeApp.js +33 -0
  10. package/systemlynx/App/components/loadModules.js +14 -0
  11. package/systemlynx/App/components/loadServices.js +28 -0
  12. package/systemlynx/App/tests/App.test.js +354 -0
  13. package/systemlynx/Client/Client.js +42 -0
  14. package/systemlynx/Client/components/ClientModule.js +28 -0
  15. package/systemlynx/Client/components/ServiceRequestHandler.js +62 -0
  16. package/systemlynx/Client/components/SocketDispatcher.js +20 -0
  17. package/systemlynx/Client/components/loadConnectionData.js +18 -0
  18. package/systemlynx/Client/tests/Client.test.js +208 -0
  19. package/systemlynx/Client/tests/SocketDispatcher.test.js +54 -0
  20. package/systemlynx/Dispatcher/Dispatcher.js +21 -0
  21. package/systemlynx/Dispatcher/Dispatcher.test.js +21 -0
  22. package/systemlynx/HttpClient/HttpClient.js +44 -0
  23. package/systemlynx/HttpClient/HttpClient.test.js +143 -0
  24. package/systemlynx/HttpClient/test.file.json +1 -0
  25. package/systemlynx/HttpClient/test.server.js +34 -0
  26. package/systemlynx/LoadBalancer/LoadBalancer.js +7 -0
  27. package/systemlynx/LoadBalancer/components/CloneManager.js +49 -0
  28. package/systemlynx/LoadBalancer/components/Router.js +37 -0
  29. package/systemlynx/LoadBalancer/tests/LoadBalancer.test.js +142 -0
  30. package/systemlynx/ServerManager/ServerManager.js +113 -0
  31. package/systemlynx/ServerManager/components/Router.js +89 -0
  32. package/systemlynx/ServerManager/components/Server.js +52 -0
  33. package/systemlynx/ServerManager/components/SocketEmitter.js +19 -0
  34. package/systemlynx/ServerManager/components/WebSocketServer.js +7 -0
  35. package/systemlynx/ServerManager/components/parseMethods.js +19 -0
  36. package/systemlynx/ServerManager/tests/ServerManager.test.js +197 -0
  37. package/systemlynx/ServerManager/tests/SocketEmitter.test.js +29 -0
  38. package/systemlynx/Service/Service.js +28 -0
  39. package/systemlynx/Service/Service.test.js +176 -0
  40. package/temp/.gitignore +4 -0
  41. package/utils/ProcessChecker.js +18 -0
@@ -0,0 +1,208 @@
1
+ const { expect } = require("chai");
2
+ const ClientFactory = require("../Client");
3
+ const ServiceFactory = require("../../Service/Service");
4
+ const Service = ServiceFactory();
5
+ const port = 6757;
6
+ const route = "service-test";
7
+ const url = `http://localhost:${port}/${route}`;
8
+
9
+ describe("Client Factory", () => {
10
+ it("should return a SystemLynx Client", () => {
11
+ const Client = ClientFactory();
12
+ expect(Client)
13
+ .to.be.an("object")
14
+ .that.has.property("loadService")
15
+ .that.is.a("function");
16
+ });
17
+ });
18
+ describe("Client", () => {
19
+ it("should be able to use Client.loadService(url, options) to return a promise that resolve into a backend service", async () => {
20
+ Service.ServerModule(
21
+ "orders",
22
+ function () {
23
+ this.action1 = (data) => ({ SERVICE_TEST_PASSED: true, ...data, action1: true });
24
+ this.action2 = (data) => ({ SERVICE_TEST_PASSED: true, ...data, action2: true });
25
+ this.action3 = (data) => ({ SERVICE_TEST_PASSED: true, ...data, action3: true });
26
+ this.noArgTest = () => ({ SERVICE_TEST_PASSED: true, noArgTest: true });
27
+ this.multiArgTest = (arg1, arg2, arg3) => ({
28
+ SERVICE_TEST_PASSED: true,
29
+ multiArgTest: true,
30
+ arg1,
31
+ arg2,
32
+ arg3,
33
+ });
34
+ },
35
+ ["action3"]
36
+ );
37
+
38
+ await Service.startService({ route, port });
39
+ const Client = ClientFactory();
40
+ const buAPI = await Client.loadService(url);
41
+
42
+ expect(buAPI)
43
+ .to.be.an("object")
44
+ .that.has.all.keys("emit", "on", "resetConnection", "disconnect", "orders")
45
+ .that.respondsTo("emit")
46
+ .that.respondsTo("on")
47
+ .that.respondsTo("resetConnection")
48
+ .that.respondsTo("disconnect");
49
+
50
+ expect(buAPI.orders)
51
+ .to.be.an("object")
52
+ .that.has.all.keys(
53
+ "emit",
54
+ "on",
55
+ "disconnect",
56
+ "__setConnection",
57
+ "__connectionData",
58
+ "action1",
59
+ "action2",
60
+ "multiArgTest",
61
+ "noArgTest"
62
+ )
63
+ .that.respondsTo("emit")
64
+ .that.respondsTo("on")
65
+ .that.respondsTo("emit")
66
+ .that.respondsTo("__setConnection")
67
+ .that.respondsTo("__connectionData")
68
+ .that.respondsTo("action1")
69
+ .that.respondsTo("action2")
70
+ .that.respondsTo("multiArgTest")
71
+ .that.respondsTo("noArgTest");
72
+ });
73
+ });
74
+
75
+ describe("Service", () => {
76
+ it("should be able to call methods from the frontend client to the backend ServerModule", async () => {
77
+ const Client = ClientFactory();
78
+ const buAPI = await Client.loadService(url);
79
+
80
+ const results = await buAPI.orders.action1({ code: 3 });
81
+
82
+ const results2 = await buAPI.orders.action2({ code: 11 });
83
+
84
+ expect(results).to.deep.equal({ SERVICE_TEST_PASSED: true, code: 3, action1: true });
85
+ expect(results2).to.deep.equal({
86
+ SERVICE_TEST_PASSED: true,
87
+ code: 11,
88
+ action2: true,
89
+ });
90
+ });
91
+ it("should be able to send multiple arguments to the backend ServerModule", async () => {
92
+ const Client = ClientFactory();
93
+ const buAPI = await Client.loadService(url);
94
+ const arg1 = 4,
95
+ arg2 = 5,
96
+ arg3 = 6;
97
+
98
+ const results = await buAPI.orders.multiArgTest(arg1, arg2, arg3);
99
+
100
+ expect(results).to.deep.equal({
101
+ SERVICE_TEST_PASSED: true,
102
+ multiArgTest: true,
103
+ arg1,
104
+ arg2,
105
+ arg3,
106
+ });
107
+ });
108
+
109
+ it("should be able to send no arguments and use a promise", async () => {
110
+ const Client = ClientFactory();
111
+ const buAPI = await Client.loadService(url);
112
+ const results = await buAPI.orders.noArgTest();
113
+
114
+ expect(results).to.deep.equal({
115
+ SERVICE_TEST_PASSED: true,
116
+ noArgTest: true,
117
+ });
118
+ });
119
+
120
+ it("should be able to receive events emitted from the backend Client", async () => {
121
+ const eventName = "testing";
122
+ const eventTester = Service.ServerModule("eventTester", function () {
123
+ const eventTester = this;
124
+ eventTester.sendEvent = () => eventTester.emit(eventName, { testPassed: true });
125
+ });
126
+
127
+ const Client = ClientFactory();
128
+ const buAPI = await Client.loadService(url);
129
+
130
+ buAPI.eventTester.on(eventName, (data, event) => {
131
+ console.log("Ladies and gentleman... mission accomplish!");
132
+ // console.log(data);
133
+ // console.log(event);
134
+ expect(data).to.deep.equal({ testPassed: true });
135
+ expect(event).to.be.an("object").that.has.all.keys("id", "name", "data", "type");
136
+ expect(event.name).to.equal("testing");
137
+ expect(event.data).to.deep.equal({ testPassed: true });
138
+ expect(event.id).to.be.a("string");
139
+ expect(event.type).to.equal("WebSocket");
140
+ });
141
+
142
+ eventTester.emit(eventName, { testPassed: true });
143
+ });
144
+
145
+ it("should be able to send REST http requests", async () => {
146
+ const Client = ClientFactory();
147
+ const Service = ServiceFactory();
148
+ const route = "rest-tester";
149
+ const port = "8492";
150
+ const url = `http://localhost:${port}/${route}`;
151
+ const useREST = true;
152
+ Service.ServerModule("restTester", function () {
153
+ this.get = (data) => ({ REST_TEST_PASSED: true, getResponse: true, ...data });
154
+ this.put = () => ({ REST_TEST_PASSED: true, putResponse: true });
155
+ this.post = () => ({ REST_TEST_PASSED: true, postResponse: true });
156
+ this.delete = () => ({ REST_TEST_PASSED: true, deleteResponse: true });
157
+ });
158
+
159
+ await Service.startService({ route, port, useREST });
160
+ const buAPI = await Client.loadService(url);
161
+ const getResponse = await buAPI.restTester.get({ name: "GET TEST", id: 12 });
162
+ const putResponse = await buAPI.restTester.put();
163
+ const postResponse = await buAPI.restTester.post();
164
+ const deleteResponse = await buAPI.restTester.delete();
165
+
166
+ expect(getResponse).to.deep.equal({
167
+ REST_TEST_PASSED: true,
168
+ getResponse: true,
169
+ name: "GET TEST",
170
+ id: 12,
171
+ });
172
+ expect(putResponse).to.deep.equal({ REST_TEST_PASSED: true, putResponse: true });
173
+ expect(postResponse).to.deep.equal({ REST_TEST_PASSED: true, postResponse: true });
174
+ expect(deleteResponse).to.deep.equal({
175
+ REST_TEST_PASSED: true,
176
+ deleteResponse: true,
177
+ });
178
+ });
179
+
180
+ it("should be able to use 'useReturnValue' configuration option to enable synchronous return values from ServerModule methods", async () => {
181
+ const service = ServiceFactory();
182
+ const route = "sync/test";
183
+ const port = 4920;
184
+ const host = "localhost";
185
+ const url = `http://localhost:${port}/${route}`;
186
+ service.ServerModule("AsyncMath", function () {
187
+ this.max = Math.max;
188
+ this.min = Math.min;
189
+ this.round = Math.round;
190
+ });
191
+
192
+ await service.startService({
193
+ route,
194
+ port,
195
+ host,
196
+ useReturnValues: true,
197
+ useCallbacks: false,
198
+ });
199
+ const Client = ClientFactory();
200
+ const { AsyncMath } = await Client.loadService(url);
201
+ const results = await AsyncMath.max(10, 2);
202
+ expect(results).to.equal(10);
203
+ const results2 = await AsyncMath.min(10, 2);
204
+ expect(results2).to.equal(2);
205
+ const results3 = await AsyncMath.round(10.2);
206
+ expect(results3).to.equal(10);
207
+ });
208
+ });
@@ -0,0 +1,54 @@
1
+ const { expect } = require("chai");
2
+ const SocketDispatcher = require("../components/SocketDispatcher");
3
+ const { WebSocket, SocketServer } = require("../../ServerManager/components/WebSocketServer")();
4
+
5
+ const namespace = "test-namespace";
6
+ const port = 4592;
7
+ const socket = WebSocket.of(`/${namespace}`);
8
+
9
+ SocketServer.listen(port);
10
+
11
+ describe("SocketDispatcher", () => {
12
+ const eventName = "test-event";
13
+ const dispatcher = SocketDispatcher(`http://localhost:${port}/${namespace}`);
14
+ it("should return an EventDispatcher object with methods on and emit", async () => {
15
+ expect(dispatcher)
16
+ .to.be.an("object")
17
+ .that.has.all.keys("on", "emit", "disconnect")
18
+ .that.respondsTo("on")
19
+ .that.respondsTo("emit")
20
+ .that.respondsTo("disconnect");
21
+ });
22
+ it("Should be able to emit and handle events", (done) => {
23
+ dispatcher.on(eventName, (data) => {
24
+ expect(data).to.deep.equal({ testPassed: true });
25
+ done();
26
+ });
27
+ dispatcher.on("connect", () => console.log(`I'm all the way connected!`));
28
+ setTimeout(() => socket.emit("dispatch", { name: eventName, data: { testPassed: true } }), 500);
29
+ });
30
+ });
31
+
32
+ describe("SocketDispatcher.apply()", () => {
33
+ const eventName = "testing-event";
34
+ const dispatcher = SocketDispatcher.apply({}, [`http://localhost:${port}/${namespace}`]);
35
+ it("should return an EventDispatcher object with methods on and emit", async () => {
36
+ expect(dispatcher)
37
+ .to.be.an("object")
38
+ .that.has.all.keys("on", "emit", "disconnect")
39
+ .that.respondsTo("on")
40
+ .that.respondsTo("emit")
41
+ .that.respondsTo("disconnect");
42
+ });
43
+ it("Should be able to emit and handle events", (done) => {
44
+ dispatcher.on(eventName, (data, event) => {
45
+ expect(data).to.deep.equal({ testPassed: true });
46
+ expect(event).to.deep.equal({ name: "testing-event", data: { testPassed: true } });
47
+ //console.log(event);
48
+ console.log(`I'm all the way connected too!`);
49
+ done();
50
+ });
51
+
52
+ setTimeout(() => socket.emit("dispatch", { name: eventName, data: { testPassed: true } }), 500);
53
+ });
54
+ });
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ module.exports = function SystemLynxDispatcher(events = {}) {
3
+ const Dispatcher = this || {};
4
+
5
+ Dispatcher.emit = (eventName, data, event) => {
6
+ if (events[eventName]) events[eventName].forEach((callback) => callback(data, event));
7
+ return Dispatcher;
8
+ };
9
+
10
+ Dispatcher.on = (eventName, callback) => {
11
+ if (typeof callback !== "function")
12
+ throw Error(
13
+ "SystemLynxDispatcher Error: object.on(eventName, callback) invalid parameters"
14
+ );
15
+ if (!events[eventName]) events[eventName] = [];
16
+ events[eventName].push(callback);
17
+ return Dispatcher;
18
+ };
19
+
20
+ return Dispatcher;
21
+ };
@@ -0,0 +1,21 @@
1
+ const { expect } = require("chai");
2
+ const Dispatcher = require("./Dispatcher");
3
+
4
+ describe("SystemLynxDispatcher", () => {
5
+ const dispatcher = Dispatcher();
6
+ it("should return an EventDispatcher object with methods on and emit", async () => {
7
+ expect(dispatcher)
8
+ .to.be.an("object")
9
+ .that.has.all.keys("on", "emit")
10
+ .that.respondsTo("on")
11
+ .that.respondsTo("emit");
12
+ });
13
+ it("Should be able to emit and handle events", (done) => {
14
+ dispatcher.on("test", (data) => {
15
+ expect(data).to.deep.equal({ testPassed: true });
16
+ done();
17
+ });
18
+
19
+ dispatcher.emit("test", { testPassed: true });
20
+ });
21
+ });
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ const httpClient = require("request");
3
+ const json = true;
4
+
5
+ module.exports = function SystemLynxClient() {
6
+ const Client = this || {};
7
+ Client.request = ({ method, url, body }, cb) => {
8
+ const tryRequest = (callback) => {
9
+ httpClient({ method, url, body, json }, (err, res, body) => {
10
+ if (err) callback(err);
11
+ else if (res.statusCode >= 400) callback(body);
12
+ else callback(null, body, res);
13
+ });
14
+ };
15
+ if (typeof cb === "function") tryRequest(cb);
16
+ else
17
+ return new Promise((resolve, reject) =>
18
+ tryRequest((err, results) => {
19
+ if (err) reject(err);
20
+ else resolve(results);
21
+ })
22
+ );
23
+ };
24
+
25
+ Client.upload = ({ url, formData }, cb) => {
26
+ const tryRequest = (callback) => {
27
+ httpClient.post({ url, formData, json }, (err, res, body) => {
28
+ if (err) callback(err);
29
+ else if (res.statusCode >= 400) callback(body);
30
+ else callback(null, body, res);
31
+ });
32
+ };
33
+ if (typeof cb === "function") tryRequest(cb);
34
+ else
35
+ return new Promise((resolve, reject) =>
36
+ tryRequest((err, results) => {
37
+ if (err) reject(err);
38
+ else resolve(results);
39
+ })
40
+ );
41
+ };
42
+
43
+ return Client;
44
+ };
@@ -0,0 +1,143 @@
1
+ const { expect } = require("chai");
2
+ const fs = require("fs");
3
+ const HttpClientFactory = require("./HttpClient");
4
+ const port = 4789;
5
+ const testServerSetup = require("./test.server");
6
+ //test server setup
7
+
8
+ beforeAll(() => new Promise(resolve => testServerSetup(port, resolve)));
9
+ describe("HttpClientFactory Test", () => {
10
+ const HttpClient = HttpClientFactory();
11
+ const url = `http://localhost:${port}/test`;
12
+ const singleFileUrl = `http://localhost:${port}/sf/test`;
13
+ const multiFileUrl = `http://localhost:${port}/mf/test`;
14
+
15
+ it("should return a HttpClient instance", () => {
16
+ expect(HttpClient)
17
+ .to.be.an("Object")
18
+ .that.has.all.keys("request", "upload")
19
+ .that.respondsTo("request")
20
+ .that.respondsTo("upload");
21
+ });
22
+
23
+ it("should be able to make http requests using a callback", async () => {
24
+ const results = await new Promise((resolve, reject) => {
25
+ HttpClient.request(
26
+ {
27
+ method: "GET",
28
+ url: "http://localhost:4789/test",
29
+ body: { getWithCallback: true }
30
+ },
31
+ (err, results) => {
32
+ if (err) reject(err);
33
+ else resolve(results);
34
+ }
35
+ );
36
+ });
37
+
38
+ expect(results)
39
+ .to.be.an("Object")
40
+ .that.deep.equal({
41
+ getWithCallback: true,
42
+ testPassed: true,
43
+ method: "GET"
44
+ });
45
+ });
46
+
47
+ it("should be able to make http requests using a promise", async () => {
48
+ const results = await HttpClient.request({
49
+ method: "GET",
50
+ url,
51
+ body: { getWithPromise: true }
52
+ });
53
+
54
+ expect(results)
55
+ .to.be.an("Object")
56
+ .that.deep.equal({
57
+ getWithPromise: true,
58
+ testPassed: true,
59
+ method: "GET"
60
+ });
61
+ });
62
+
63
+ it("should be able to make PUT requests", async () => {
64
+ const results = await HttpClient.request({
65
+ method: "GET",
66
+ url,
67
+ body: { getWithPromise: true }
68
+ });
69
+
70
+ expect(results)
71
+ .to.be.an("Object")
72
+ .that.deep.equal({
73
+ getWithPromise: true,
74
+ testPassed: true,
75
+ method: "GET"
76
+ });
77
+ });
78
+
79
+ it("should be able to make POST requests", async () => {
80
+ const results = await HttpClient.request({
81
+ method: "POST",
82
+ url,
83
+ body: { test: true }
84
+ });
85
+
86
+ expect(results)
87
+ .to.be.an("Object")
88
+ .that.deep.equal({
89
+ test: true,
90
+ testPassed: true,
91
+ method: "POST"
92
+ });
93
+ });
94
+ it("should be able to make DELETE requests", async () => {
95
+ const results = await HttpClient.request({
96
+ method: "DELETE",
97
+ url,
98
+ body: { test: true }
99
+ });
100
+
101
+ expect(results)
102
+ .to.be.an("Object")
103
+ .that.deep.equal({
104
+ test: true,
105
+ testPassed: true,
106
+ method: "DELETE"
107
+ });
108
+ });
109
+
110
+ it("should be able to upload a file", async () => {
111
+ const file = fs.createReadStream(__dirname + "/test.file.json");
112
+ const results = await HttpClient.upload({
113
+ url: singleFileUrl,
114
+ formData: { file }
115
+ });
116
+
117
+ expect(results)
118
+ .to.be.an("Object")
119
+ .that.has.property("testPassed", true);
120
+ expect(results)
121
+ .to.have.property("file")
122
+ .that.is.an("Object")
123
+ .that.has.property("originalname", "test.file.json");
124
+ });
125
+
126
+ it("should be able to upload multiple files", async () => {
127
+ const files = [
128
+ fs.createReadStream(__dirname + "/test.file.json"),
129
+ fs.createReadStream(__dirname + "/test.file.json")
130
+ ];
131
+ const multiUploadResponse = await HttpClient.upload({
132
+ url: multiFileUrl,
133
+ formData: { files }
134
+ });
135
+ expect(multiUploadResponse)
136
+ .to.be.an("Object")
137
+ .that.has.property("testPassed", true);
138
+ expect(multiUploadResponse)
139
+ .to.have.property("files")
140
+ .that.is.an("Array");
141
+ expect(multiUploadResponse).to.have.property("fileUploadTest", true);
142
+ });
143
+ });
@@ -0,0 +1 @@
1
+ { "testPassed": true, "fileUploadTest": true }
@@ -0,0 +1,34 @@
1
+ module.exports = TestServerSetup = (port, done) => {
2
+ const fs = require("fs");
3
+ const server = require("../ServerManager/components/Server")();
4
+
5
+ const response = (req, res) => {
6
+ const { body, method } = req;
7
+ body.testPassed = true;
8
+ res.json({ method, ...body });
9
+ };
10
+
11
+ const uploadResponse = (req, res) => {
12
+ const { file } = req;
13
+ const json = JSON.parse(fs.readFileSync(file.path));
14
+
15
+ res.json({ file, ...json });
16
+ };
17
+
18
+ const multiUploadResponse = (req, res) => {
19
+ const { files } = req;
20
+ const json = JSON.parse(fs.readFileSync(files[0].path));
21
+
22
+ res.json({ files, ...json });
23
+ };
24
+
25
+ server.get("/test", response);
26
+ server.put("/test", response);
27
+ server.post("/test", response);
28
+ server.delete("/test", response);
29
+ server.post("/sf/test", uploadResponse);
30
+ server.post("/mf/test", multiUploadResponse);
31
+ server.listen(port, console.log(`(TestServer) listening on port:${port}`), done);
32
+
33
+ return server;
34
+ };
@@ -0,0 +1,7 @@
1
+ const Service = require("../Service/Service");
2
+ const CloneManager = require("./components/CloneManager");
3
+ module.exports = function LoadBalancer() {
4
+ const LoadBalancer = Service();
5
+ const clones = LoadBalancer.ServerModule("clones", CloneManager);
6
+ return { ...LoadBalancer, clones };
7
+ };
@@ -0,0 +1,49 @@
1
+ const Router = require("./Router");
2
+ module.exports = function Clones(server) {
3
+ const Clones = this;
4
+ const cloneRouter = Router.apply(Clones, [server]);
5
+ const handledEvents = [];
6
+ Clones.clones = [];
7
+
8
+ Clones.register = ({ port, host, route }, cb) => {
9
+ if (!(port && route && host))
10
+ return cb({
11
+ message: "route port and host are required options",
12
+ status: 400,
13
+ });
14
+
15
+ route = route.charAt(0) === "/" ? route : "/" + route;
16
+ const url = `http://${host}:${port}${route}`;
17
+ let service = Clones.clones.find((service) => service.route === route);
18
+
19
+ if (service) {
20
+ if (service.locations.indexOf(url) === -1) {
21
+ service.locations.push(url);
22
+ Clones.emit("new_clone", { url, service });
23
+ cb(null, { message: "New clone locations registered", service });
24
+ }
25
+ } else {
26
+ service = { route, locations: [url] };
27
+ cloneRouter.addService(service);
28
+ Clones.clones.push(service);
29
+ Clones.emit("new_service", { url, service });
30
+ Clones.emit("new_clone", { url, service });
31
+ cb(null, { url, service });
32
+ }
33
+ };
34
+
35
+ Clones.dispatch = ({ name, data }, cb) => {
36
+ Clones.emit(name, data);
37
+ cb();
38
+ };
39
+
40
+ Clones.assignDispatch = (event, cb) => {
41
+ const e = handledEvents.find((e) => e.id === event.id);
42
+ if (!e) {
43
+ handledEvents.push(event);
44
+ cb(null, event);
45
+ } else cb({ message: "Event already handle", status: 403 });
46
+
47
+ if (handledEvents.length > 50) handledEvents.splice(20);
48
+ };
49
+ };
@@ -0,0 +1,37 @@
1
+ const HttpClient = require("../../HttpClient/HttpClient")();
2
+
3
+ module.exports = function Router(server) {
4
+ const CloneManager = this;
5
+
6
+ const addService = ({ route, locations }) => {
7
+ server.get(route, recursiveGetService);
8
+
9
+ let location_index = -1;
10
+ function recursiveGetService(req, res) {
11
+ if (locations.length === 0)
12
+ return res.status(404).json({
13
+ message: `No services found on requested route: ${route}`,
14
+ locations
15
+ });
16
+
17
+ location_index++;
18
+ location_index = location_index < locations.length ? location_index : 0;
19
+ const url = locations[location_index];
20
+
21
+ HttpClient.request({ url }, (err, connData) => {
22
+ if (err) {
23
+ for (i = 0; i < locations.length; i++) {
24
+ if (locations[i] === url) {
25
+ locations.splice(i, 1);
26
+ console.warn(`(LoadBalancer): Removing (${url}) URL from ${route} Service`);
27
+ CloneManager.emit("location_removed", { url, route, locations });
28
+ }
29
+ }
30
+ recursiveGetService(req, res);
31
+ } else res.json(connData);
32
+ });
33
+ }
34
+ };
35
+
36
+ return { addService };
37
+ };