vrpc 2.4.0 → 3.0.0-alpha.1
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/CHANGELOG.md +69 -0
- package/README.md +33 -56
- package/binding.gyp.no-auto +4 -26
- package/browser/vrpc.js +1 -1
- package/index.js +2 -2
- package/package.json +13 -17
- package/vrpc/VrpcAdapter.js +337 -216
- package/vrpc/VrpcAgent.js +203 -183
- package/vrpc/{VrpcRemote.js → VrpcClient.js} +304 -288
- package/vrpc/VrpcNative.js +307 -0
- package/vrpc/{vrpc.hpp → adapter.hpp} +1001 -1115
- package/vrpc/addon.cpp +5 -5
- package/vrpc/json.hpp +1769 -870
- package/vrpc/vrpc-agent-js +4 -4
- package/README.rst +0 -18
- package/third_party/include/catch.hpp +0 -12749
- package/third_party/install.sh +0 -22
- package/vrpc/VrpcLocal.js +0 -264
- package/vrpc/VrpcLocal.py +0 -171
- package/vrpc/__init__.py +0 -1
- package/vrpc/module.cpp +0 -183
|
@@ -10,9 +10,9 @@ __\/\\\_______\/\\\__/\\\///////\\\___\/\\\/////////\\\____/\\\////////__
|
|
|
10
10
|
________\///________\///________\///__\///___________________\/////////__
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
Non-intrusively
|
|
13
|
+
Non-intrusively adapts code and provides access in form of asynchronous remote
|
|
14
14
|
procedure calls (RPC).
|
|
15
|
-
Author: Dr. Burkhard C. Heisen (https://github.com/
|
|
15
|
+
Author: Dr. Burkhard C. Heisen (https://github.com/heisenware/vrpc)
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
|
@@ -39,16 +39,19 @@ SOFTWARE.
|
|
|
39
39
|
|
|
40
40
|
const os = require('os')
|
|
41
41
|
const crypto = require('crypto')
|
|
42
|
+
const { nanoid } = require('nanoid')
|
|
42
43
|
const mqtt = require('mqtt')
|
|
43
44
|
const EventEmitter = require('events')
|
|
44
45
|
|
|
46
|
+
const VRPC_PROTOCOL_VERSION = 3
|
|
47
|
+
|
|
45
48
|
/**
|
|
46
49
|
* Client capable of creating proxy objects and remotely calling
|
|
47
50
|
* functions as provided through one or more (distributed) agents.
|
|
48
51
|
*
|
|
49
52
|
* @extends EventEmitter
|
|
50
53
|
*/
|
|
51
|
-
class
|
|
54
|
+
class VrpcClient extends EventEmitter {
|
|
52
55
|
/**
|
|
53
56
|
* Constructs a remote client, able to communicate with any distributed agents
|
|
54
57
|
*
|
|
@@ -66,7 +69,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
66
69
|
* @param {Object} [options.log=console] Log object (must support debug, info, warn, and error level)
|
|
67
70
|
* @param {Boolean} [options.bestEffort=false] If true, message will be sent with best effort, i.e. no caching if offline
|
|
68
71
|
* @example
|
|
69
|
-
* const client = new
|
|
72
|
+
* const client = new VrpcClient({
|
|
70
73
|
* domain: 'public.vrpc',
|
|
71
74
|
* broker: 'mqtt://vrpc.io'
|
|
72
75
|
* })
|
|
@@ -86,11 +89,15 @@ class VrpcRemote extends EventEmitter {
|
|
|
86
89
|
// domain sanity check
|
|
87
90
|
if (!domain) throw new Error('The domain must be specified')
|
|
88
91
|
if (domain.match(/[+/#*]/)) {
|
|
89
|
-
throw new Error(
|
|
92
|
+
throw new Error(
|
|
93
|
+
'The domain must NOT contain any of those characters: "+", "/", "#", "*"'
|
|
94
|
+
)
|
|
90
95
|
}
|
|
91
96
|
// agent sanity check
|
|
92
97
|
if (agent.match(/[+/#]/)) {
|
|
93
|
-
throw new Error(
|
|
98
|
+
throw new Error(
|
|
99
|
+
'The agent must NOT contain any of those characters: "+", "/", "#"'
|
|
100
|
+
)
|
|
94
101
|
}
|
|
95
102
|
this._token = token
|
|
96
103
|
this._username = username
|
|
@@ -101,14 +108,16 @@ class VrpcRemote extends EventEmitter {
|
|
|
101
108
|
this._timeout = timeout
|
|
102
109
|
this._qos = this._qos = bestEffort ? 0 : 1
|
|
103
110
|
|
|
104
|
-
this._instance =
|
|
111
|
+
this._instance = nanoid(8)
|
|
105
112
|
this._mqttClientId = this._createMqttClientId()
|
|
106
113
|
this._vrpcClientId = this._createVrpcClientId()
|
|
107
114
|
this._agents = {}
|
|
108
115
|
this._eventEmitter = new EventEmitter()
|
|
109
116
|
this._invokeId = 0
|
|
117
|
+
this._proxyId = 0
|
|
110
118
|
this._client = null
|
|
111
119
|
this._cachedSubscriptions = new Map()
|
|
120
|
+
this._proxies = {}
|
|
112
121
|
if (log === 'console') {
|
|
113
122
|
this._log = console
|
|
114
123
|
this._log.debug = () => {}
|
|
@@ -117,6 +126,15 @@ class VrpcRemote extends EventEmitter {
|
|
|
117
126
|
}
|
|
118
127
|
}
|
|
119
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Provides a unique id for this client instance
|
|
131
|
+
*
|
|
132
|
+
* @returns {String} clientId
|
|
133
|
+
*/
|
|
134
|
+
getClientId () {
|
|
135
|
+
return this._vrpcClientId
|
|
136
|
+
}
|
|
137
|
+
|
|
120
138
|
/**
|
|
121
139
|
* Actually connects to the MQTT broker.
|
|
122
140
|
*
|
|
@@ -153,15 +171,15 @@ class VrpcRemote extends EventEmitter {
|
|
|
153
171
|
if (password === undefined) delete options.password
|
|
154
172
|
this._client = mqtt.connect(this._broker, options)
|
|
155
173
|
|
|
156
|
-
this._client.on('error',
|
|
174
|
+
this._client.on('error', err => {
|
|
157
175
|
this.emit('error', err)
|
|
158
176
|
})
|
|
159
177
|
|
|
160
|
-
this._client.stream.on('error',
|
|
178
|
+
this._client.stream.on('error', err => {
|
|
161
179
|
this.emit('error', err)
|
|
162
180
|
})
|
|
163
181
|
|
|
164
|
-
this.on('error',
|
|
182
|
+
this.on('error', err => {
|
|
165
183
|
this._log.debug(`Encountered MQTT error: ${err.message}`)
|
|
166
184
|
})
|
|
167
185
|
|
|
@@ -193,7 +211,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
193
211
|
this._agents[agent].hostname = hostname
|
|
194
212
|
this._agents[agent].version = version
|
|
195
213
|
this.emit('agent', { domain, agent, status, hostname, version })
|
|
196
|
-
|
|
214
|
+
// ClassInfo message
|
|
197
215
|
} else if (instance === '__classInfo__') {
|
|
198
216
|
// Json properties: { klass, instances, memberFunctions, staticFunctions }
|
|
199
217
|
const json = JSON.parse(message.toString())
|
|
@@ -211,24 +229,23 @@ class VrpcRemote extends EventEmitter {
|
|
|
211
229
|
staticFunctions,
|
|
212
230
|
meta
|
|
213
231
|
} = json
|
|
214
|
-
if (removed.length !== 0)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
'
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// RPC message
|
|
232
|
+
if (removed.length !== 0)
|
|
233
|
+
this.emit('instanceGone', removed, { domain, agent, className })
|
|
234
|
+
if (added.length !== 0)
|
|
235
|
+
this.emit('instanceNew', added, { domain, agent, className })
|
|
236
|
+
this.emit('class', {
|
|
237
|
+
domain,
|
|
238
|
+
agent,
|
|
239
|
+
className,
|
|
240
|
+
instances,
|
|
241
|
+
memberFunctions,
|
|
242
|
+
staticFunctions,
|
|
243
|
+
meta
|
|
244
|
+
})
|
|
245
|
+
// RPC message
|
|
229
246
|
} else {
|
|
230
|
-
const {
|
|
231
|
-
this._eventEmitter.emit(
|
|
247
|
+
const { i, a, e, r } = JSON.parse(message.toString())
|
|
248
|
+
this._eventEmitter.emit(i, { a, e, r })
|
|
232
249
|
}
|
|
233
250
|
})
|
|
234
251
|
await new Promise((resolve, reject) => {
|
|
@@ -242,11 +259,6 @@ class VrpcRemote extends EventEmitter {
|
|
|
242
259
|
})
|
|
243
260
|
}
|
|
244
261
|
|
|
245
|
-
async connected () {
|
|
246
|
-
this._indicateDeprecation('VrpcRemote.connected(): This API usage is deprecated, use `connect()` instead.')
|
|
247
|
-
return this.connect()
|
|
248
|
-
}
|
|
249
|
-
|
|
250
262
|
/**
|
|
251
263
|
* Creates a new remote instance and provides a proxy to it.
|
|
252
264
|
*
|
|
@@ -272,6 +284,8 @@ class VrpcRemote extends EventEmitter {
|
|
|
272
284
|
* @param {Array} [options.args] Positional arguments for the constructor call
|
|
273
285
|
* @param {String} [options.agent] Agent name. If not provided class default
|
|
274
286
|
* is used
|
|
287
|
+
* @param {bool} [options.cacheProxy=false] If true the proxy object for a given
|
|
288
|
+
* instance is cached and used in subsequent calls
|
|
275
289
|
* @returns {Promise<Proxy>} Object reflecting a proxy to the original one
|
|
276
290
|
* handled by the agent
|
|
277
291
|
* @example
|
|
@@ -293,24 +307,24 @@ class VrpcRemote extends EventEmitter {
|
|
|
293
307
|
*/
|
|
294
308
|
async create ({
|
|
295
309
|
className,
|
|
296
|
-
instance,
|
|
310
|
+
instance = nanoid(8),
|
|
297
311
|
args = [],
|
|
298
|
-
agent = this._agent
|
|
312
|
+
agent = this._agent,
|
|
313
|
+
cacheProxy = false,
|
|
314
|
+
isIsolated = false
|
|
299
315
|
} = {}) {
|
|
300
316
|
if (agent === '*') throw new Error('Agent must be specified')
|
|
301
|
-
const data = instance ? { _1: instance } : {}
|
|
302
|
-
const offset = instance ? 2 : 1
|
|
303
|
-
args.forEach((value, index) => {
|
|
304
|
-
data[`_${index + offset}`] = value
|
|
305
|
-
})
|
|
306
317
|
const json = {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
318
|
+
c: className,
|
|
319
|
+
f: isIsolated ? '__createIsolated__' : '__createShared__',
|
|
320
|
+
i: `${this._instance}-${this._invokeId++ % Number.MAX_SAFE_INTEGER}`,
|
|
321
|
+
s: `${this._domain}/${os.hostname()}/${this._instance}`,
|
|
322
|
+
a: [instance, ...args],
|
|
323
|
+
v: VRPC_PROTOCOL_VERSION
|
|
312
324
|
}
|
|
313
|
-
|
|
325
|
+
const proxy = await this._getProxy(agent, className, json)
|
|
326
|
+
if (instance && cacheProxy) this._proxies[instance] = proxy
|
|
327
|
+
return proxy
|
|
314
328
|
}
|
|
315
329
|
|
|
316
330
|
/**
|
|
@@ -328,6 +342,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
328
342
|
* @returns {Promise<Proxy>} Proxy object reflecting the remotely existing instance
|
|
329
343
|
*/
|
|
330
344
|
async getInstance (instance, options) {
|
|
345
|
+
if (this._proxies[instance]) return this._proxies[instance]
|
|
331
346
|
if (typeof instance === 'string') {
|
|
332
347
|
const {
|
|
333
348
|
agent,
|
|
@@ -335,11 +350,12 @@ class VrpcRemote extends EventEmitter {
|
|
|
335
350
|
instance: instanceString
|
|
336
351
|
} = await this._getInstanceData(instance, options)
|
|
337
352
|
return this._createProxy(agent, className, instanceString)
|
|
338
|
-
} else {
|
|
353
|
+
} else {
|
|
354
|
+
// deprecate this
|
|
339
355
|
this._indicateDeprecation(
|
|
340
|
-
'
|
|
341
|
-
|
|
342
|
-
|
|
356
|
+
'VrpcClient.getInstance(): ' +
|
|
357
|
+
'Using an object as single argument is deprecated, ' +
|
|
358
|
+
'use "getInstance(instance, options)" instead.'
|
|
343
359
|
)
|
|
344
360
|
const fakedOptions = { ...instance }
|
|
345
361
|
const fakedInstance = fakedOptions.instance
|
|
@@ -370,24 +386,27 @@ class VrpcRemote extends EventEmitter {
|
|
|
370
386
|
if (typeof instance === 'string') {
|
|
371
387
|
instanceData = await this._getInstanceData(instance)
|
|
372
388
|
if (options) instanceData = { ...options, ...instanceData }
|
|
373
|
-
} else {
|
|
389
|
+
} else {
|
|
390
|
+
// deprecate this
|
|
374
391
|
this._indicateDeprecation(
|
|
375
|
-
'
|
|
376
|
-
|
|
377
|
-
|
|
392
|
+
'VrpcClient.delete(): ' +
|
|
393
|
+
'Using an object as single argument is deprecated, ' +
|
|
394
|
+
'use "delete(instance, options)" instead.'
|
|
378
395
|
)
|
|
379
396
|
instanceData = { ...instanceData, ...instance }
|
|
380
397
|
}
|
|
381
398
|
const { agent, className, instance: instanceString } = instanceData
|
|
382
399
|
const json = {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
400
|
+
c: className,
|
|
401
|
+
f: '__delete__',
|
|
402
|
+
i: `${this._instance}-${this._invokeId++ % Number.MAX_SAFE_INTEGER}`,
|
|
403
|
+
s: `${this._domain}/${os.hostname()}/${this._instance}`,
|
|
404
|
+
a: [instanceString],
|
|
405
|
+
v: VRPC_PROTOCOL_VERSION
|
|
388
406
|
}
|
|
389
407
|
const topic = `${this._domain}/${agent}/${className}/__static__/__delete__`
|
|
390
408
|
this._mqttPublish(topic, JSON.stringify(json))
|
|
409
|
+
if (this._proxies[instance]) delete this._proxies[instance]
|
|
391
410
|
return this._handleAgentAnswer(json)
|
|
392
411
|
}
|
|
393
412
|
|
|
@@ -407,12 +426,15 @@ class VrpcRemote extends EventEmitter {
|
|
|
407
426
|
args = [],
|
|
408
427
|
agent = this._agent
|
|
409
428
|
} = {}) {
|
|
429
|
+
const wrapped = this._wrapArguments(className, functionName, ...args)
|
|
430
|
+
if (!wrapped) return // Skipping remote call -> handled locally
|
|
410
431
|
const json = {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
432
|
+
c: className,
|
|
433
|
+
f: functionName,
|
|
434
|
+
i: `${this._instance}-${this._invokeId++ % Number.MAX_SAFE_INTEGER}`,
|
|
435
|
+
s: this._vrpcClientId,
|
|
436
|
+
a: wrapped,
|
|
437
|
+
v: VRPC_PROTOCOL_VERSION
|
|
416
438
|
}
|
|
417
439
|
const topic = `${this._domain}/${agent}/${className}/__static__/${functionName}`
|
|
418
440
|
await this._waitUntilClassIsOnline(agent, className)
|
|
@@ -422,19 +444,23 @@ class VrpcRemote extends EventEmitter {
|
|
|
422
444
|
|
|
423
445
|
/**
|
|
424
446
|
* Calls the same function on all instances of a given class and returns an
|
|
425
|
-
* aggregated result.
|
|
447
|
+
* aggregated result. It as well allows for batch event and callback
|
|
448
|
+
* registrations. In this case the instanceId of the emitter is injected as
|
|
449
|
+
* first argument of any event callback.
|
|
426
450
|
*
|
|
427
451
|
* NOTE: When no agent was specified as class default and no agent is
|
|
428
452
|
* specified when calling this function, callAll will act on the requested
|
|
429
|
-
* class across all available agents. The same is true when explicitly using
|
|
430
|
-
*
|
|
453
|
+
* class across all available agents. The same is true when explicitly using a
|
|
454
|
+
* wildcard (*) as agent value.
|
|
431
455
|
*
|
|
432
456
|
* @param {Object} options
|
|
433
457
|
* @param {String} options.className Name of the static function's class
|
|
434
|
-
* @param {Array} [options.args] Positional arguments of the static function
|
|
435
|
-
*
|
|
436
|
-
* @
|
|
437
|
-
*
|
|
458
|
+
* @param {Array} [options.args] Positional arguments of the static function
|
|
459
|
+
* call
|
|
460
|
+
* @param {String} [options.agent] Agent name. If not provided class default
|
|
461
|
+
* is used
|
|
462
|
+
* @returns {Promise<Object[]>} An array of objects `{ id, val, err }`
|
|
463
|
+
* carrying the instance id, the return value and potential errors
|
|
438
464
|
*/
|
|
439
465
|
async callAll ({
|
|
440
466
|
className,
|
|
@@ -442,20 +468,26 @@ class VrpcRemote extends EventEmitter {
|
|
|
442
468
|
args = [],
|
|
443
469
|
agent = this._agent
|
|
444
470
|
} = {}) {
|
|
445
|
-
const data = { _1: functionName }
|
|
446
|
-
args.forEach((value, index) => (data[`_${index + 2}`] = value))
|
|
447
471
|
const json = {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
472
|
+
c: className,
|
|
473
|
+
f: functionName,
|
|
474
|
+
i: `${this._instance}-${this._invokeId++ % Number.MAX_SAFE_INTEGER}`,
|
|
475
|
+
s: this._vrpcClientId,
|
|
476
|
+
a: [],
|
|
477
|
+
v: VRPC_PROTOCOL_VERSION
|
|
453
478
|
}
|
|
454
479
|
if (agent === '*') {
|
|
455
480
|
const result = []
|
|
456
481
|
const agents = this.getAvailableAgents()
|
|
457
482
|
for (const x of agents) {
|
|
458
483
|
const topic = `${this._domain}/${x}/${className}/__static__/__callAll__`
|
|
484
|
+
const wrapped = this._wrapArguments(
|
|
485
|
+
`${x}-${className}`,
|
|
486
|
+
functionName,
|
|
487
|
+
...args
|
|
488
|
+
)
|
|
489
|
+
if (!wrapped) continue // using cache
|
|
490
|
+
json.a = [functionName, ...wrapped]
|
|
459
491
|
await this._waitUntilClassIsOnline(x, className)
|
|
460
492
|
this._mqttPublish(topic, JSON.stringify(json))
|
|
461
493
|
const tmp = await this._handleAgentAnswer(json)
|
|
@@ -464,41 +496,22 @@ class VrpcRemote extends EventEmitter {
|
|
|
464
496
|
return result
|
|
465
497
|
}
|
|
466
498
|
const topic = `${this._domain}/${agent}/${className}/__static__/__callAll__`
|
|
499
|
+
const wrapped = this._wrapArguments(
|
|
500
|
+
`${agent}-${className}`,
|
|
501
|
+
functionName,
|
|
502
|
+
...args
|
|
503
|
+
)
|
|
504
|
+
if (!wrapped) return // using cache
|
|
505
|
+
json.a = [functionName, ...wrapped]
|
|
467
506
|
await this._waitUntilClassIsOnline(agent, className)
|
|
468
507
|
this._mqttPublish(topic, JSON.stringify(json))
|
|
469
508
|
return this._handleAgentAnswer(json)
|
|
470
509
|
}
|
|
471
510
|
|
|
472
|
-
/**
|
|
473
|
-
* Retrieves all agents, instances, classes, member and static
|
|
474
|
-
* functions potentially available for remote control.
|
|
475
|
-
* @deprecated
|
|
476
|
-
* @returns {Object} SystemInformation
|
|
477
|
-
* ```ts
|
|
478
|
-
* type SystemInformation = {
|
|
479
|
-
* [domain].agents[agent].status: string, // 'offline' or 'online'
|
|
480
|
-
* [domain].agents[agent].hostname: string,
|
|
481
|
-
* [domain].agents[agent].version: string,
|
|
482
|
-
* [domain].agents[agent].classes[className].instances: string[],
|
|
483
|
-
* [domain].agents[agent].classes[className].memberFunctions: string[],
|
|
484
|
-
* [domain].agents[agent].classes[className].staticFunctions: string[],
|
|
485
|
-
* [domain].agents[agent].classes[className].meta?: MetaData
|
|
486
|
-
* }
|
|
487
|
-
* ```
|
|
488
|
-
*/
|
|
489
|
-
getAvailabilities () {
|
|
490
|
-
this._indicateDeprecation(
|
|
491
|
-
'VrpcRemote.getAvailabilities(): ' +
|
|
492
|
-
'This function is deprecated and will be removed soon, ' +
|
|
493
|
-
'use `getSystemInformation()` instead.'
|
|
494
|
-
)
|
|
495
|
-
return { [this._domain]: { agents: this._agents } }
|
|
496
|
-
}
|
|
497
|
-
|
|
498
511
|
/**
|
|
499
512
|
* Retrieves all information about the currently available components.
|
|
500
513
|
*
|
|
501
|
-
|
|
514
|
+
* @returns {Object} SystemInformation
|
|
502
515
|
* ```ts
|
|
503
516
|
* type SystemInformation = {
|
|
504
517
|
* [agent].status: string, // 'offline' or 'online'
|
|
@@ -515,21 +528,6 @@ class VrpcRemote extends EventEmitter {
|
|
|
515
528
|
return this._agents
|
|
516
529
|
}
|
|
517
530
|
|
|
518
|
-
/**
|
|
519
|
-
* Retrieves all domains on which agents can be remote controlled
|
|
520
|
-
*
|
|
521
|
-
* @deprecated
|
|
522
|
-
* @returns {Array} Array of domain names
|
|
523
|
-
*/
|
|
524
|
-
getAvailableDomains () {
|
|
525
|
-
this._indicateDeprecation(
|
|
526
|
-
'VrpcRemote.getAvailableDomains(): ' +
|
|
527
|
-
'this function will be removed in the next major release, as the client' +
|
|
528
|
-
'works with a single domain anyways'
|
|
529
|
-
)
|
|
530
|
-
return [this._domain]
|
|
531
|
-
}
|
|
532
|
-
|
|
533
531
|
/**
|
|
534
532
|
* Retrieves all available agents.
|
|
535
533
|
*
|
|
@@ -542,8 +540,8 @@ class VrpcRemote extends EventEmitter {
|
|
|
542
540
|
// `options = {}` was `domain = this._domain` before
|
|
543
541
|
if (typeof options === 'string') {
|
|
544
542
|
this._indicateDeprecation(
|
|
545
|
-
'
|
|
546
|
-
|
|
543
|
+
'VrpcClient.getAvailableAgents(): ' +
|
|
544
|
+
'Providing a domain here has no effect and will be an error in future.'
|
|
547
545
|
)
|
|
548
546
|
options = { mustBeOnline: true }
|
|
549
547
|
}
|
|
@@ -570,16 +568,19 @@ class VrpcRemote extends EventEmitter {
|
|
|
570
568
|
* @param {Boolean} [options.mustBeOnline=true] Only retrieve currently online classes
|
|
571
569
|
* @returns {Array} Array of class names.
|
|
572
570
|
*/
|
|
573
|
-
getAvailableClasses (
|
|
571
|
+
getAvailableClasses (
|
|
572
|
+
options = { agent: this._agent, mustBeOnline: true },
|
|
573
|
+
domain
|
|
574
|
+
) {
|
|
574
575
|
/// DEPRECATION INFORMATION AND WORKAROUND - TO BE REMOVED IN 3.x
|
|
575
576
|
let agent = this._agent
|
|
576
577
|
let mustBeOnline = true
|
|
577
578
|
// `options = {}` was `agent = this._agent` before
|
|
578
579
|
if (typeof options === 'string') {
|
|
579
580
|
this._indicateDeprecation(
|
|
580
|
-
'
|
|
581
|
-
|
|
582
|
-
|
|
581
|
+
'VrpcClient.getAvailableClasses(): ' +
|
|
582
|
+
'setting the agent as string argument is deprecated.`' +
|
|
583
|
+
'Use `{ agent: <myAgent> }` instead.'
|
|
583
584
|
)
|
|
584
585
|
agent = options
|
|
585
586
|
} else {
|
|
@@ -589,8 +590,8 @@ class VrpcRemote extends EventEmitter {
|
|
|
589
590
|
// was `domain = this._domain` before
|
|
590
591
|
if (domain) {
|
|
591
592
|
this._indicateDeprecation(
|
|
592
|
-
'
|
|
593
|
-
|
|
593
|
+
'VrpcClient.getAvailableClasses(): ' +
|
|
594
|
+
'Providing a domain here has no effect and will be an error in future.'
|
|
594
595
|
)
|
|
595
596
|
}
|
|
596
597
|
///
|
|
@@ -622,9 +623,9 @@ class VrpcRemote extends EventEmitter {
|
|
|
622
623
|
// `options = {}` was `agent = this._agent` before
|
|
623
624
|
if (typeof options === 'string') {
|
|
624
625
|
this._indicateDeprecation(
|
|
625
|
-
'
|
|
626
|
-
|
|
627
|
-
|
|
626
|
+
'VrpcClient.getAvailableInstances(): ' +
|
|
627
|
+
'Setting the agent as string argument is deprecated.`' +
|
|
628
|
+
'Use `{ agent: <myAgent> }` instead.'
|
|
628
629
|
)
|
|
629
630
|
agent = options
|
|
630
631
|
} else {
|
|
@@ -634,8 +635,8 @@ class VrpcRemote extends EventEmitter {
|
|
|
634
635
|
// was `domain = this._domain` before
|
|
635
636
|
if (domain) {
|
|
636
637
|
this._indicateDeprecation(
|
|
637
|
-
'
|
|
638
|
-
|
|
638
|
+
'VrpcClient.getAvailableInstances(): ' +
|
|
639
|
+
'Providing a domain here has no effect and will be an error in future.'
|
|
639
640
|
)
|
|
640
641
|
}
|
|
641
642
|
///
|
|
@@ -667,9 +668,9 @@ class VrpcRemote extends EventEmitter {
|
|
|
667
668
|
// `options = {}` was `agent = this._agent` before
|
|
668
669
|
if (typeof options === 'string') {
|
|
669
670
|
this._indicateDeprecation(
|
|
670
|
-
'
|
|
671
|
-
|
|
672
|
-
|
|
671
|
+
'VrpcClient.getAvailableMemberFunctions(): ' +
|
|
672
|
+
'Setting the agent as string argument is deprecated.`' +
|
|
673
|
+
'Use `{ agent: <myAgent> }` instead.'
|
|
673
674
|
)
|
|
674
675
|
agent = options
|
|
675
676
|
} else {
|
|
@@ -679,8 +680,8 @@ class VrpcRemote extends EventEmitter {
|
|
|
679
680
|
// was `domain = this._domain` before
|
|
680
681
|
if (domain) {
|
|
681
682
|
this._indicateDeprecation(
|
|
682
|
-
'
|
|
683
|
-
|
|
683
|
+
'VrpcClient.getAvailableMemberFunctions(): ' +
|
|
684
|
+
'Providing a domain here has no effect and will be an error in future.'
|
|
684
685
|
)
|
|
685
686
|
}
|
|
686
687
|
///
|
|
@@ -714,9 +715,9 @@ class VrpcRemote extends EventEmitter {
|
|
|
714
715
|
// `options = {}` was `agent = this._agent` before
|
|
715
716
|
if (typeof options === 'string') {
|
|
716
717
|
this._indicateDeprecation(
|
|
717
|
-
'
|
|
718
|
-
|
|
719
|
-
|
|
718
|
+
'VrpcClient.getAvailableStaticFunctions(): ' +
|
|
719
|
+
'Setting the agent as string argument is deprecated.`' +
|
|
720
|
+
'Use `{ agent: <myAgent> }` instead.'
|
|
720
721
|
)
|
|
721
722
|
agent = options
|
|
722
723
|
} else {
|
|
@@ -726,8 +727,8 @@ class VrpcRemote extends EventEmitter {
|
|
|
726
727
|
// was `domain = this._domain` before
|
|
727
728
|
if (domain) {
|
|
728
729
|
this._indicateDeprecation(
|
|
729
|
-
'
|
|
730
|
-
|
|
730
|
+
'VrpcClient.getAvailableStaticFunctions(): ' +
|
|
731
|
+
'Providing a domain here has no effect and will be an error in future.'
|
|
731
732
|
)
|
|
732
733
|
}
|
|
733
734
|
///
|
|
@@ -749,10 +750,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
749
750
|
* @param {String} options.agent Agent name. If not provided class default is used
|
|
750
751
|
* @returns {Promise} Promise that resolves once re-connected
|
|
751
752
|
*/
|
|
752
|
-
async reconnectWithToken (
|
|
753
|
-
token,
|
|
754
|
-
{ agent = this._agent } = {}
|
|
755
|
-
) {
|
|
753
|
+
async reconnectWithToken (token, { agent = this._agent } = {}) {
|
|
756
754
|
this._token = token
|
|
757
755
|
this._agent = agent
|
|
758
756
|
this._client.end(() => this.connect())
|
|
@@ -791,19 +789,30 @@ class VrpcRemote extends EventEmitter {
|
|
|
791
789
|
async end () {
|
|
792
790
|
this._mqttPublish(
|
|
793
791
|
`${this._vrpcClientId}/__clientInfo__`,
|
|
794
|
-
JSON.stringify({ status: 'offline' })
|
|
792
|
+
JSON.stringify({ status: 'offline', v: VRPC_PROTOCOL_VERSION })
|
|
795
793
|
)
|
|
796
794
|
return new Promise(resolve => this._client.end(false, {}, resolve))
|
|
797
795
|
}
|
|
798
796
|
|
|
799
797
|
_createMqttClientId () {
|
|
800
|
-
const clientInfo =
|
|
801
|
-
|
|
802
|
-
|
|
798
|
+
const clientInfo =
|
|
799
|
+
os.arch() +
|
|
800
|
+
JSON.stringify(os.cpus()) +
|
|
801
|
+
os.homedir() +
|
|
802
|
+
os.hostname() +
|
|
803
|
+
JSON.stringify(os.networkInterfaces()) +
|
|
804
|
+
os.platform() +
|
|
805
|
+
os.release() +
|
|
806
|
+
os.totalmem() +
|
|
807
|
+
os.type()
|
|
803
808
|
// console.log('ClientInfo:', clientInfo)
|
|
804
|
-
const md5 = crypto
|
|
809
|
+
const md5 = crypto
|
|
810
|
+
.createHash('md5')
|
|
811
|
+
.update(clientInfo)
|
|
812
|
+
.digest('hex')
|
|
813
|
+
.substr(0, 13)
|
|
805
814
|
// FIXME (3.x): use vrpcp -> vrpcc
|
|
806
|
-
return `
|
|
815
|
+
return `vc${this._instance}${md5}` // 2 + 8 + 13 = 23 (max clientId)
|
|
807
816
|
}
|
|
808
817
|
|
|
809
818
|
_createVrpcClientId () {
|
|
@@ -811,29 +820,44 @@ class VrpcRemote extends EventEmitter {
|
|
|
811
820
|
}
|
|
812
821
|
|
|
813
822
|
_mqttPublish (topic, message, options) {
|
|
814
|
-
this._client.publish(
|
|
815
|
-
|
|
816
|
-
|
|
823
|
+
this._client.publish(
|
|
824
|
+
topic,
|
|
825
|
+
message,
|
|
826
|
+
{ qos: this._qos, ...options },
|
|
827
|
+
err => {
|
|
828
|
+
if (err) {
|
|
829
|
+
this._log.warn(
|
|
830
|
+
`Could not publish MQTT message because: ${err.message}`
|
|
831
|
+
)
|
|
832
|
+
}
|
|
817
833
|
}
|
|
818
|
-
|
|
834
|
+
)
|
|
819
835
|
}
|
|
820
836
|
|
|
821
837
|
_mqttSubscribe (topic, options) {
|
|
822
|
-
this._client.subscribe(
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
if (
|
|
827
|
-
this._log.
|
|
838
|
+
this._client.subscribe(
|
|
839
|
+
topic,
|
|
840
|
+
{ qos: this._qos, ...options },
|
|
841
|
+
(err, granted) => {
|
|
842
|
+
if (err) {
|
|
843
|
+
this._log.warn(
|
|
844
|
+
`Could not subscribe to topic: ${topic} because: ${err.message}`
|
|
845
|
+
)
|
|
846
|
+
} else {
|
|
847
|
+
if (granted.length === 0) {
|
|
848
|
+
this._log.debug(`Already subscribed to: ${topic}`)
|
|
849
|
+
}
|
|
828
850
|
}
|
|
829
851
|
}
|
|
830
|
-
|
|
852
|
+
)
|
|
831
853
|
}
|
|
832
854
|
|
|
833
855
|
_mqttUnsubscribe (topic, options) {
|
|
834
|
-
this._client.unsubscribe(topic, options,
|
|
856
|
+
this._client.unsubscribe(topic, options, err => {
|
|
835
857
|
if (err) {
|
|
836
|
-
this._log.warn(
|
|
858
|
+
this._log.warn(
|
|
859
|
+
`Could not unsubscribe from topic: ${topic} because: ${err.message}`
|
|
860
|
+
)
|
|
837
861
|
}
|
|
838
862
|
})
|
|
839
863
|
}
|
|
@@ -845,25 +869,22 @@ class VrpcRemote extends EventEmitter {
|
|
|
845
869
|
}
|
|
846
870
|
|
|
847
871
|
async _getProxy (agent, className, json) {
|
|
848
|
-
const {
|
|
849
|
-
const topic = `${this._domain}/${agent}/${className}/__static__/${
|
|
872
|
+
const { f, i } = json
|
|
873
|
+
const topic = `${this._domain}/${agent}/${className}/__static__/${f}`
|
|
850
874
|
await this._waitUntilClassIsOnline(agent, className)
|
|
851
875
|
this._mqttPublish(topic, JSON.stringify(json))
|
|
852
876
|
return new Promise((resolve, reject) => {
|
|
853
877
|
const msg = `Proxy creation for class "${className}" on agent "${agent}" and domain "${this._domain}" timed out (> ${this._timeout} ms)`
|
|
854
|
-
const timer = setTimeout(
|
|
855
|
-
()
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
this._timeout
|
|
860
|
-
)
|
|
861
|
-
this._eventEmitter.once(json.id, data => {
|
|
878
|
+
const timer = setTimeout(() => {
|
|
879
|
+
this._eventEmitter.removeAllListeners(i)
|
|
880
|
+
reject(new Error(msg))
|
|
881
|
+
}, this._timeout)
|
|
882
|
+
this._eventEmitter.once(i, ({ e, r }) => {
|
|
862
883
|
clearTimeout(timer)
|
|
863
|
-
if (
|
|
864
|
-
reject(new Error(
|
|
884
|
+
if (e) {
|
|
885
|
+
reject(new Error(e))
|
|
865
886
|
} else {
|
|
866
|
-
const proxy = this._createProxy(agent, className,
|
|
887
|
+
const proxy = this._createProxy(agent, className, r)
|
|
867
888
|
resolve(proxy)
|
|
868
889
|
}
|
|
869
890
|
})
|
|
@@ -883,7 +904,11 @@ class VrpcRemote extends EventEmitter {
|
|
|
883
904
|
}
|
|
884
905
|
timer = setTimeout(() => {
|
|
885
906
|
this.removeListener('class', checkClass)
|
|
886
|
-
reject(
|
|
907
|
+
reject(
|
|
908
|
+
new Error(
|
|
909
|
+
`Proxy creation for class "${className}" on agent "${agent}" and domain "${this._domain}" timed out (> ${this._timeout} ms)`
|
|
910
|
+
)
|
|
911
|
+
)
|
|
887
912
|
}, this._timeout)
|
|
888
913
|
this.on('class', checkClass)
|
|
889
914
|
})
|
|
@@ -899,10 +924,11 @@ class VrpcRemote extends EventEmitter {
|
|
|
899
924
|
|
|
900
925
|
_createProxy (agent, className, instance) {
|
|
901
926
|
const targetTopic = `${this._domain}/${agent}/${className}/${instance}`
|
|
902
|
-
const proxyId =
|
|
927
|
+
const proxyId = `${this._instance}-${this._proxyId++}`
|
|
903
928
|
const proxy = {
|
|
904
|
-
|
|
905
|
-
|
|
929
|
+
vrpcClientId: this._vrpcClientId,
|
|
930
|
+
vrpcInstanceId: instance,
|
|
931
|
+
vrpcProxyId: proxyId
|
|
906
932
|
}
|
|
907
933
|
let functions = this._agents[agent].classes[className].memberFunctions
|
|
908
934
|
// Strip off argument signature
|
|
@@ -916,37 +942,37 @@ class VrpcRemote extends EventEmitter {
|
|
|
916
942
|
// Build proxy
|
|
917
943
|
uniqueFuncs.forEach(name => {
|
|
918
944
|
proxy[name] = async (...args) => {
|
|
945
|
+
const wrapped = this._wrapArguments(proxyId, name, ...args)
|
|
946
|
+
if (!wrapped) return // Skipping remote call -> handled locally
|
|
919
947
|
try {
|
|
920
948
|
const json = {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
949
|
+
c: instance,
|
|
950
|
+
f: name,
|
|
951
|
+
i: `${this._instance}-${this._invokeId++ % Number.MAX_SAFE_INTEGER}`,
|
|
952
|
+
s: this._vrpcClientId,
|
|
953
|
+
a: wrapped,
|
|
954
|
+
v: VRPC_PROTOCOL_VERSION
|
|
926
955
|
}
|
|
927
|
-
// Skipping remote call -> handled locally
|
|
928
|
-
if (json.data === null) return
|
|
929
956
|
this._mqttPublish(`${targetTopic}/${name}`, JSON.stringify(json))
|
|
930
957
|
return this._handleAgentAnswer(json)
|
|
931
958
|
} catch (err) {
|
|
932
|
-
throw new Error(
|
|
959
|
+
throw new Error(
|
|
960
|
+
`Could not remotely call "${name}" because: ${err.message}`
|
|
961
|
+
)
|
|
933
962
|
}
|
|
934
963
|
}
|
|
935
964
|
})
|
|
936
965
|
return proxy
|
|
937
966
|
}
|
|
938
967
|
|
|
939
|
-
async _handleAgentAnswer ({
|
|
968
|
+
async _handleAgentAnswer ({ i, c, f }) {
|
|
940
969
|
return new Promise((resolve, reject) => {
|
|
941
|
-
const msg = `Function call "${
|
|
942
|
-
const timer = setTimeout(
|
|
943
|
-
()
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
this._timeout
|
|
948
|
-
)
|
|
949
|
-
this._eventEmitter.once(id, data => {
|
|
970
|
+
const msg = `Function call "${c}::${f}()" timed out (> ${this._timeout} ms)`
|
|
971
|
+
const timer = setTimeout(() => {
|
|
972
|
+
this._eventEmitter.removeAllListeners(i)
|
|
973
|
+
reject(new Error(msg))
|
|
974
|
+
}, this._timeout)
|
|
975
|
+
this._eventEmitter.once(i, data => {
|
|
950
976
|
clearTimeout(timer)
|
|
951
977
|
if (data.e) {
|
|
952
978
|
reject(new Error(data.e))
|
|
@@ -968,7 +994,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
968
994
|
|
|
969
995
|
async _waitForInstance (instance, options = {}) {
|
|
970
996
|
return new Promise((resolve, reject) => {
|
|
971
|
-
const handler =
|
|
997
|
+
const handler = timer => (instances, { agent, className }) => {
|
|
972
998
|
if (instances.includes(instance)) {
|
|
973
999
|
if (options.agent && agent !== options.agent) return
|
|
974
1000
|
if (options.className && className !== options.className) return
|
|
@@ -977,75 +1003,64 @@ class VrpcRemote extends EventEmitter {
|
|
|
977
1003
|
resolve({ agent, className, instance })
|
|
978
1004
|
}
|
|
979
1005
|
}
|
|
980
|
-
const timer = setTimeout(
|
|
981
|
-
()
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
},
|
|
986
|
-
this._timeout
|
|
987
|
-
)
|
|
1006
|
+
const timer = setTimeout(() => {
|
|
1007
|
+
this.removeListener('instanceNew', handler(timer))
|
|
1008
|
+
const msg = `Could not find instance: ${instance} (> ${this._timeout} ms)`
|
|
1009
|
+
reject(new Error(msg))
|
|
1010
|
+
}, this._timeout)
|
|
988
1011
|
this.on('instanceNew', handler(timer))
|
|
989
1012
|
})
|
|
990
1013
|
}
|
|
991
1014
|
|
|
992
|
-
|
|
993
|
-
const
|
|
1015
|
+
_wrapArguments (remoteId, functionName, ...args) {
|
|
1016
|
+
const wrapped = []
|
|
994
1017
|
let isHandledLocally = false
|
|
995
|
-
args.forEach((
|
|
1018
|
+
args.forEach((x, i) => {
|
|
996
1019
|
// Check whether provided argument is a function
|
|
997
|
-
if (this._isFunction(
|
|
1020
|
+
if (this._isFunction(x)) {
|
|
998
1021
|
// Check special case of an event emitter registration
|
|
999
1022
|
// We test three conditions:
|
|
1000
1023
|
// 1) functionName must be "on"
|
|
1001
1024
|
// 2) callback is second argument
|
|
1002
1025
|
// 3) first argument was string
|
|
1003
|
-
if (functionName === 'on' &&
|
|
1004
|
-
|
|
1005
|
-
typeof args[0] === 'string'
|
|
1006
|
-
) {
|
|
1007
|
-
const id = this._addEventSubscription(proxyId, args[0], value)
|
|
1026
|
+
if (functionName === 'on' && i === 1 && typeof args[0] === 'string') {
|
|
1027
|
+
const id = this._addEventSubscription(remoteId, args[0], x)
|
|
1008
1028
|
if (!id) isHandledLocally = true
|
|
1009
|
-
|
|
1029
|
+
wrapped.push(id)
|
|
1010
1030
|
} else if (
|
|
1011
1031
|
(functionName === 'off' || functionName === 'removeListener') &&
|
|
1012
|
-
|
|
1032
|
+
i === 1 &&
|
|
1013
1033
|
typeof args[0] === 'string'
|
|
1014
1034
|
) {
|
|
1015
|
-
const id = this._removeEventSubscription(
|
|
1035
|
+
const id = this._removeEventSubscription(remoteId, args[0], x)
|
|
1016
1036
|
if (!id) isHandledLocally = true
|
|
1017
|
-
|
|
1018
|
-
|
|
1037
|
+
wrapped.push(id)
|
|
1038
|
+
// Regular function callback
|
|
1019
1039
|
} else {
|
|
1020
|
-
const id = `__f__${
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
.map(x => data[x])
|
|
1026
|
-
value.apply(null, args) // This is the actual function call
|
|
1040
|
+
const id = `__f__${remoteId}-${functionName}-${i}-${this._invokeId++ %
|
|
1041
|
+
Number.MAX_SAFE_INTEGER}`
|
|
1042
|
+
wrapped.push(id)
|
|
1043
|
+
this._eventEmitter.once(id, ({ a }) => {
|
|
1044
|
+
x.apply(null, a) // This is the actual function call
|
|
1027
1045
|
})
|
|
1028
1046
|
}
|
|
1029
|
-
} else if (this._isEmitter(
|
|
1030
|
-
const { emitter, event } =
|
|
1031
|
-
const id = `__f__${
|
|
1032
|
-
|
|
1033
|
-
this._eventEmitter.on(id,
|
|
1034
|
-
|
|
1035
|
-
.filter(x => x[0] === '_')
|
|
1036
|
-
.map(x => data[x])
|
|
1037
|
-
emitter.emit(event, ...args)
|
|
1047
|
+
} else if (this._isEmitter(x)) {
|
|
1048
|
+
const { emitter, event } = x
|
|
1049
|
+
const id = `__f__${remoteId}-${functionName}-${i}-${event}`
|
|
1050
|
+
wrapped.push(id)
|
|
1051
|
+
this._eventEmitter.on(id, ({ a }) => {
|
|
1052
|
+
emitter.emit(event, ...a)
|
|
1038
1053
|
})
|
|
1039
1054
|
} else {
|
|
1040
|
-
|
|
1055
|
+
wrapped.push(x)
|
|
1041
1056
|
}
|
|
1042
1057
|
})
|
|
1043
1058
|
if (isHandledLocally) return null
|
|
1044
|
-
return
|
|
1059
|
+
return wrapped
|
|
1045
1060
|
}
|
|
1046
1061
|
|
|
1047
|
-
_addEventSubscription (
|
|
1048
|
-
const id = `__f__${
|
|
1062
|
+
_addEventSubscription (remoteId, event, callback) {
|
|
1063
|
+
const id = `__f__${remoteId}-${event}`
|
|
1049
1064
|
if (this._cachedSubscriptions.has(id)) {
|
|
1050
1065
|
this._cachedSubscriptions.get(id).on(id, callback)
|
|
1051
1066
|
return
|
|
@@ -1053,17 +1068,14 @@ class VrpcRemote extends EventEmitter {
|
|
|
1053
1068
|
const emitter = new EventEmitter()
|
|
1054
1069
|
emitter.on(id, callback)
|
|
1055
1070
|
this._cachedSubscriptions.set(id, emitter)
|
|
1056
|
-
this._eventEmitter.on(id, (
|
|
1057
|
-
|
|
1058
|
-
.filter(x => x[0] === '_')
|
|
1059
|
-
.map(x => data[x])
|
|
1060
|
-
emitter.emit(id, ...args)
|
|
1071
|
+
this._eventEmitter.on(id, ({ a }) => {
|
|
1072
|
+
emitter.emit(id, ...a)
|
|
1061
1073
|
})
|
|
1062
1074
|
return id
|
|
1063
1075
|
}
|
|
1064
1076
|
|
|
1065
|
-
_removeEventSubscription (
|
|
1066
|
-
const id = `__f__${
|
|
1077
|
+
_removeEventSubscription (remoteId, event, callback) {
|
|
1078
|
+
const id = `__f__${remoteId}-${event}`
|
|
1067
1079
|
if (this._cachedSubscriptions.has(id)) {
|
|
1068
1080
|
const emitter = this._cachedSubscriptions.get(id)
|
|
1069
1081
|
emitter.removeListener(id, callback)
|
|
@@ -1084,8 +1096,10 @@ class VrpcRemote extends EventEmitter {
|
|
|
1084
1096
|
_isFunction (variable) {
|
|
1085
1097
|
const getType = {}
|
|
1086
1098
|
const type = getType.toString.call(variable)
|
|
1087
|
-
return
|
|
1099
|
+
return (
|
|
1100
|
+
variable &&
|
|
1088
1101
|
(type === '[object Function]' || type === '[object AsyncFunction]')
|
|
1102
|
+
)
|
|
1089
1103
|
}
|
|
1090
1104
|
|
|
1091
1105
|
_isEmitter (variable) {
|
|
@@ -1101,7 +1115,9 @@ class VrpcRemote extends EventEmitter {
|
|
|
1101
1115
|
async _getInstanceData (instance, options = {}) {
|
|
1102
1116
|
const instanceData = this._getInstanceFromCache(instance, options)
|
|
1103
1117
|
if (!instanceData) {
|
|
1104
|
-
if (options.noWait)
|
|
1118
|
+
if (options.noWait) {
|
|
1119
|
+
throw new Error(`Could not find instance: ${instance}`)
|
|
1120
|
+
}
|
|
1105
1121
|
return this._waitForInstance(instance, options)
|
|
1106
1122
|
}
|
|
1107
1123
|
return instanceData
|
|
@@ -1140,7 +1156,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
1140
1156
|
* This event is fired whenever an agent is added or removed, or whenever
|
|
1141
1157
|
* an agent changes its status (switches between online or offline).
|
|
1142
1158
|
*
|
|
1143
|
-
* @event
|
|
1159
|
+
* @event VrpcClient#agent
|
|
1144
1160
|
* @param {Object} info
|
|
1145
1161
|
* @param {String} info.domain - Domain name
|
|
1146
1162
|
* @param {String} info.agent - Agent name
|
|
@@ -1155,7 +1171,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
1155
1171
|
* Emitted whenever a class is added or removed, or when instances
|
|
1156
1172
|
* or functions of this class have changed.
|
|
1157
1173
|
*
|
|
1158
|
-
* @event
|
|
1174
|
+
* @event VrpcClient#class
|
|
1159
1175
|
* @param {Object} info
|
|
1160
1176
|
* @param {String} info.domain - Domain name
|
|
1161
1177
|
* @param {String} info.agent - Agent name
|
|
@@ -1167,57 +1183,57 @@ class VrpcRemote extends EventEmitter {
|
|
|
1167
1183
|
*/
|
|
1168
1184
|
|
|
1169
1185
|
/**
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1186
|
+
* Event 'instanceNew'
|
|
1187
|
+
*
|
|
1188
|
+
* Emitted whenever a new instance was created.
|
|
1189
|
+
*
|
|
1190
|
+
* @event VrpcClient#instanceNew
|
|
1191
|
+
*
|
|
1192
|
+
* @param {Array.<String>} addedInstances - An array of newly added instances
|
|
1193
|
+
* @param {Object} info
|
|
1194
|
+
* @param {String} info.domain - Domain name
|
|
1195
|
+
* @param {String} info.agent - Agent name
|
|
1196
|
+
* @param {String} info.className - Class name
|
|
1197
|
+
*/
|
|
1182
1198
|
|
|
1183
1199
|
/**
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1200
|
+
* Event 'instanceGone'
|
|
1201
|
+
*
|
|
1202
|
+
* Emitted whenever a new instance was removed.
|
|
1203
|
+
*
|
|
1204
|
+
* @event VrpcClient#instanceGone
|
|
1205
|
+
*
|
|
1206
|
+
* @param {Array.<String>} removedInstances - An array of removed instances
|
|
1207
|
+
* @param {Object} info
|
|
1208
|
+
* @param {String} info.domain - Domain name
|
|
1209
|
+
* @param {String} info.agent - Agent name
|
|
1210
|
+
* @param {String} info.className - Class name
|
|
1211
|
+
*/
|
|
1196
1212
|
|
|
1197
1213
|
/**
|
|
1198
1214
|
* Event 'connect'
|
|
1199
1215
|
*
|
|
1200
1216
|
* Emitted on successful (re)connection (i.e. connack rc=0).
|
|
1201
1217
|
*
|
|
1202
|
-
* @event
|
|
1218
|
+
* @event VrpcClient#connect
|
|
1203
1219
|
* @type {Object}
|
|
1204
1220
|
* @property {Boolean} sessionPresent - A session from a previous connection is already present
|
|
1205
|
-
*/
|
|
1221
|
+
*/
|
|
1206
1222
|
|
|
1207
1223
|
/**
|
|
1208
1224
|
* Event 'reconnect'
|
|
1209
1225
|
*
|
|
1210
1226
|
* Emitted when a reconnect starts.
|
|
1211
1227
|
*
|
|
1212
|
-
* @event
|
|
1213
|
-
*/
|
|
1228
|
+
* @event VrpcClient#reconnect
|
|
1229
|
+
*/
|
|
1214
1230
|
|
|
1215
1231
|
/**
|
|
1216
1232
|
* Event 'close'
|
|
1217
1233
|
*
|
|
1218
1234
|
* Emitted after a disconnection.
|
|
1219
1235
|
*
|
|
1220
|
-
* @event
|
|
1236
|
+
* @event VrpcClient#close
|
|
1221
1237
|
*/
|
|
1222
1238
|
|
|
1223
1239
|
/**
|
|
@@ -1225,7 +1241,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
1225
1241
|
*
|
|
1226
1242
|
* Emitted when the client goes offline.
|
|
1227
1243
|
*
|
|
1228
|
-
* @event
|
|
1244
|
+
* @event VrpcClient#offline
|
|
1229
1245
|
*/
|
|
1230
1246
|
|
|
1231
1247
|
/**
|
|
@@ -1240,7 +1256,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
1240
1256
|
* - EADDRINUSE
|
|
1241
1257
|
* - ENOTFOUND
|
|
1242
1258
|
*
|
|
1243
|
-
* @event
|
|
1259
|
+
* @event VrpcClient#error
|
|
1244
1260
|
* @type {Object} Error
|
|
1245
1261
|
*/
|
|
1246
1262
|
|
|
@@ -1250,7 +1266,7 @@ class VrpcRemote extends EventEmitter {
|
|
|
1250
1266
|
* Emitted when mqtt.Client#end() is called. If a callback was passed to
|
|
1251
1267
|
* mqtt.Client#end(), this event is emitted once the callback returns.
|
|
1252
1268
|
*
|
|
1253
|
-
* @event
|
|
1269
|
+
* @event VrpcClient#end
|
|
1254
1270
|
*/
|
|
1255
1271
|
|
|
1256
|
-
module.exports =
|
|
1272
|
+
module.exports = VrpcClient
|