vrpc 3.5.1 → 3.5.3
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/browser/vrpc.js +2 -2
- package/package.json +1 -1
- package/vrpc/VrpcClient.js +162 -126
package/package.json
CHANGED
package/vrpc/VrpcClient.js
CHANGED
|
@@ -136,6 +136,8 @@ class VrpcClient extends EventEmitter {
|
|
|
136
136
|
this._proxies = {}
|
|
137
137
|
this._callbackIds = new WeakMap()
|
|
138
138
|
this._emitterListener = new WeakMap()
|
|
139
|
+
this._pendingSubscriptions = new Map()
|
|
140
|
+
this._pendingUnsubscriptions = new Map()
|
|
139
141
|
if (log === 'console') {
|
|
140
142
|
this._log = console
|
|
141
143
|
this._log.debug = () => {}
|
|
@@ -188,6 +190,11 @@ class VrpcClient extends EventEmitter {
|
|
|
188
190
|
}
|
|
189
191
|
if (username === undefined) delete options.username
|
|
190
192
|
if (password === undefined) delete options.password
|
|
193
|
+
|
|
194
|
+
this.on('error', err => {
|
|
195
|
+
this._log.debug(`Encountered MQTT error: ${err.message}`)
|
|
196
|
+
})
|
|
197
|
+
|
|
191
198
|
this._client = mqtt.connect(this._broker, options)
|
|
192
199
|
|
|
193
200
|
// Persistent lifecycle handlers
|
|
@@ -195,6 +202,7 @@ class VrpcClient extends EventEmitter {
|
|
|
195
202
|
this._log.warn('MQTT client went offline.')
|
|
196
203
|
// Clear the cache to ensure a fresh state upon reconnection
|
|
197
204
|
this._agents = {}
|
|
205
|
+
this._proxies = {}
|
|
198
206
|
this.emit('offline')
|
|
199
207
|
})
|
|
200
208
|
|
|
@@ -211,31 +219,37 @@ class VrpcClient extends EventEmitter {
|
|
|
211
219
|
this.emit('error', err)
|
|
212
220
|
})
|
|
213
221
|
|
|
214
|
-
this.on('
|
|
215
|
-
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
this._client.on('connect', () => {
|
|
219
|
-
// This will give us an overview of all remotely available classes
|
|
220
|
-
const agent = this._agent === '*' ? '+' : this._agent
|
|
221
|
-
// Agent info
|
|
222
|
-
this._mqttSubscribe(`${this._domain}/${agent}/__agentInfo__`)
|
|
223
|
-
// Class info
|
|
224
|
-
if (this._requiresSchema) {
|
|
225
|
-
this._mqttSubscribe(`${this._domain}/${agent}/+/__classInfo__`)
|
|
226
|
-
} else {
|
|
227
|
-
this._mqttSubscribe(`${this._domain}/${agent}/+/__classInfoConcise__`)
|
|
228
|
-
}
|
|
229
|
-
// RPC responses
|
|
230
|
-
this._mqttSubscribe(this._vrpcClientId)
|
|
231
|
-
|
|
232
|
-
// Re-subscribe to all cached event topics
|
|
233
|
-
this._log.info('Restoring event subscriptions after reconnect...')
|
|
234
|
-
for (const topic of Object.keys(this._cachedSubscriptions)) {
|
|
235
|
-
this._mqttSubscribe(topic)
|
|
236
|
-
}
|
|
237
|
-
|
|
222
|
+
this._client.on('connect', async () => {
|
|
223
|
+
// forward the good news
|
|
238
224
|
this.emit('connect')
|
|
225
|
+
try {
|
|
226
|
+
// This will give us an overview of all remotely available classes
|
|
227
|
+
const agent = this._agent === '*' ? '+' : this._agent
|
|
228
|
+
// Agent info
|
|
229
|
+
await this._mqttSubscribe(`${this._domain}/${agent}/__agentInfo__`)
|
|
230
|
+
// Class info
|
|
231
|
+
if (this._requiresSchema) {
|
|
232
|
+
await this._mqttSubscribe(`${this._domain}/${agent}/+/__classInfo__`)
|
|
233
|
+
} else {
|
|
234
|
+
await this._mqttSubscribe(
|
|
235
|
+
`${this._domain}/${agent}/+/__classInfoConcise__`
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
// RPC responses
|
|
239
|
+
await this._mqttSubscribe(this._vrpcClientId)
|
|
240
|
+
|
|
241
|
+
// Re-subscribe to all cached event topics
|
|
242
|
+
this._log.debug('Restoring event subscriptions after reconnect...')
|
|
243
|
+
const promises = []
|
|
244
|
+
for (const topic of Object.keys(this._cachedSubscriptions)) {
|
|
245
|
+
promises.push(this._mqttSubscribe(topic))
|
|
246
|
+
}
|
|
247
|
+
await Promise.allSettled(promises)
|
|
248
|
+
} catch (err) {
|
|
249
|
+
this._log.error(
|
|
250
|
+
`Encountered issue while setting up subscriptions after connect: ${err.message}`
|
|
251
|
+
)
|
|
252
|
+
}
|
|
239
253
|
})
|
|
240
254
|
|
|
241
255
|
this._client.on('message', (topic, message) => {
|
|
@@ -326,7 +340,6 @@ class VrpcClient extends EventEmitter {
|
|
|
326
340
|
resolve()
|
|
327
341
|
})
|
|
328
342
|
})
|
|
329
|
-
// --------------------------------------------------------------------------------
|
|
330
343
|
}
|
|
331
344
|
|
|
332
345
|
/**
|
|
@@ -455,25 +468,7 @@ class VrpcClient extends EventEmitter {
|
|
|
455
468
|
const topic = `${this._domain}/${agent}/${className}/__static__/__delete__`
|
|
456
469
|
this._mqttPublish(topic, JSON.stringify(json))
|
|
457
470
|
if (this._proxies[instance]) delete this._proxies[instance]
|
|
458
|
-
|
|
459
|
-
// Now that deletion is confirmed, proactively update all local caches
|
|
460
|
-
if (result) {
|
|
461
|
-
// 1. Remove from the proxy cache
|
|
462
|
-
if (this._proxies[instance]) {
|
|
463
|
-
delete this._proxies[instance]
|
|
464
|
-
}
|
|
465
|
-
// 2. Remove from the main agent/instance cache
|
|
466
|
-
if (this._agents[agent] && this._agents[agent].classes) {
|
|
467
|
-
const classInfo = this._agents[agent].classes[className]
|
|
468
|
-
if (classInfo && classInfo.instances) {
|
|
469
|
-
const index = classInfo.instances.indexOf(instance)
|
|
470
|
-
if (index > -1) {
|
|
471
|
-
classInfo.instances.splice(index, 1)
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
return result
|
|
471
|
+
return this._handleAgentAnswer(json, agent)
|
|
477
472
|
}
|
|
478
473
|
|
|
479
474
|
/**
|
|
@@ -495,7 +490,7 @@ class VrpcClient extends EventEmitter {
|
|
|
495
490
|
if (!this._isConnected()) {
|
|
496
491
|
throw new Error('Client is not connected')
|
|
497
492
|
}
|
|
498
|
-
const wrapped = this._wrapArguments({
|
|
493
|
+
const wrapped = await this._wrapArguments({
|
|
499
494
|
agent,
|
|
500
495
|
className,
|
|
501
496
|
functionName,
|
|
@@ -558,7 +553,7 @@ class VrpcClient extends EventEmitter {
|
|
|
558
553
|
const agents = this.getAvailableAgents()
|
|
559
554
|
for (const agent of agents) {
|
|
560
555
|
const topic = `${this._domain}/${agent}/${className}/__static__/__callAll__`
|
|
561
|
-
const wrapped = this._wrapArguments({
|
|
556
|
+
const wrapped = await this._wrapArguments({
|
|
562
557
|
agent,
|
|
563
558
|
className,
|
|
564
559
|
functionName,
|
|
@@ -574,7 +569,7 @@ class VrpcClient extends EventEmitter {
|
|
|
574
569
|
return result
|
|
575
570
|
}
|
|
576
571
|
const topic = `${this._domain}/${agent}/${className}/__static__/__callAll__`
|
|
577
|
-
const wrapped = this._wrapArguments({
|
|
572
|
+
const wrapped = await this._wrapArguments({
|
|
578
573
|
agent,
|
|
579
574
|
className,
|
|
580
575
|
functionName,
|
|
@@ -847,68 +842,77 @@ class VrpcClient extends EventEmitter {
|
|
|
847
842
|
)
|
|
848
843
|
}
|
|
849
844
|
|
|
850
|
-
_mqttSubscribe (topic, options) {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
if (err.message === 'client disconnecting') {
|
|
860
|
-
// This most certainly relates to a bug in MQTT.js (#1284)
|
|
861
|
-
this._log.error(`Failed to subscribe, because: ${err.message}`)
|
|
862
|
-
this.emit('error', err)
|
|
863
|
-
this._log.info('Forcing reconnect now...')
|
|
864
|
-
this._client.disconnecting = false
|
|
865
|
-
this._client.reconnect()
|
|
866
|
-
}
|
|
867
|
-
} else {
|
|
868
|
-
const topicArray = Array.isArray(topic) ? topic : [topic]
|
|
869
|
-
const erroneousGranted = granted
|
|
870
|
-
.filter(x => x.qos === 128)
|
|
871
|
-
.map(x => x.topic)
|
|
872
|
-
if (erroneousGranted.length > 0) {
|
|
873
|
-
err = new Error(
|
|
874
|
-
`Could not subscribe all ${topicArray.length} topic(s) but got error qos=128 on following ${erroneousGranted.length} topic(s): ${erroneousGranted}`
|
|
875
|
-
)
|
|
876
|
-
err.code = 'SUBSCRIBE_FAILED'
|
|
877
|
-
err.subscribeOptions = options
|
|
878
|
-
this._log.error(err)
|
|
879
|
-
this.emit('error', err)
|
|
880
|
-
}
|
|
881
|
-
const reducedQos = granted.filter(x => x.qos < this._qos)
|
|
882
|
-
if (reducedQos.length > 0) {
|
|
883
|
-
err = new Error(
|
|
884
|
-
`Could not subscribe all ${
|
|
885
|
-
topicArray.length
|
|
886
|
-
} topic(s) at desired qos=${
|
|
887
|
-
this._qos
|
|
888
|
-
} but got reduced qos on following ${
|
|
889
|
-
reducedQos.length
|
|
890
|
-
} topic(s): ${JSON.stringify(reducedQos)}`
|
|
845
|
+
async _mqttSubscribe (topic, options) {
|
|
846
|
+
return new Promise((resolve, reject) => {
|
|
847
|
+
this._client.subscribe(
|
|
848
|
+
topic,
|
|
849
|
+
{ qos: this._qos, ...options },
|
|
850
|
+
(err, granted) => {
|
|
851
|
+
if (err) {
|
|
852
|
+
this._log.warn(
|
|
853
|
+
`Could not subscribe to topic(s): '${topic}', because: ${err.message}`
|
|
891
854
|
)
|
|
892
|
-
err.
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
855
|
+
if (err.message === 'client disconnecting') {
|
|
856
|
+
// This most certainly relates to a bug in MQTT.js (#1284)
|
|
857
|
+
const msg = `Failed to subscribe, because: ${err.message}`
|
|
858
|
+
this._log.error(msg)
|
|
859
|
+
this.emit('error', err)
|
|
860
|
+
this._log.info('Forcing reconnect now...')
|
|
861
|
+
this._client.disconnecting = false
|
|
862
|
+
this._client.reconnect()
|
|
863
|
+
reject(new Error(msg))
|
|
864
|
+
}
|
|
865
|
+
} else {
|
|
866
|
+
const topicArray = Array.isArray(topic) ? topic : [topic]
|
|
867
|
+
const erroneousGranted = granted
|
|
868
|
+
.filter(x => x.qos === 128)
|
|
869
|
+
.map(x => x.topic)
|
|
870
|
+
if (erroneousGranted.length > 0) {
|
|
871
|
+
err = new Error(
|
|
872
|
+
`Could not subscribe all ${topicArray.length} topic(s) but got error qos=128 on following ${erroneousGranted.length} topic(s): ${erroneousGranted}`
|
|
873
|
+
)
|
|
874
|
+
err.code = 'SUBSCRIBE_FAILED'
|
|
875
|
+
err.subscribeOptions = options
|
|
876
|
+
this._log.error(err.message)
|
|
877
|
+
this.emit('error', err)
|
|
878
|
+
}
|
|
879
|
+
const reducedQos = granted.filter(x => x.qos < this._qos)
|
|
880
|
+
if (reducedQos.length > 0) {
|
|
881
|
+
err = new Error(
|
|
882
|
+
`Could not subscribe all ${
|
|
883
|
+
topicArray.length
|
|
884
|
+
} topic(s) at desired qos=${
|
|
885
|
+
this._qos
|
|
886
|
+
} but got reduced qos on following ${
|
|
887
|
+
reducedQos.length
|
|
888
|
+
} topic(s): ${JSON.stringify(reducedQos)}`
|
|
889
|
+
)
|
|
890
|
+
err.code = 'SUBSCRIBE_REDUCED_QOS'
|
|
891
|
+
err.subscribeOptions = options
|
|
892
|
+
this._log.warn(err.message)
|
|
893
|
+
this.emit('error', err)
|
|
894
|
+
}
|
|
895
|
+
if (granted.length === 0) {
|
|
896
|
+
this._log.debug(`Already subscribed to: ${topic}`)
|
|
897
|
+
}
|
|
898
|
+
resolve()
|
|
899
899
|
}
|
|
900
900
|
}
|
|
901
|
-
|
|
902
|
-
)
|
|
901
|
+
)
|
|
902
|
+
})
|
|
903
903
|
}
|
|
904
904
|
|
|
905
|
-
_mqttUnsubscribe (topic, options) {
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
905
|
+
async _mqttUnsubscribe (topic, options) {
|
|
906
|
+
return new Promise((resolve, reject) => {
|
|
907
|
+
this._client.unsubscribe(topic, options, err => {
|
|
908
|
+
if (err) {
|
|
909
|
+
this._log.warn(
|
|
910
|
+
`Could not unsubscribe from topic: ${topic} because: ${err.message}`
|
|
911
|
+
)
|
|
912
|
+
}
|
|
913
|
+
// we resolve in any case to let the upstream logic flow
|
|
914
|
+
resolve()
|
|
915
|
+
})
|
|
912
916
|
})
|
|
913
917
|
}
|
|
914
918
|
|
|
@@ -1001,7 +1005,7 @@ class VrpcClient extends EventEmitter {
|
|
|
1001
1005
|
const id = `__e__${topic}`
|
|
1002
1006
|
if (this._cachedSubscriptions[topic]) {
|
|
1003
1007
|
this._eventEmitter.removeAllListeners(id)
|
|
1004
|
-
this._mqttUnsubscribe(topic)
|
|
1008
|
+
await this._mqttUnsubscribe(topic)
|
|
1005
1009
|
delete this._cachedSubscriptions[topic]
|
|
1006
1010
|
}
|
|
1007
1011
|
try {
|
|
@@ -1029,7 +1033,7 @@ class VrpcClient extends EventEmitter {
|
|
|
1029
1033
|
return
|
|
1030
1034
|
}
|
|
1031
1035
|
proxy[functionName] = async (...args) => {
|
|
1032
|
-
const wrapped = this._wrapArguments({
|
|
1036
|
+
const wrapped = await this._wrapArguments({
|
|
1033
1037
|
agent,
|
|
1034
1038
|
className,
|
|
1035
1039
|
instance,
|
|
@@ -1064,7 +1068,7 @@ class VrpcClient extends EventEmitter {
|
|
|
1064
1068
|
if (!uniqueFuncs.has('vrpcOn') && !uniqueFuncs.has('vrpcOff')) {
|
|
1065
1069
|
proxy.vrpcOn = async (functionName, ...args) => {
|
|
1066
1070
|
if (!uniqueFuncs.has(functionName)) throw new Error('Bad magic')
|
|
1067
|
-
const wrapped = this._wrapArguments({
|
|
1071
|
+
const wrapped = await this._wrapArguments({
|
|
1068
1072
|
agent,
|
|
1069
1073
|
className,
|
|
1070
1074
|
instance,
|
|
@@ -1169,7 +1173,14 @@ class VrpcClient extends EventEmitter {
|
|
|
1169
1173
|
})
|
|
1170
1174
|
}
|
|
1171
1175
|
|
|
1172
|
-
_wrapArguments ({
|
|
1176
|
+
async _wrapArguments ({
|
|
1177
|
+
agent,
|
|
1178
|
+
className,
|
|
1179
|
+
instance,
|
|
1180
|
+
proxyId,
|
|
1181
|
+
functionName,
|
|
1182
|
+
args
|
|
1183
|
+
}) {
|
|
1173
1184
|
const wrapped = []
|
|
1174
1185
|
for (const [i, x] of args.entries()) {
|
|
1175
1186
|
// Check whether provided argument is a function
|
|
@@ -1185,7 +1196,7 @@ class VrpcClient extends EventEmitter {
|
|
|
1185
1196
|
// 2) callback is second argument
|
|
1186
1197
|
// 3) first argument was string
|
|
1187
1198
|
const event = args[0]
|
|
1188
|
-
const id = this._onRemoteEvent({
|
|
1199
|
+
const id = await this._onRemoteEvent({
|
|
1189
1200
|
agent,
|
|
1190
1201
|
className,
|
|
1191
1202
|
instance,
|
|
@@ -1200,7 +1211,7 @@ class VrpcClient extends EventEmitter {
|
|
|
1200
1211
|
typeof args[0] === 'string'
|
|
1201
1212
|
) {
|
|
1202
1213
|
const event = args[0]
|
|
1203
|
-
const id = this._offRemoteEvent({
|
|
1214
|
+
const id = await this._offRemoteEvent({
|
|
1204
1215
|
agent,
|
|
1205
1216
|
className,
|
|
1206
1217
|
instance,
|
|
@@ -1235,7 +1246,7 @@ class VrpcClient extends EventEmitter {
|
|
|
1235
1246
|
this._emitterListener.set(emitter, new Map([[event, callback]]))
|
|
1236
1247
|
}
|
|
1237
1248
|
|
|
1238
|
-
const id = this._onRemoteEvent({
|
|
1249
|
+
const id = await this._onRemoteEvent({
|
|
1239
1250
|
agent,
|
|
1240
1251
|
className,
|
|
1241
1252
|
instance,
|
|
@@ -1251,7 +1262,7 @@ class VrpcClient extends EventEmitter {
|
|
|
1251
1262
|
return wrapped
|
|
1252
1263
|
}
|
|
1253
1264
|
|
|
1254
|
-
_onRemoteEvent ({ agent, className, instance, event, callback }) {
|
|
1265
|
+
async _onRemoteEvent ({ agent, className, instance, event, callback }) {
|
|
1255
1266
|
const callbackId = this._getCallbackId(callback)
|
|
1256
1267
|
const eventCallback = `${event}-${callbackId}`
|
|
1257
1268
|
|
|
@@ -1261,10 +1272,15 @@ class VrpcClient extends EventEmitter {
|
|
|
1261
1272
|
: `${this._domain}/${agent}/${className}/${eventCallback}`
|
|
1262
1273
|
|
|
1263
1274
|
// prepare a special id for the agent to know that events should be
|
|
1264
|
-
// published to the provided topic after the prefix
|
|
1275
|
+
// published to the provided topic after the prefix
|
|
1265
1276
|
|
|
1266
1277
|
const id = `__e__${topic}`
|
|
1267
1278
|
|
|
1279
|
+
// If a subscription for this topic is already in progress, wait for it to finish.
|
|
1280
|
+
if (this._pendingSubscriptions.has(topic)) {
|
|
1281
|
+
await this._pendingSubscriptions.get(topic)
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1268
1284
|
// call our proxy callback when remote events were received
|
|
1269
1285
|
const handler = ({ a }) => callback.apply(null, a)
|
|
1270
1286
|
if (this._eventEmitter.listenerCount(id) === 0) {
|
|
@@ -1272,19 +1288,29 @@ class VrpcClient extends EventEmitter {
|
|
|
1272
1288
|
}
|
|
1273
1289
|
if (!this._cachedSubscriptions[topic]) {
|
|
1274
1290
|
// when not yet subscribed to this topic do it now
|
|
1275
|
-
this._mqttSubscribe(topic)
|
|
1276
|
-
this.
|
|
1277
|
-
|
|
1291
|
+
const subscribePromise = this._mqttSubscribe(topic)
|
|
1292
|
+
this._pendingSubscriptions.set(topic, subscribePromise) // set lock
|
|
1293
|
+
|
|
1294
|
+
try {
|
|
1295
|
+
await subscribePromise
|
|
1296
|
+
this._cachedSubscriptions[topic] = [{ callback, handler }]
|
|
1297
|
+
} finally {
|
|
1298
|
+
this._pendingSubscriptions.delete(topic) // release lock
|
|
1299
|
+
}
|
|
1300
|
+
} else {
|
|
1301
|
+
// otherwise just add the new callback-handler pair
|
|
1302
|
+
this._cachedSubscriptions[topic].push({ callback, handler })
|
|
1278
1303
|
}
|
|
1279
|
-
// otherwise just add the new callback-handler pair
|
|
1280
|
-
this._cachedSubscriptions[topic].push({ callback, handler })
|
|
1281
1304
|
return id
|
|
1282
1305
|
}
|
|
1283
1306
|
|
|
1284
|
-
_offRemoteEvent ({ agent, className, instance, event, callback }) {
|
|
1307
|
+
async _offRemoteEvent ({ agent, className, instance, event, callback }) {
|
|
1285
1308
|
const callbackId = this._getCallbackId(callback, {
|
|
1286
1309
|
readOnly: true
|
|
1287
1310
|
})
|
|
1311
|
+
// If the callback was never registered, we can't do anything.
|
|
1312
|
+
if (!callbackId) return null
|
|
1313
|
+
|
|
1288
1314
|
const eventCallback = `${event}-${callbackId}`
|
|
1289
1315
|
const topic = instance
|
|
1290
1316
|
? `${this._domain}/${agent}/${className}/${instance}:${eventCallback}`
|
|
@@ -1292,6 +1318,10 @@ class VrpcClient extends EventEmitter {
|
|
|
1292
1318
|
|
|
1293
1319
|
const id = `__e__${topic}`
|
|
1294
1320
|
|
|
1321
|
+
if (this._pendingUnsubscriptions.has(topic)) {
|
|
1322
|
+
await this._pendingUnsubscriptions.get(topic)
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1295
1325
|
if (this._cachedSubscriptions[topic]) {
|
|
1296
1326
|
const index = this._cachedSubscriptions[topic].findIndex(
|
|
1297
1327
|
x => x.callback === callback
|
|
@@ -1302,16 +1332,21 @@ class VrpcClient extends EventEmitter {
|
|
|
1302
1332
|
}
|
|
1303
1333
|
const [{ handler }] = this._cachedSubscriptions[topic].splice(index, 1)
|
|
1304
1334
|
if (this._cachedSubscriptions[topic].length === 0) {
|
|
1305
|
-
this._eventEmitter.removeListener(id, handler)
|
|
1306
|
-
this._mqttUnsubscribe(topic)
|
|
1307
1335
|
delete this._cachedSubscriptions[topic]
|
|
1308
|
-
|
|
1336
|
+
const unsubscribePromise = this._mqttUnsubscribe(topic)
|
|
1337
|
+
this._pendingUnsubscriptions.set(topic, unsubscribePromise) // set lock
|
|
1338
|
+
|
|
1339
|
+
try {
|
|
1340
|
+
await unsubscribePromise
|
|
1341
|
+
this._eventEmitter.removeListener(id, handler)
|
|
1342
|
+
} finally {
|
|
1343
|
+
this._pendingUnsubscriptions.delete(topic) // release lock
|
|
1344
|
+
}
|
|
1345
|
+
} else {
|
|
1346
|
+
this._log.warn(`Can not unsubscribe from non-existing event: ${event}`)
|
|
1309
1347
|
}
|
|
1310
1348
|
return id
|
|
1311
|
-
} else {
|
|
1312
|
-
this._log.warn(`Can not unsubscribe from non-existing event: ${event}`)
|
|
1313
1349
|
}
|
|
1314
|
-
return id
|
|
1315
1350
|
}
|
|
1316
1351
|
|
|
1317
1352
|
_clearCachedSubscriptions ({ lostAgent, lostInstance }) {
|
|
@@ -1327,11 +1362,12 @@ class VrpcClient extends EventEmitter {
|
|
|
1327
1362
|
)
|
|
1328
1363
|
obsoleteTopics.forEach(topic => {
|
|
1329
1364
|
const id = `__e__${topic}`
|
|
1330
|
-
this._log.
|
|
1365
|
+
this._log.debug(`Clearing subscriptions for obsolete topic: ${topic}`)
|
|
1331
1366
|
const subscriptions = this._cachedSubscriptions[topic]
|
|
1332
1367
|
subscriptions.forEach(({ handler }) => {
|
|
1333
1368
|
this._eventEmitter.removeListener(id, handler)
|
|
1334
1369
|
})
|
|
1370
|
+
// this async function will never reject
|
|
1335
1371
|
this._mqttUnsubscribe(topic)
|
|
1336
1372
|
delete this._cachedSubscriptions[topic]
|
|
1337
1373
|
})
|