unetjs 2.0.10 → 3.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.
- package/README.md +10 -6
- package/dist/cjs/unet.cjs +128 -65
- package/dist/esm/unet.js +126 -44
- package/dist/unetjs.js +126 -43
- package/dist/unetjs.js.map +1 -1
- package/dist/unetjs.min.js +1 -1
- package/dist/unetjs.min.js.map +1 -1
- package/package.json +11 -12
package/README.md
CHANGED
|
@@ -63,14 +63,18 @@ The JavaScript version of the UnetSocket API allows a user to connect to a node
|
|
|
63
63
|
|
|
64
64
|
The UnetSocket API allows a user to cache responses to parameter requests. This is useful in a scenario where the parameters aren't changing very often, and the user wants to reduce the round trip time for parameter requests.
|
|
65
65
|
|
|
66
|
+
> This behaviour used to be enabled by default in unetsocket.js v2.0.0 till v2.0.10. From v3.0.0 onwards, this behaviour is **disabled** by default but a available as an option.
|
|
67
|
+
|
|
68
|
+
You can use the `CachingGateway` class instead of the `Gateway` class to enable this behaviour.
|
|
69
|
+
|
|
66
70
|
UnetSocket API acheives this using two mechanism, firstly, it can request ALL of the parameters from an Agent instead of just one, and then cache the responses. This is called the `greedy` mode. The greedy mode is enabled by default but can be disabled by setting the `greedy` property to `false` in the `CachingAgentID` constructor.
|
|
67
71
|
|
|
68
72
|
Secondly, the UnetSocket API caches the responses to parameter requests for a limited time. If the user requests the same parameter again, the UnetSocket will return the cached response. The time to cache a response is set by the `cacheTime` property in the `CachingAgentID` constructor.
|
|
69
73
|
|
|
70
74
|
```js
|
|
71
|
-
import {UnetMessages,
|
|
72
|
-
let gw = new
|
|
73
|
-
let nodeinfo = await gw.agentForService(Services.NODE_INFO); // returns a CachingAgentID
|
|
75
|
+
import {UnetMessages, CachingGateway} from 'unetjs'
|
|
76
|
+
let gw = new CachingGateway({...});
|
|
77
|
+
let nodeinfo = await gw.agentForService(Services.NODE_INFO); // returns a CachingAgentID
|
|
74
78
|
let cLoc = nodeinfo.get('location'); // this will request all the Parameters from the Agent, and cache the responses.
|
|
75
79
|
...
|
|
76
80
|
cLoc = nodeinfo.get('location', maxage=5000); // this will return the cached response if it was called within 5000ms of the original request.
|
|
@@ -79,9 +83,9 @@ cLoc = nodeinfo.get('location', maxage=0); // this will force the Gateway to req
|
|
|
79
83
|
```
|
|
80
84
|
|
|
81
85
|
```js
|
|
82
|
-
import {UnetMessages,
|
|
83
|
-
let gw = new
|
|
84
|
-
let nodeinfo = await gw.agentForService(Services.NODE_INFO); // returns a CachingAgentID
|
|
86
|
+
import {UnetMessages, CachingGateway} from 'unetjs'
|
|
87
|
+
let gw = new CachingGateway({...});
|
|
88
|
+
let nodeinfo = await gw.agentForService(Services.NODE_INFO); // returns a CachingAgentID
|
|
85
89
|
let nonCachingNodeInfo = await gw.agentForService(Services.NODE_INFO, false); // returns an AgentID without caching (original fjage.js functionality).
|
|
86
90
|
let cLoc = nonCachingNodeInfo.get('location'); // this will request the `location` parameter from the Agent.
|
|
87
91
|
...
|
package/dist/cjs/unet.cjs
CHANGED
|
@@ -1,28 +1,8 @@
|
|
|
1
|
-
/* unet.js
|
|
1
|
+
/* unet.js v3.1.0 2024-01-26T11:16:07.040Z */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
function _interopNamespace(e) {
|
|
8
|
-
if (e && e.__esModule) return e;
|
|
9
|
-
var n = Object.create(null);
|
|
10
|
-
if (e) {
|
|
11
|
-
Object.keys(e).forEach(function (k) {
|
|
12
|
-
if (k !== 'default') {
|
|
13
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
-
enumerable: true,
|
|
16
|
-
get: function () { return e[k]; }
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
n["default"] = e;
|
|
22
|
-
return Object.freeze(n);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/* fjage.js v1.10.3 */
|
|
5
|
+
/* fjage.js v1.12.0 */
|
|
26
6
|
|
|
27
7
|
const isBrowser =
|
|
28
8
|
typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
@@ -47,10 +27,13 @@ const isJsDom =
|
|
|
47
27
|
(navigator.userAgent.includes("Node.js") ||
|
|
48
28
|
navigator.userAgent.includes("jsdom")));
|
|
49
29
|
|
|
50
|
-
typeof Deno !== "undefined" &&
|
|
30
|
+
typeof Deno !== "undefined" &&
|
|
31
|
+
typeof Deno.version !== "undefined" &&
|
|
32
|
+
typeof Deno.version.deno !== "undefined";
|
|
51
33
|
|
|
52
34
|
const SOCKET_OPEN = 'open';
|
|
53
35
|
const SOCKET_OPENING = 'opening';
|
|
36
|
+
const DEFAULT_RECONNECT_TIME$1 = 5000; // ms, delay between retries to connect to the server.
|
|
54
37
|
|
|
55
38
|
var createConnection;
|
|
56
39
|
|
|
@@ -62,17 +45,24 @@ class TCPconnector {
|
|
|
62
45
|
|
|
63
46
|
/**
|
|
64
47
|
* Create an TCPConnector to connect to a fjage master over TCP
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
48
|
+
* @param {Object} opts
|
|
49
|
+
* @param {string} [opts.hostname='localhost'] - hostname/ip address of the master container to connect to
|
|
50
|
+
* @param {number} opts.port - port number of the master container to connect to
|
|
51
|
+
* @param {string} opts.pathname - path of the master container to connect to
|
|
52
|
+
* @param {boolean} opts.keepAlive - try to reconnect if the connection is lost
|
|
53
|
+
* @param {number} [opts.reconnectTime=5000] - time before reconnection is attempted after an error
|
|
68
54
|
*/
|
|
69
55
|
constructor(opts = {}) {
|
|
70
56
|
this.url = new URL('tcp://localhost');
|
|
71
57
|
let host = opts.hostname || 'localhost';
|
|
72
58
|
let port = opts.port || -1;
|
|
73
|
-
this.url.hostname =
|
|
74
|
-
this.url.port =
|
|
59
|
+
this.url.hostname = host;
|
|
60
|
+
this.url.port = port;
|
|
75
61
|
this._buf = '';
|
|
62
|
+
this._reconnectTime = opts.reconnectTime || DEFAULT_RECONNECT_TIME$1;
|
|
63
|
+
this._keepAlive = opts.keepAlive || true;
|
|
64
|
+
this._firstConn = true; // if the Gateway has managed to connect to a server before
|
|
65
|
+
this._firstReConn = true; // if the Gateway has attempted to reconnect to a server before
|
|
76
66
|
this.pendingOnOpen = []; // list of callbacks make as soon as gateway is open
|
|
77
67
|
this.connListeners = []; // external listeners wanting to listen connection events
|
|
78
68
|
this._sockInit(host, port);
|
|
@@ -88,7 +78,7 @@ class TCPconnector {
|
|
|
88
78
|
_sockInit(host, port){
|
|
89
79
|
if (!createConnection){
|
|
90
80
|
try {
|
|
91
|
-
|
|
81
|
+
import('net').then(module => {
|
|
92
82
|
createConnection = module.createConnection;
|
|
93
83
|
this._sockSetup(host, port);
|
|
94
84
|
});
|
|
@@ -97,7 +87,7 @@ class TCPconnector {
|
|
|
97
87
|
}
|
|
98
88
|
}else {
|
|
99
89
|
this._sockSetup(host, port);
|
|
100
|
-
}
|
|
90
|
+
}
|
|
101
91
|
}
|
|
102
92
|
|
|
103
93
|
_sockSetup(host, port){
|
|
@@ -116,18 +106,18 @@ class TCPconnector {
|
|
|
116
106
|
}
|
|
117
107
|
|
|
118
108
|
_sockReconnect(){
|
|
119
|
-
if (this._firstConn || !this.
|
|
109
|
+
if (this._firstConn || !this._keepAlive || this.sock.readyState == SOCKET_OPENING || this.sock.readyState == SOCKET_OPEN) return;
|
|
120
110
|
if (this._firstReConn) this._sendConnEvent(false);
|
|
121
111
|
this._firstReConn = false;
|
|
122
|
-
if(this.debug) console.log('Reconnecting to ', this.sock.remoteAddress + ':' + this.sock.remotePort);
|
|
123
112
|
setTimeout(() => {
|
|
124
113
|
this.pendingOnOpen = [];
|
|
125
|
-
this._sockSetup(this.
|
|
114
|
+
this._sockSetup(this.url.hostname, this.url.port);
|
|
126
115
|
}, this._reconnectTime);
|
|
127
116
|
}
|
|
128
117
|
|
|
129
118
|
_onSockOpen() {
|
|
130
119
|
this._sendConnEvent(true);
|
|
120
|
+
this._firstConn = false;
|
|
131
121
|
this.sock.on('close', this._sockReconnect.bind(this));
|
|
132
122
|
this.sock.on('data', this._processSockData.bind(this));
|
|
133
123
|
this.pendingOnOpen.forEach(cb => cb());
|
|
@@ -184,7 +174,7 @@ class TCPconnector {
|
|
|
184
174
|
* @ignore
|
|
185
175
|
* @param {string} s - incoming message string
|
|
186
176
|
*/
|
|
187
|
-
|
|
177
|
+
|
|
188
178
|
/**
|
|
189
179
|
* Add listener for connection events
|
|
190
180
|
* @param {function} listener - a listener callback that is called when the connection is opened/closed
|
|
@@ -215,12 +205,16 @@ class TCPconnector {
|
|
|
215
205
|
if (this.sock.readyState == SOCKET_OPENING) {
|
|
216
206
|
this.pendingOnOpen.push(() => {
|
|
217
207
|
this.sock.send('{"alive": false}\n');
|
|
218
|
-
this.sock.
|
|
208
|
+
this.sock.removeAllListeners('connect');
|
|
209
|
+
this.sock.removeAllListeners('error');
|
|
210
|
+
this.sock.removeAllListeners('close');
|
|
219
211
|
this.sock.destroy();
|
|
220
212
|
});
|
|
221
213
|
} else if (this.sock.readyState == SOCKET_OPEN) {
|
|
222
214
|
this.sock.send('{"alive": false}\n');
|
|
223
|
-
this.sock.
|
|
215
|
+
this.sock.removeAllListeners('connect');
|
|
216
|
+
this.sock.removeAllListeners('error');
|
|
217
|
+
this.sock.removeAllListeners('close');
|
|
224
218
|
this.sock.destroy();
|
|
225
219
|
}
|
|
226
220
|
}
|
|
@@ -245,11 +239,11 @@ class WSConnector {
|
|
|
245
239
|
*/
|
|
246
240
|
constructor(opts = {}) {
|
|
247
241
|
this.url = new URL('ws://localhost');
|
|
248
|
-
this.url.hostname = opts.hostname;
|
|
242
|
+
this.url.hostname = opts.hostname;
|
|
249
243
|
this.url.port = opts.port;
|
|
250
244
|
this.url.pathname = opts.pathname;
|
|
251
245
|
this._reconnectTime = opts.reconnectTime || DEFAULT_RECONNECT_TIME;
|
|
252
|
-
this._keepAlive = opts.keepAlive;
|
|
246
|
+
this._keepAlive = opts.keepAlive || true;
|
|
253
247
|
this.debug = opts.debug || false; // debug info to be logged to console?
|
|
254
248
|
this._firstConn = true; // if the Gateway has managed to connect to a server before
|
|
255
249
|
this._firstReConn = true; // if the Gateway has attempted to reconnect to a server before
|
|
@@ -335,7 +329,7 @@ class WSConnector {
|
|
|
335
329
|
* @ignore
|
|
336
330
|
* @param {string} s - incoming message string
|
|
337
331
|
*/
|
|
338
|
-
|
|
332
|
+
|
|
339
333
|
/**
|
|
340
334
|
* Add listener for connection events
|
|
341
335
|
* @param {function} listener - a listener callback that is called when the connection is opened/closed
|
|
@@ -379,6 +373,7 @@ class WSConnector {
|
|
|
379
373
|
|
|
380
374
|
/* global global Buffer */
|
|
381
375
|
|
|
376
|
+
|
|
382
377
|
const DEFAULT_QUEUE_SIZE = 128; // max number of old unreceived messages to store
|
|
383
378
|
|
|
384
379
|
/**
|
|
@@ -507,14 +502,17 @@ class AgentID {
|
|
|
507
502
|
msg.index = Number.isInteger(index) ? index : -1;
|
|
508
503
|
const rsp = await this.owner.request(msg, timeout);
|
|
509
504
|
var ret = Array.isArray(params) ? new Array(params.length).fill(null) : null;
|
|
510
|
-
if (!rsp || rsp.perf != Performative.INFORM || !rsp.param)
|
|
505
|
+
if (!rsp || rsp.perf != Performative.INFORM || !rsp.param) {
|
|
506
|
+
if (this.owner._returnNullOnFailedResponse) return ret;
|
|
507
|
+
else throw new Error(`Unable to set ${this.name}.${params} to ${values}`);
|
|
508
|
+
}
|
|
511
509
|
if (Array.isArray(params)) {
|
|
512
510
|
if (!rsp.values) rsp.values = {};
|
|
513
511
|
if (rsp.param) rsp.values[rsp.param] = rsp.value;
|
|
514
512
|
const rvals = Object.keys(rsp.values);
|
|
515
513
|
return params.map( p => {
|
|
516
514
|
let f = rvals.find(rv => rv.endsWith(p));
|
|
517
|
-
return f ? rsp.values[f] :
|
|
515
|
+
return f ? rsp.values[f] : undefined;
|
|
518
516
|
});
|
|
519
517
|
} else {
|
|
520
518
|
return rsp.value;
|
|
@@ -545,7 +543,10 @@ class AgentID {
|
|
|
545
543
|
msg.index = Number.isInteger(index) ? index : -1;
|
|
546
544
|
const rsp = await this.owner.request(msg, timeout);
|
|
547
545
|
var ret = Array.isArray(params) ? new Array(params.length).fill(null) : null;
|
|
548
|
-
if (!rsp || rsp.perf != Performative.INFORM ||
|
|
546
|
+
if (!rsp || rsp.perf != Performative.INFORM || !rsp.param) {
|
|
547
|
+
if (this.owner._returnNullOnFailedResponse) return ret;
|
|
548
|
+
else throw new Error(`Unable to get ${this.name}.${params}`);
|
|
549
|
+
}
|
|
549
550
|
// Request for listing of all parameters.
|
|
550
551
|
if (!params) {
|
|
551
552
|
if (!rsp.values) rsp.values = {};
|
|
@@ -557,7 +558,7 @@ class AgentID {
|
|
|
557
558
|
const rvals = Object.keys(rsp.values);
|
|
558
559
|
return params.map(p => {
|
|
559
560
|
let f = rvals.find(rv => rv.endsWith(p));
|
|
560
|
-
return f ? rsp.values[f] :
|
|
561
|
+
return f ? rsp.values[f] : undefined;
|
|
561
562
|
});
|
|
562
563
|
} else {
|
|
563
564
|
return rsp.value;
|
|
@@ -641,12 +642,17 @@ class Message {
|
|
|
641
642
|
return null;
|
|
642
643
|
}
|
|
643
644
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
645
|
+
try {
|
|
646
|
+
let qclazz = obj.clazz;
|
|
647
|
+
let clazz = qclazz.replace(/^.*\./, '');
|
|
648
|
+
let rv = MessageClass[clazz] ? new MessageClass[clazz] : new Message();
|
|
649
|
+
rv.__clazz__ = qclazz;
|
|
650
|
+
rv._inflate(obj.data);
|
|
651
|
+
return rv;
|
|
652
|
+
} catch (err) {
|
|
653
|
+
console.warn('Error trying to deserialize JSON object : ', obj, err);
|
|
654
|
+
return null;
|
|
655
|
+
}
|
|
650
656
|
}
|
|
651
657
|
}
|
|
652
658
|
|
|
@@ -663,6 +669,7 @@ class Message {
|
|
|
663
669
|
* @param {string} [opts.keepAlive=true] - try to reconnect if the connection is lost
|
|
664
670
|
* @param {number} [opts.queueSize=128] - size of the queue of received messages that haven't been consumed yet
|
|
665
671
|
* @param {number} [opts.timeout=1000] - timeout for fjage level messages in ms
|
|
672
|
+
* @param {boolean} [opts.returnNullOnFailedResponse=true] - return null instead of throwing an error when a parameter is not found
|
|
666
673
|
* @param {string} [hostname="localhost"] - <strike>Deprecated : hostname/ip address of the master container to connect to</strike>
|
|
667
674
|
* @param {number} [port=] - <strike>Deprecated : port number of the master container to connect to</strike>
|
|
668
675
|
* @param {string} [pathname=="/ws/"] - <strike>Deprecated : path of the master container to connect to (for WebSockets)</strike>
|
|
@@ -691,6 +698,7 @@ class Gateway {
|
|
|
691
698
|
this._timeout = opts.timeout; // timeout for fjage level messages (agentForService etc)
|
|
692
699
|
this._keepAlive = opts.keepAlive; // reconnect if connection gets closed/errored
|
|
693
700
|
this._queueSize = opts.queueSize; // size of queue
|
|
701
|
+
this._returnNullOnFailedResponse = opts.returnNullOnFailedResponse; // null or error
|
|
694
702
|
this.pending = {}; // msgid to callback mapping for pending requests to server
|
|
695
703
|
this.subscriptions = {}; // hashset for all topics that are subscribed
|
|
696
704
|
this.listener = {}; // set of callbacks that want to listen to incoming messages
|
|
@@ -706,7 +714,13 @@ class Gateway {
|
|
|
706
714
|
_sendEvent(type, val) {
|
|
707
715
|
if (Array.isArray(this.eventListeners[type])) {
|
|
708
716
|
this.eventListeners[type].forEach(l => {
|
|
709
|
-
l && {}.toString.call(l) === '[object Function]'
|
|
717
|
+
if (l && {}.toString.call(l) === '[object Function]'){
|
|
718
|
+
try {
|
|
719
|
+
l(val);
|
|
720
|
+
} catch (error) {
|
|
721
|
+
console.warn('Error in event listener : ' + error);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
710
724
|
});
|
|
711
725
|
}
|
|
712
726
|
}
|
|
@@ -735,18 +749,26 @@ class Gateway {
|
|
|
735
749
|
var consumed = false;
|
|
736
750
|
if (Array.isArray(this.eventListeners['message'])){
|
|
737
751
|
for (var i = 0; i < this.eventListeners['message'].length; i++) {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
752
|
+
try {
|
|
753
|
+
if (this.eventListeners['message'][i](msg)) {
|
|
754
|
+
consumed = true;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
} catch (error) {
|
|
758
|
+
console.warn('Error in message listener : ' + error);
|
|
741
759
|
}
|
|
742
760
|
}
|
|
743
761
|
}
|
|
744
762
|
// iterate over internal callbacks, until one consumes the message
|
|
745
763
|
for (var key in this.listener){
|
|
746
764
|
// callback returns true if it has consumed the message
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
765
|
+
try {
|
|
766
|
+
if (this.listener[key](msg)) {
|
|
767
|
+
consumed = true;
|
|
768
|
+
break;
|
|
769
|
+
}
|
|
770
|
+
} catch (error) {
|
|
771
|
+
console.warn('Error in listener : ' + error);
|
|
750
772
|
}
|
|
751
773
|
}
|
|
752
774
|
if(!consumed) {
|
|
@@ -834,6 +856,7 @@ class Gateway {
|
|
|
834
856
|
this.connector.write('{"alive": true}');
|
|
835
857
|
this._update_watch();
|
|
836
858
|
}
|
|
859
|
+
this._sendEvent('conn', state);
|
|
837
860
|
});
|
|
838
861
|
return conn;
|
|
839
862
|
}
|
|
@@ -847,7 +870,12 @@ class Gateway {
|
|
|
847
870
|
} else if (filter.__proto__.name == 'Message' || filter.__proto__.__proto__.name == 'Message') {
|
|
848
871
|
return filter.__clazz__ == msg.__clazz__;
|
|
849
872
|
} else if (typeof filter == 'function') {
|
|
850
|
-
|
|
873
|
+
try {
|
|
874
|
+
return filter(msg);
|
|
875
|
+
}catch(e){
|
|
876
|
+
console.warn('Error in filter : ' + e);
|
|
877
|
+
return false;
|
|
878
|
+
}
|
|
851
879
|
} else {
|
|
852
880
|
return msg instanceof filter;
|
|
853
881
|
}
|
|
@@ -1021,6 +1049,30 @@ class Gateway {
|
|
|
1021
1049
|
this._update_watch();
|
|
1022
1050
|
}
|
|
1023
1051
|
|
|
1052
|
+
/**
|
|
1053
|
+
* Gets a list of all agents in the container.
|
|
1054
|
+
* @returns {Promise<AgentID[]>} - a promise which returns an array of all agent ids when resolved
|
|
1055
|
+
*/
|
|
1056
|
+
async agents() {
|
|
1057
|
+
let rq = { action: 'agents' };
|
|
1058
|
+
let rsp = await this._msgTxRx(rq);
|
|
1059
|
+
if (!rsp || !Array.isArray(rsp.agentIDs)) throw new Error('Unable to get agents');
|
|
1060
|
+
return rsp.agentIDs.map(aid => new AgentID(aid, false, this));
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* Check if an agent with a given name exists in the container.
|
|
1065
|
+
*
|
|
1066
|
+
* @param {AgentID|String} agentID - the agent id to check
|
|
1067
|
+
* @returns {Promise<boolean>} - a promise which returns true if the agent exists when resolved
|
|
1068
|
+
*/
|
|
1069
|
+
async containsAgent(agentID) {
|
|
1070
|
+
let rq = { action: 'containsAgent', agentID: agentID instanceof AgentID ? agentID.getName() : agentID };
|
|
1071
|
+
let rsp = await this._msgTxRx(rq);
|
|
1072
|
+
if (!rsp) throw new Error('Unable to check if agent exists');
|
|
1073
|
+
return !!rsp.answer;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1024
1076
|
/**
|
|
1025
1077
|
* Finds an agent that provides a named service. If multiple agents are registered
|
|
1026
1078
|
* to provide a given service, any of the agents' id may be returned.
|
|
@@ -1031,7 +1083,11 @@ class Gateway {
|
|
|
1031
1083
|
async agentForService(service) {
|
|
1032
1084
|
let rq = { action: 'agentForService', service: service };
|
|
1033
1085
|
let rsp = await this._msgTxRx(rq);
|
|
1034
|
-
if (!rsp
|
|
1086
|
+
if (!rsp) {
|
|
1087
|
+
if (this._returnNullOnFailedResponse) return null;
|
|
1088
|
+
else throw new Error('Unable to get agent for service');
|
|
1089
|
+
}
|
|
1090
|
+
if (!rsp.agentID) return null;
|
|
1035
1091
|
return new AgentID(rsp.agentID, false, this);
|
|
1036
1092
|
}
|
|
1037
1093
|
|
|
@@ -1045,7 +1101,11 @@ class Gateway {
|
|
|
1045
1101
|
let rq = { action: 'agentsForService', service: service };
|
|
1046
1102
|
let rsp = await this._msgTxRx(rq);
|
|
1047
1103
|
let aids = [];
|
|
1048
|
-
if (!rsp
|
|
1104
|
+
if (!rsp) {
|
|
1105
|
+
if (this._returnNullOnFailedResponse) return aids;
|
|
1106
|
+
else throw new Error('Unable to get agents for service');
|
|
1107
|
+
}
|
|
1108
|
+
if (!Array.isArray(rsp.agentIDs)) return aids;
|
|
1049
1109
|
for (var i = 0; i < rsp.agentIDs.length; i++)
|
|
1050
1110
|
aids.push(new AgentID(rsp.agentIDs[i], false, this));
|
|
1051
1111
|
return aids;
|
|
@@ -1117,7 +1177,7 @@ class Gateway {
|
|
|
1117
1177
|
let timer;
|
|
1118
1178
|
if (timeout > 0){
|
|
1119
1179
|
timer = setTimeout(() => {
|
|
1120
|
-
delete this.listener[lid];
|
|
1180
|
+
this.listener[lid] && delete this.listener[lid];
|
|
1121
1181
|
if (this.debug) console.log('Receive Timeout : ' + filter);
|
|
1122
1182
|
resolve();
|
|
1123
1183
|
}, timeout);
|
|
@@ -1125,7 +1185,7 @@ class Gateway {
|
|
|
1125
1185
|
this.listener[lid] = msg => {
|
|
1126
1186
|
if (!this._matchMessage(filter, msg)) return false;
|
|
1127
1187
|
if(timer) clearTimeout(timer);
|
|
1128
|
-
delete this.listener[lid];
|
|
1188
|
+
this.listener[lid] && delete this.listener[lid];
|
|
1129
1189
|
resolve(msg);
|
|
1130
1190
|
return true;
|
|
1131
1191
|
};
|
|
@@ -1264,7 +1324,8 @@ if (isBrowser || isWebWorker){
|
|
|
1264
1324
|
'pathname' : '/ws/',
|
|
1265
1325
|
'timeout': 1000,
|
|
1266
1326
|
'keepAlive' : true,
|
|
1267
|
-
'queueSize': DEFAULT_QUEUE_SIZE
|
|
1327
|
+
'queueSize': DEFAULT_QUEUE_SIZE,
|
|
1328
|
+
'returnNullOnFailedResponse': true
|
|
1268
1329
|
});
|
|
1269
1330
|
DEFAULT_URL = new URL('ws://localhost');
|
|
1270
1331
|
// Enable caching of Gateways
|
|
@@ -1278,7 +1339,8 @@ if (isBrowser || isWebWorker){
|
|
|
1278
1339
|
'pathname': '',
|
|
1279
1340
|
'timeout': 1000,
|
|
1280
1341
|
'keepAlive' : true,
|
|
1281
|
-
'queueSize': DEFAULT_QUEUE_SIZE
|
|
1342
|
+
'queueSize': DEFAULT_QUEUE_SIZE,
|
|
1343
|
+
'returnNullOnFailedResponse': true
|
|
1282
1344
|
});
|
|
1283
1345
|
DEFAULT_URL = new URL('tcp://localhost');
|
|
1284
1346
|
gObj.atob = a => Buffer.from(a, 'base64').toString('binary');
|
|
@@ -1724,7 +1786,7 @@ class UnetSocket {
|
|
|
1724
1786
|
|
|
1725
1787
|
constructor(hostname, port, path='') {
|
|
1726
1788
|
return (async () => {
|
|
1727
|
-
this.gw = new
|
|
1789
|
+
this.gw = new Gateway({
|
|
1728
1790
|
hostname : hostname,
|
|
1729
1791
|
port : port,
|
|
1730
1792
|
path : path
|
|
@@ -1984,7 +2046,8 @@ class UnetSocket {
|
|
|
1984
2046
|
|
|
1985
2047
|
exports.AgentID = AgentID;
|
|
1986
2048
|
exports.CachingAgentID = CachingAgentID;
|
|
1987
|
-
exports.
|
|
2049
|
+
exports.CachingGateway = CachingGateway;
|
|
2050
|
+
exports.Gateway = Gateway;
|
|
1988
2051
|
exports.Message = Message;
|
|
1989
2052
|
exports.MessageClass = MessageClass;
|
|
1990
2053
|
exports.Performative = Performative;
|