systemlynx 1.5.0 → 1.7.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.
- package/API.md +67 -8
- package/README.md +8 -8
- package/index.test.js +3 -8
- package/package.json +3 -3
- package/systemlynx/App/App.js +23 -24
- package/systemlynx/App/components/initializeApp.js +4 -4
- package/systemlynx/App/components/loadModules.js +6 -6
- package/systemlynx/App/components/loadServices.js +9 -6
- package/systemlynx/App/tests/App.test.js +123 -26
- package/systemlynx/Client/Client.js +31 -10
- package/systemlynx/Client/components/ClientModule.js +15 -5
- package/systemlynx/Client/components/ServiceRequestHandler.js +8 -2
- package/systemlynx/Client/components/SocketDispatcher.js +2 -2
- package/systemlynx/Client/components/loadConnectionData.js +3 -1
- package/systemlynx/Client/tests/Client.test.js +34 -31
- package/systemlynx/Dispatcher/Dispatcher.js +14 -7
- package/systemlynx/HttpClient/HttpClient.test.js +40 -56
- package/systemlynx/LoadBalancer/tests/LoadBalancer.test.js +17 -15
- package/systemlynx/ServerManager/ServerManager.js +30 -16
- package/systemlynx/ServerManager/components/Router.js +8 -8
- package/systemlynx/ServerManager/components/SocketEmitter.js +3 -2
- package/systemlynx/Service/Service.js +19 -12
- package/systemlynx/Service/Service.test.js +10 -8
- package/systemlynx/utils/System.js +7 -0
- package/systemlynx/utils/SystemContext.js +10 -0
- package/systemlynx/App/components/SystemObject.js +0 -9
|
@@ -3,7 +3,7 @@ const loadConnectionData = require("./components/loadConnectionData");
|
|
|
3
3
|
const SocketDispatcher = require("./components/SocketDispatcher");
|
|
4
4
|
const ClientModule = require("./components/ClientModule");
|
|
5
5
|
|
|
6
|
-
module.exports = function SystemLynxClient() {
|
|
6
|
+
module.exports = function SystemLynxClient(systemContext) {
|
|
7
7
|
const Client = {};
|
|
8
8
|
Client.loadedServices = {};
|
|
9
9
|
|
|
@@ -12,29 +12,50 @@ module.exports = function SystemLynxClient() {
|
|
|
12
12
|
return Client.loadedServices[url];
|
|
13
13
|
|
|
14
14
|
const connData = await loadConnectionData(url, options);
|
|
15
|
-
const Service =
|
|
15
|
+
const Service = Client.createService(connData);
|
|
16
16
|
Client.loadedServices[url] = Service;
|
|
17
|
-
|
|
17
|
+
await new Promise((resolve) => Service.on("connect", resolve));
|
|
18
|
+
return Service;
|
|
19
|
+
};
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
Client.createService = (connData) => {
|
|
22
|
+
const events = {};
|
|
23
|
+
if (Client.loadedServices[connData.serviceUrl])
|
|
24
|
+
return Client.loadedServices[connData.serviceUrl];
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
const Service = SocketDispatcher(connData.namespace, events, systemContext);
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
Client.loadedServices[connData.serviceUrl] = Service;
|
|
29
|
+
|
|
30
|
+
Service.resetConnection = async (cb) => {
|
|
31
|
+
const { modules, host, port, namespace } = await loadConnectionData(
|
|
32
|
+
connData.serviceUrl
|
|
26
33
|
);
|
|
34
|
+
SocketDispatcher.apply(Service, [namespace, events, systemContext]);
|
|
27
35
|
|
|
36
|
+
modules.forEach(({ namespace, route, name }) => {
|
|
37
|
+
if (Service[name]) {
|
|
38
|
+
Service[name].__setConnection(host, port, route, namespace);
|
|
39
|
+
Service[name].emit("reconnect");
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
Service.emit("reconnect");
|
|
28
44
|
if (typeof cb === "function") cb();
|
|
29
45
|
};
|
|
30
46
|
|
|
31
47
|
connData.modules.forEach(
|
|
32
|
-
(mod) =>
|
|
48
|
+
(mod) =>
|
|
49
|
+
(Service[mod.name] = ClientModule(
|
|
50
|
+
mod,
|
|
51
|
+
connData,
|
|
52
|
+
Service.resetConnection,
|
|
53
|
+
systemContext
|
|
54
|
+
))
|
|
33
55
|
);
|
|
34
56
|
|
|
35
57
|
Service.on("disconnect", Service.resetConnection);
|
|
36
58
|
|
|
37
|
-
await new Promise((resolve) => Service.on("connect", resolve));
|
|
38
59
|
return Service;
|
|
39
60
|
};
|
|
40
61
|
|
|
@@ -2,25 +2,35 @@
|
|
|
2
2
|
const ServiceRequestHandler = require("./ServiceRequestHandler");
|
|
3
3
|
const SocketDispatcher = require("./SocketDispatcher");
|
|
4
4
|
module.exports = function SystemLynxClientModule(
|
|
5
|
-
{ methods, namespace, route },
|
|
5
|
+
{ methods, namespace, route, connectionData, name },
|
|
6
6
|
{ port, host },
|
|
7
|
-
|
|
7
|
+
reconnectService,
|
|
8
|
+
systemContext
|
|
8
9
|
) {
|
|
9
10
|
const events = {};
|
|
10
11
|
const ClientModule = this || {};
|
|
11
12
|
|
|
12
13
|
ClientModule.__setConnection = (host, port, route, namespace) => {
|
|
13
14
|
ClientModule.__connectionData = () => ({ route, host, port });
|
|
14
|
-
SocketDispatcher.apply(ClientModule, [namespace, events]);
|
|
15
|
+
SocketDispatcher.apply(ClientModule, [namespace, events, systemContext]);
|
|
15
16
|
};
|
|
16
|
-
|
|
17
17
|
ClientModule.__setConnection(host, port, route, namespace);
|
|
18
18
|
|
|
19
|
+
const reconnectModule = async (cb) => {
|
|
20
|
+
const url = connectionData.serviceUrl + `?modules=${name}`;
|
|
21
|
+
const { modules, port, host } = await loadConnectionData(url);
|
|
22
|
+
const { namespace, route } = modules[0];
|
|
23
|
+
ClientModule.__setConnection(host, port, route, namespace);
|
|
24
|
+
|
|
25
|
+
if (typeof cb === "function") cb();
|
|
26
|
+
};
|
|
27
|
+
|
|
19
28
|
methods.forEach(({ method, fn }) => {
|
|
20
29
|
ClientModule[fn] = ServiceRequestHandler.apply(ClientModule, [
|
|
21
30
|
method,
|
|
22
31
|
fn,
|
|
23
|
-
|
|
32
|
+
reconnectService,
|
|
33
|
+
connectionData && reconnectModule,
|
|
24
34
|
]);
|
|
25
35
|
});
|
|
26
36
|
|
|
@@ -8,7 +8,12 @@ const makeQuery = (data) =>
|
|
|
8
8
|
(query, name) => (query += `${name}=${data[name]}&`),
|
|
9
9
|
"?"
|
|
10
10
|
);
|
|
11
|
-
module.exports = function ServiceRequestHandler(
|
|
11
|
+
module.exports = function ServiceRequestHandler(
|
|
12
|
+
method,
|
|
13
|
+
fn,
|
|
14
|
+
reconnectService,
|
|
15
|
+
reconnectModule
|
|
16
|
+
) {
|
|
12
17
|
const ClientModule = this;
|
|
13
18
|
|
|
14
19
|
return function sendRequest() {
|
|
@@ -48,7 +53,8 @@ module.exports = function ServiceRequestHandler(method, fn, resetConnection) {
|
|
|
48
53
|
} else if (errCount <= 3) {
|
|
49
54
|
console.log(err);
|
|
50
55
|
errCount++;
|
|
51
|
-
|
|
56
|
+
if (reconnectModule) reconnectModule(() => tryRequest(cb, errCount));
|
|
57
|
+
else reconnectService(() => tryRequest(cb, errCount));
|
|
52
58
|
} else throw Error(`[SystemLynx][Service][Error]: Invalid route:${err}`);
|
|
53
59
|
};
|
|
54
60
|
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
const io = require("socket.io-client");
|
|
3
3
|
const SystemLynxDispatcher = require("../../Dispatcher/Dispatcher");
|
|
4
4
|
|
|
5
|
-
module.exports = function SocketDispatcher(namespace, events = {}) {
|
|
5
|
+
module.exports = function SocketDispatcher(namespace, events = {}, systemContext) {
|
|
6
6
|
const dispatcher =
|
|
7
7
|
(this || {}).on && (this || {}).emit
|
|
8
8
|
? this
|
|
9
|
-
: SystemLynxDispatcher.apply(this, [events]);
|
|
9
|
+
: SystemLynxDispatcher.apply(this, [events, systemContext]);
|
|
10
10
|
const socket = io.connect(namespace);
|
|
11
11
|
socket.on("dispatch", (event) => dispatcher.emit(event.name, event.data, event));
|
|
12
12
|
socket.on("disconnect", () => {
|
|
@@ -11,7 +11,9 @@ module.exports = function loadConnectionData(url, { limit = 10, wait = 150 } = {
|
|
|
11
11
|
if (errors.length < limit)
|
|
12
12
|
setTimeout(() => getData(resolve), errors.length * wait);
|
|
13
13
|
else
|
|
14
|
-
|
|
14
|
+
console.error(
|
|
15
|
+
`[SystemLynx][Client][Error]: Failed to load Service @${url} after ${errors.length} attempts.`
|
|
16
|
+
);
|
|
15
17
|
} else resolve(results);
|
|
16
18
|
});
|
|
17
19
|
});
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const { expect } = require("chai");
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const Service =
|
|
2
|
+
const SystemLynxClient = require("../Client");
|
|
3
|
+
const SystemLynxService = require("../../Service/Service");
|
|
4
|
+
const Service = SystemLynxService();
|
|
5
5
|
const port = 6757;
|
|
6
6
|
const route = "service-test";
|
|
7
7
|
const url = `http://localhost:${port}/${route}`;
|
|
8
8
|
|
|
9
|
-
describe("
|
|
9
|
+
describe("SystemLynxClient()", () => {
|
|
10
10
|
it("should return a SystemLynx Client", () => {
|
|
11
|
-
const Client =
|
|
11
|
+
const Client = SystemLynxClient();
|
|
12
12
|
expect(Client)
|
|
13
13
|
.to.be.an("object")
|
|
14
14
|
.that.has.property("loadService")
|
|
@@ -36,7 +36,7 @@ describe("Client", () => {
|
|
|
36
36
|
);
|
|
37
37
|
|
|
38
38
|
await Service.startService({ route, port });
|
|
39
|
-
const Client =
|
|
39
|
+
const Client = SystemLynxClient();
|
|
40
40
|
const buAPI = await Client.loadService(url);
|
|
41
41
|
|
|
42
42
|
expect(buAPI)
|
|
@@ -74,7 +74,7 @@ describe("Client", () => {
|
|
|
74
74
|
|
|
75
75
|
describe("Service", () => {
|
|
76
76
|
it("should be able to call methods from the frontend client to the backend Module", async () => {
|
|
77
|
-
const Client =
|
|
77
|
+
const Client = SystemLynxClient();
|
|
78
78
|
const buAPI = await Client.loadService(url);
|
|
79
79
|
|
|
80
80
|
const results = await buAPI.orders.action1({ code: 3 });
|
|
@@ -89,7 +89,7 @@ describe("Service", () => {
|
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
91
|
it("should be able to send multiple arguments to the backend Module", async () => {
|
|
92
|
-
const Client =
|
|
92
|
+
const Client = SystemLynxClient();
|
|
93
93
|
const buAPI = await Client.loadService(url);
|
|
94
94
|
const arg1 = 4,
|
|
95
95
|
arg2 = 5,
|
|
@@ -107,7 +107,7 @@ describe("Service", () => {
|
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
it("should be able to send no arguments and use a promise", async () => {
|
|
110
|
-
const Client =
|
|
110
|
+
const Client = SystemLynxClient();
|
|
111
111
|
const buAPI = await Client.loadService(url);
|
|
112
112
|
const results = await buAPI.orders.noArgTest();
|
|
113
113
|
|
|
@@ -119,32 +119,37 @@ describe("Service", () => {
|
|
|
119
119
|
|
|
120
120
|
it("should be able to receive events emitted from the backend Client", async () => {
|
|
121
121
|
const eventName = "testing";
|
|
122
|
+
const route = "test-service";
|
|
123
|
+
const port = "8980";
|
|
124
|
+
const url = `http://localhost:${port}/${route}`;
|
|
125
|
+
const Service = SystemLynxService();
|
|
122
126
|
const eventTester = Service.module("eventTester", function () {
|
|
123
|
-
|
|
124
|
-
eventTester.sendEvent = () => eventTester.emit(eventName, { testPassed: true });
|
|
127
|
+
this.sendEvent = () => this.emit(eventName, { testPassed: true });
|
|
125
128
|
});
|
|
129
|
+
await Service.startService({ route, port });
|
|
126
130
|
|
|
127
|
-
const Client =
|
|
128
|
-
const buAPI = await Client.loadService(url);
|
|
131
|
+
const Client = SystemLynxClient();
|
|
129
132
|
|
|
130
|
-
buAPI.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
const buAPI = await Client.loadService(url);
|
|
134
|
+
setTimeout(() => eventTester.emit(eventName, { testPassed: true }), 500);
|
|
135
|
+
|
|
136
|
+
await new Promise((resolve) => {
|
|
137
|
+
buAPI.eventTester.on(eventName, (data, event) => {
|
|
138
|
+
console.log("Ladies and gentleman... mission accomplish!");
|
|
139
|
+
expect(data).to.deep.equal({ testPassed: true });
|
|
140
|
+
expect(event).to.be.an("object").that.has.all.keys("id", "name", "data", "type");
|
|
141
|
+
expect(event.name).to.equal(eventName);
|
|
142
|
+
expect(event.data).to.deep.equal({ testPassed: true });
|
|
143
|
+
expect(event.id).to.be.a("string");
|
|
144
|
+
expect(event.type).to.equal("WebSocket");
|
|
145
|
+
resolve();
|
|
146
|
+
});
|
|
140
147
|
});
|
|
141
|
-
|
|
142
|
-
eventTester.emit(eventName, { testPassed: true });
|
|
143
148
|
});
|
|
144
149
|
|
|
145
150
|
it("should be able to send REST http requests", async () => {
|
|
146
|
-
const Client =
|
|
147
|
-
const Service =
|
|
151
|
+
const Client = SystemLynxClient();
|
|
152
|
+
const Service = SystemLynxService();
|
|
148
153
|
const route = "rest-tester";
|
|
149
154
|
const port = "8492";
|
|
150
155
|
const url = `http://localhost:${port}/${route}`;
|
|
@@ -178,7 +183,7 @@ describe("Service", () => {
|
|
|
178
183
|
});
|
|
179
184
|
|
|
180
185
|
it("should be able to use 'useReturnValue' configuration option to enable synchronous return values from Module methods", async () => {
|
|
181
|
-
const service =
|
|
186
|
+
const service = SystemLynxService();
|
|
182
187
|
const route = "sync/test";
|
|
183
188
|
const port = 4920;
|
|
184
189
|
const host = "localhost";
|
|
@@ -193,10 +198,8 @@ describe("Service", () => {
|
|
|
193
198
|
route,
|
|
194
199
|
port,
|
|
195
200
|
host,
|
|
196
|
-
useReturnValues: true,
|
|
197
|
-
useCallbacks: false,
|
|
198
201
|
});
|
|
199
|
-
const Client =
|
|
202
|
+
const Client = SystemLynxClient();
|
|
200
203
|
const { AsyncMath } = await Client.loadService(url);
|
|
201
204
|
const results = await AsyncMath.max(10, 2);
|
|
202
205
|
expect(results).to.equal(10);
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
module.exports = function SystemLynxDispatcher(events = {}) {
|
|
2
|
+
module.exports = function SystemLynxDispatcher(events = {}, systemContext) {
|
|
3
3
|
const Dispatcher = this || {};
|
|
4
4
|
|
|
5
5
|
Dispatcher.emit = (eventName, data, event) => {
|
|
6
|
-
if (events[eventName])
|
|
6
|
+
if (events[eventName])
|
|
7
|
+
events[eventName].forEach((callback) =>
|
|
8
|
+
callback.apply(systemContext, [data, event])
|
|
9
|
+
);
|
|
7
10
|
return Dispatcher;
|
|
8
11
|
};
|
|
9
12
|
|
|
10
13
|
Dispatcher.on = (eventName, callback) => {
|
|
11
|
-
if (typeof callback !== "function")
|
|
12
|
-
|
|
13
|
-
"[SystemLynx][EventHandler][Error]: EventHandler.on(eventName, callback) received invalid parameters"
|
|
14
|
-
);
|
|
14
|
+
if (typeof callback !== "function") return Dispatcher;
|
|
15
|
+
|
|
15
16
|
if (!events[eventName]) events[eventName] = [];
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
if (callback.name) {
|
|
19
|
+
//if the function has a name and it already present don't add it
|
|
20
|
+
const i = events[eventName].findIndex((fn) => fn.name === callback.name);
|
|
21
|
+
if (i === -1) events[eventName].push(callback);
|
|
22
|
+
else events[eventName][i] = callback;
|
|
23
|
+
} else events[eventName].push(callback);
|
|
17
24
|
return Dispatcher;
|
|
18
25
|
};
|
|
19
26
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const { expect } = require("chai");
|
|
2
2
|
const fs = require("fs");
|
|
3
|
-
const
|
|
3
|
+
const HttpSystemLynxClient = require("./HttpClient");
|
|
4
4
|
const port = 4789;
|
|
5
5
|
const testServerSetup = require("./test.server");
|
|
6
6
|
//test server setup
|
|
7
7
|
|
|
8
|
-
beforeAll(() => new Promise(resolve => testServerSetup(port, resolve)));
|
|
9
|
-
describe("
|
|
10
|
-
const HttpClient =
|
|
8
|
+
beforeAll(() => new Promise((resolve) => testServerSetup(port, resolve)));
|
|
9
|
+
describe("HttpSystemLynxClient Test", () => {
|
|
10
|
+
const HttpClient = HttpSystemLynxClient();
|
|
11
11
|
const url = `http://localhost:${port}/test`;
|
|
12
12
|
const singleFileUrl = `http://localhost:${port}/sf/test`;
|
|
13
13
|
const multiFileUrl = `http://localhost:${port}/mf/test`;
|
|
@@ -26,7 +26,7 @@ describe("HttpClientFactory Test", () => {
|
|
|
26
26
|
{
|
|
27
27
|
method: "GET",
|
|
28
28
|
url: "http://localhost:4789/test",
|
|
29
|
-
body: { getWithCallback: true }
|
|
29
|
+
body: { getWithCallback: true },
|
|
30
30
|
},
|
|
31
31
|
(err, results) => {
|
|
32
32
|
if (err) reject(err);
|
|
@@ -35,88 +35,76 @@ describe("HttpClientFactory Test", () => {
|
|
|
35
35
|
);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
expect(results)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
method: "GET"
|
|
44
|
-
});
|
|
38
|
+
expect(results).to.be.an("Object").that.deep.equal({
|
|
39
|
+
getWithCallback: true,
|
|
40
|
+
testPassed: true,
|
|
41
|
+
method: "GET",
|
|
42
|
+
});
|
|
45
43
|
});
|
|
46
44
|
|
|
47
45
|
it("should be able to make http requests using a promise", async () => {
|
|
48
46
|
const results = await HttpClient.request({
|
|
49
47
|
method: "GET",
|
|
50
48
|
url,
|
|
51
|
-
body: { getWithPromise: true }
|
|
49
|
+
body: { getWithPromise: true },
|
|
52
50
|
});
|
|
53
51
|
|
|
54
|
-
expect(results)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
method: "GET"
|
|
60
|
-
});
|
|
52
|
+
expect(results).to.be.an("Object").that.deep.equal({
|
|
53
|
+
getWithPromise: true,
|
|
54
|
+
testPassed: true,
|
|
55
|
+
method: "GET",
|
|
56
|
+
});
|
|
61
57
|
});
|
|
62
58
|
|
|
63
59
|
it("should be able to make PUT requests", async () => {
|
|
64
60
|
const results = await HttpClient.request({
|
|
65
61
|
method: "GET",
|
|
66
62
|
url,
|
|
67
|
-
body: { getWithPromise: true }
|
|
63
|
+
body: { getWithPromise: true },
|
|
68
64
|
});
|
|
69
65
|
|
|
70
|
-
expect(results)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
method: "GET"
|
|
76
|
-
});
|
|
66
|
+
expect(results).to.be.an("Object").that.deep.equal({
|
|
67
|
+
getWithPromise: true,
|
|
68
|
+
testPassed: true,
|
|
69
|
+
method: "GET",
|
|
70
|
+
});
|
|
77
71
|
});
|
|
78
72
|
|
|
79
73
|
it("should be able to make POST requests", async () => {
|
|
80
74
|
const results = await HttpClient.request({
|
|
81
75
|
method: "POST",
|
|
82
76
|
url,
|
|
83
|
-
body: { test: true }
|
|
77
|
+
body: { test: true },
|
|
84
78
|
});
|
|
85
79
|
|
|
86
|
-
expect(results)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
method: "POST"
|
|
92
|
-
});
|
|
80
|
+
expect(results).to.be.an("Object").that.deep.equal({
|
|
81
|
+
test: true,
|
|
82
|
+
testPassed: true,
|
|
83
|
+
method: "POST",
|
|
84
|
+
});
|
|
93
85
|
});
|
|
94
86
|
it("should be able to make DELETE requests", async () => {
|
|
95
87
|
const results = await HttpClient.request({
|
|
96
88
|
method: "DELETE",
|
|
97
89
|
url,
|
|
98
|
-
body: { test: true }
|
|
90
|
+
body: { test: true },
|
|
99
91
|
});
|
|
100
92
|
|
|
101
|
-
expect(results)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
method: "DELETE"
|
|
107
|
-
});
|
|
93
|
+
expect(results).to.be.an("Object").that.deep.equal({
|
|
94
|
+
test: true,
|
|
95
|
+
testPassed: true,
|
|
96
|
+
method: "DELETE",
|
|
97
|
+
});
|
|
108
98
|
});
|
|
109
99
|
|
|
110
100
|
it("should be able to upload a file", async () => {
|
|
111
101
|
const file = fs.createReadStream(__dirname + "/test.file.json");
|
|
112
102
|
const results = await HttpClient.upload({
|
|
113
103
|
url: singleFileUrl,
|
|
114
|
-
formData: { file }
|
|
104
|
+
formData: { file },
|
|
115
105
|
});
|
|
116
106
|
|
|
117
|
-
expect(results)
|
|
118
|
-
.to.be.an("Object")
|
|
119
|
-
.that.has.property("testPassed", true);
|
|
107
|
+
expect(results).to.be.an("Object").that.has.property("testPassed", true);
|
|
120
108
|
expect(results)
|
|
121
109
|
.to.have.property("file")
|
|
122
110
|
.that.is.an("Object")
|
|
@@ -126,18 +114,14 @@ describe("HttpClientFactory Test", () => {
|
|
|
126
114
|
it("should be able to upload multiple files", async () => {
|
|
127
115
|
const files = [
|
|
128
116
|
fs.createReadStream(__dirname + "/test.file.json"),
|
|
129
|
-
fs.createReadStream(__dirname + "/test.file.json")
|
|
117
|
+
fs.createReadStream(__dirname + "/test.file.json"),
|
|
130
118
|
];
|
|
131
119
|
const multiUploadResponse = await HttpClient.upload({
|
|
132
120
|
url: multiFileUrl,
|
|
133
|
-
formData: { files }
|
|
121
|
+
formData: { files },
|
|
134
122
|
});
|
|
135
|
-
expect(multiUploadResponse)
|
|
136
|
-
|
|
137
|
-
.that.has.property("testPassed", true);
|
|
138
|
-
expect(multiUploadResponse)
|
|
139
|
-
.to.have.property("files")
|
|
140
|
-
.that.is.an("Array");
|
|
123
|
+
expect(multiUploadResponse).to.be.an("Object").that.has.property("testPassed", true);
|
|
124
|
+
expect(multiUploadResponse).to.have.property("files").that.is.an("Array");
|
|
141
125
|
expect(multiUploadResponse).to.have.property("fileUploadTest", true);
|
|
142
126
|
});
|
|
143
127
|
});
|
|
@@ -1,22 +1,15 @@
|
|
|
1
1
|
const { expect } = require("chai");
|
|
2
2
|
const LoadBalancer = require("../LoadBalancer")();
|
|
3
|
-
const
|
|
3
|
+
const SystemLynxService = require("../../Service/Service");
|
|
4
4
|
const HttpClient = require("../../HttpClient/HttpClient")();
|
|
5
5
|
const lbPort = 5030;
|
|
6
6
|
const route = "loadbalancer";
|
|
7
7
|
|
|
8
|
-
describe("
|
|
8
|
+
describe("LoadBalancer()", () => {
|
|
9
9
|
it("should return a SystemLynx LoadBalancer", () => {
|
|
10
10
|
expect(LoadBalancer)
|
|
11
11
|
.to.be.an("object")
|
|
12
|
-
.that.has.all.keys(
|
|
13
|
-
"startService",
|
|
14
|
-
"Server",
|
|
15
|
-
"WebSocket",
|
|
16
|
-
"defaultModule",
|
|
17
|
-
"module",
|
|
18
|
-
"clones"
|
|
19
|
-
)
|
|
12
|
+
.that.has.all.keys("startService", "Server", "WebSocket", "module", "clones")
|
|
20
13
|
.that.respondsTo("startService")
|
|
21
14
|
.that.respondsTo("Server")
|
|
22
15
|
.that.respondsTo("WebSocket")
|
|
@@ -76,9 +69,18 @@ describe("LoadBalancer.clones (Module)", () => {
|
|
|
76
69
|
it("should be a Service object with additional methods for LoadBalancing", () => {
|
|
77
70
|
expect(LoadBalancer.clones)
|
|
78
71
|
.to.be.an("Object")
|
|
79
|
-
.that.has.all.keys(
|
|
72
|
+
.that.has.all.keys(
|
|
73
|
+
"on",
|
|
74
|
+
"emit",
|
|
75
|
+
"$emit",
|
|
76
|
+
"register",
|
|
77
|
+
"dispatch",
|
|
78
|
+
"assignDispatch",
|
|
79
|
+
"clones"
|
|
80
|
+
)
|
|
80
81
|
.that.respondsTo("on")
|
|
81
82
|
.that.respondsTo("emit")
|
|
83
|
+
.that.respondsTo("$emit")
|
|
82
84
|
.that.respondsTo("register")
|
|
83
85
|
.that.respondsTo("dispatch")
|
|
84
86
|
.that.respondsTo("assignDispatch")
|
|
@@ -87,7 +89,7 @@ describe("LoadBalancer.clones (Module)", () => {
|
|
|
87
89
|
});
|
|
88
90
|
|
|
89
91
|
it("should be able to use clones.register(connData, callback) method to host connection", async () => {
|
|
90
|
-
const Service =
|
|
92
|
+
const Service = SystemLynxService();
|
|
91
93
|
const { route, port, host } = test_service1;
|
|
92
94
|
await Service.startService({ route, port, host });
|
|
93
95
|
LoadBalancer.clones.register({ route, port, host }, () => {});
|
|
@@ -113,8 +115,8 @@ describe("LoadBalancer.clones (Module)", () => {
|
|
|
113
115
|
|
|
114
116
|
it("should be able to manager the routing to multiple clones of the same Service", async () => {
|
|
115
117
|
const { route, port1, port2, host } = test_service2;
|
|
116
|
-
const Clone1 =
|
|
117
|
-
const Clone2 =
|
|
118
|
+
const Clone1 = SystemLynxService();
|
|
119
|
+
const Clone2 = SystemLynxService();
|
|
118
120
|
await Clone1.startService({ route, port: port1, host });
|
|
119
121
|
await Clone2.startService({ route, port: port2, host });
|
|
120
122
|
LoadBalancer.clones.register({ route, port: port1, host }, () => {});
|
|
@@ -128,7 +130,7 @@ describe("LoadBalancer.clones (Module)", () => {
|
|
|
128
130
|
expect(connData2.serviceUrl).to.equal(`http://localhost:${port2}/${route}`);
|
|
129
131
|
});
|
|
130
132
|
|
|
131
|
-
it("should be able to manage the route of multiple clones of multiple
|
|
133
|
+
it("should be able to manage the route of multiple clones of multiple services. aka Service Discovery", async () => {
|
|
132
134
|
const route1 = test_service1.route;
|
|
133
135
|
const route2 = test_service2.route;
|
|
134
136
|
const url1 = `http://localhost:${lbPort}/${route1}`;
|
|
@@ -39,6 +39,7 @@ module.exports = function SystemLynxServerManager() {
|
|
|
39
39
|
route =
|
|
40
40
|
route.charAt(route.length - 1) === "/" ? route.substr(route.length - 1) : route;
|
|
41
41
|
const serviceUrl = `http://${host}:${port}/${route}`;
|
|
42
|
+
|
|
42
43
|
serverConfigurations = {
|
|
43
44
|
...serverConfigurations,
|
|
44
45
|
...options,
|
|
@@ -46,42 +47,55 @@ module.exports = function SystemLynxServerManager() {
|
|
|
46
47
|
route,
|
|
47
48
|
socketPort,
|
|
48
49
|
};
|
|
50
|
+
const connectionData = {
|
|
51
|
+
modules,
|
|
52
|
+
host,
|
|
53
|
+
route: `/${route}`,
|
|
54
|
+
port,
|
|
55
|
+
serviceUrl,
|
|
56
|
+
namespace: `http://${host}:${socketPort}/${namespace}`,
|
|
57
|
+
SystemLynxService: true,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const selectModules = (moduleList) =>
|
|
61
|
+
moduleList.reduce(
|
|
62
|
+
(sum, moduleName) =>
|
|
63
|
+
sum.concat(modules.find(({ name }) => name === moduleName) || []),
|
|
64
|
+
[]
|
|
65
|
+
);
|
|
49
66
|
|
|
50
67
|
server.get(`/${route}`, (req, res) => {
|
|
51
68
|
//The route will return connection data for the service including an array of
|
|
52
69
|
//modules (objects) which contain instructions on how to make request to each object
|
|
70
|
+
const { query } = req;
|
|
71
|
+
|
|
53
72
|
res.json({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
host,
|
|
57
|
-
route: `/${route}`,
|
|
58
|
-
serviceUrl,
|
|
59
|
-
namespace: `http://${host}:${socketPort}/${namespace}`,
|
|
60
|
-
SystemLynxService: true,
|
|
73
|
+
...connectionData,
|
|
74
|
+
modules: query.modules ? selectModules(query.modules.split(",")) : modules,
|
|
61
75
|
});
|
|
62
76
|
});
|
|
63
77
|
|
|
64
78
|
return new Promise((resolve) =>
|
|
65
79
|
server.listen(port, () => {
|
|
66
80
|
console.log(`[SystemLynx][Service]: Listening on ${serviceUrl}`);
|
|
67
|
-
moduleQueue.forEach(({ name,
|
|
68
|
-
ServerManager.addModule(name,
|
|
81
|
+
moduleQueue.forEach(({ name, Module, reserved_methods }) =>
|
|
82
|
+
ServerManager.addModule(name, Module, reserved_methods)
|
|
69
83
|
);
|
|
70
84
|
moduleQueue.length = 0;
|
|
71
|
-
resolve(
|
|
85
|
+
resolve(connectionData);
|
|
72
86
|
})
|
|
73
87
|
);
|
|
74
88
|
};
|
|
75
89
|
|
|
76
|
-
ServerManager.addModule = (name,
|
|
90
|
+
ServerManager.addModule = (name, Module, reserved_methods = []) => {
|
|
77
91
|
const { host, route, serviceUrl, staticRouting, useService, useREST, socketPort } =
|
|
78
92
|
serverConfigurations;
|
|
79
93
|
|
|
80
|
-
if (!serviceUrl) return moduleQueue.push({ name,
|
|
81
|
-
const methods = parseMethods(
|
|
94
|
+
if (!serviceUrl) return moduleQueue.push({ name, Module, reserved_methods });
|
|
95
|
+
const methods = parseMethods(Module, ["on", "emit", ...reserved_methods], useREST);
|
|
82
96
|
const namespace = staticRouting ? name : shortId();
|
|
83
97
|
|
|
84
|
-
SocketEmitter.apply(
|
|
98
|
+
SocketEmitter.apply(Module, [namespace, WebSocket]);
|
|
85
99
|
|
|
86
100
|
if (useService) {
|
|
87
101
|
const path = staticRouting ? `${route}/${name}` : `${shortId()}/${shortId()}`;
|
|
@@ -92,7 +106,7 @@ module.exports = function SystemLynxServerManager() {
|
|
|
92
106
|
name,
|
|
93
107
|
methods,
|
|
94
108
|
});
|
|
95
|
-
methods.forEach((method) => router.addService(
|
|
109
|
+
methods.forEach((method) => router.addService(Module, path, method, name));
|
|
96
110
|
}
|
|
97
111
|
if (useREST)
|
|
98
112
|
methods.forEach((method) => {
|
|
@@ -101,7 +115,7 @@ module.exports = function SystemLynxServerManager() {
|
|
|
101
115
|
case "put":
|
|
102
116
|
case "post":
|
|
103
117
|
case "delete":
|
|
104
|
-
router.addREST(
|
|
118
|
+
router.addREST(Module, `${route}/${name}`, method, name);
|
|
105
119
|
}
|
|
106
120
|
});
|
|
107
121
|
};
|