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