@webex/plugin-meetings 3.11.0-next.24 → 3.11.0-next.26

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.
@@ -209,7 +209,7 @@ var Breakout = _webexCore.WebexPlugin.extend({
209
209
  sessionId: this.sessionId
210
210
  });
211
211
  },
212
- version: "3.11.0-next.24"
212
+ version: "3.11.0-next.26"
213
213
  });
214
214
  var _default = exports.default = Breakout;
215
215
  //# sourceMappingURL=breakout.js.map
@@ -1109,7 +1109,7 @@ var Breakouts = _webexCore.WebexPlugin.extend({
1109
1109
  this.trigger(_constants.BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1110
1110
  }
1111
1111
  },
1112
- version: "3.11.0-next.24"
1112
+ version: "3.11.0-next.26"
1113
1113
  });
1114
1114
  var _default = exports.default = Breakouts;
1115
1115
  //# sourceMappingURL=index.js.map
@@ -87,6 +87,7 @@ var HashTreeParser = /*#__PURE__*/function () {
87
87
  (0, _defineProperty2.default)(this, "locusInfoUpdateCallback", void 0);
88
88
  (0, _defineProperty2.default)(this, "visibleDataSets", void 0);
89
89
  (0, _defineProperty2.default)(this, "debugId", void 0);
90
+ (0, _defineProperty2.default)(this, "heartbeatIntervalMs", void 0);
90
91
  var _options$initialLocus = options.initialLocus,
91
92
  dataSets = _options$initialLocus.dataSets,
92
93
  locus = _options$initialLocus.locus; // extract dataSets from initialLocus
@@ -763,11 +764,15 @@ var HashTreeParser = /*#__PURE__*/function () {
763
764
  value: function deleteHashTree(dataSetName) {
764
765
  this.dataSets[dataSetName].hashTree = undefined;
765
766
 
766
- // we also need to stop the timer as there is no hash tree anymore to sync
767
+ // we also need to stop the timers as there is no hash tree anymore to sync
767
768
  if (this.dataSets[dataSetName].timer) {
768
769
  clearTimeout(this.dataSets[dataSetName].timer);
769
770
  this.dataSets[dataSetName].timer = undefined;
770
771
  }
772
+ if (this.dataSets[dataSetName].heartbeatWatchdogTimer) {
773
+ clearTimeout(this.dataSets[dataSetName].heartbeatWatchdogTimer);
774
+ this.dataSets[dataSetName].heartbeatWatchdogTimer = undefined;
775
+ }
771
776
  }
772
777
 
773
778
  /**
@@ -1103,11 +1108,15 @@ var HashTreeParser = /*#__PURE__*/function () {
1103
1108
  return _regenerator.default.wrap(function (_context7) {
1104
1109
  while (1) switch (_context7.prev = _context7.next) {
1105
1110
  case 0:
1111
+ if (message.heartbeatIntervalMs) {
1112
+ this.heartbeatIntervalMs = message.heartbeatIntervalMs;
1113
+ }
1106
1114
  if (!(message.locusStateElements === undefined)) {
1107
1115
  _context7.next = 1;
1108
1116
  break;
1109
1117
  }
1110
1118
  this.handleRootHashHeartBeatMessage(message);
1119
+ this.resetHeartbeatWatchdogs(message.dataSets);
1111
1120
  _context7.next = 3;
1112
1121
  break;
1113
1122
  case 1:
@@ -1115,6 +1124,10 @@ var HashTreeParser = /*#__PURE__*/function () {
1115
1124
  return this.parseMessage(message, debugText);
1116
1125
  case 2:
1117
1126
  updates = _context7.sent;
1127
+ // Only reset watchdogs if the meeting hasn't ended
1128
+ if (updates.updateType !== LocusInfoUpdateType.MEETING_ENDED) {
1129
+ this.resetHeartbeatWatchdogs(message.dataSets);
1130
+ }
1118
1131
  this.callLocusInfoUpdateCallback(updates);
1119
1132
  case 3:
1120
1133
  case "end":
@@ -1201,12 +1214,99 @@ var HashTreeParser = /*#__PURE__*/function () {
1201
1214
  return Math.round(Math.pow(randomValue, exponent) * maxMs);
1202
1215
  }
1203
1216
 
1217
+ /**
1218
+ * Performs a sync for the given data set.
1219
+ *
1220
+ * @param {InternalDataSet} dataSet - The data set to sync
1221
+ * @param {string} rootHash - Our current root hash for this data set
1222
+ * @param {string} reason - The reason for the sync (used for logging)
1223
+ * @returns {Promise<void>}
1224
+ */
1225
+ }, {
1226
+ key: "performSync",
1227
+ value: (function () {
1228
+ var _performSync = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee7(dataSet, rootHash, reason) {
1229
+ var mismatchedLeavesData, receivedHashes, _yield$this$getHashes, hashes, latestDataSetInfo, mismatchedLeaveIndexes, syncResponse, _t3;
1230
+ return _regenerator.default.wrap(function (_context8) {
1231
+ while (1) switch (_context8.prev = _context8.next) {
1232
+ case 0:
1233
+ if (dataSet.hashTree) {
1234
+ _context8.next = 1;
1235
+ break;
1236
+ }
1237
+ return _context8.abrupt("return");
1238
+ case 1:
1239
+ _loggerProxy.default.logger.info("HashTreeParser#performSync --> ".concat(this.debugId, " ").concat(reason, ", syncing data set \"").concat(dataSet.name, "\""));
1240
+ mismatchedLeavesData = {};
1241
+ if (!(dataSet.leafCount !== 1)) {
1242
+ _context8.next = 7;
1243
+ break;
1244
+ }
1245
+ _context8.prev = 2;
1246
+ _context8.next = 3;
1247
+ return this.getHashesFromLocus(dataSet.name, rootHash);
1248
+ case 3:
1249
+ _yield$this$getHashes = _context8.sent;
1250
+ hashes = _yield$this$getHashes.hashes;
1251
+ latestDataSetInfo = _yield$this$getHashes.dataSet;
1252
+ receivedHashes = hashes;
1253
+ dataSet.hashTree.resize(latestDataSetInfo.leafCount);
1254
+ _context8.next = 6;
1255
+ break;
1256
+ case 4:
1257
+ _context8.prev = 4;
1258
+ _t3 = _context8["catch"](2);
1259
+ if (!(_t3.statusCode === 409)) {
1260
+ _context8.next = 5;
1261
+ break;
1262
+ }
1263
+ // this is a leaf count mismatch, we should do nothing, just wait for another heartbeat message from Locus
1264
+ _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(this.debugId, " Got 409 when fetching hashes for data set \"").concat(dataSet.name, "\": ").concat(_t3.message));
1265
+ return _context8.abrupt("return");
1266
+ case 5:
1267
+ throw _t3;
1268
+ case 6:
1269
+ // identify mismatched leaves
1270
+ mismatchedLeaveIndexes = dataSet.hashTree.diffHashes(receivedHashes);
1271
+ mismatchedLeaveIndexes.forEach(function (index) {
1272
+ mismatchedLeavesData[index] = dataSet.hashTree.getLeafData(index);
1273
+ });
1274
+ _context8.next = 8;
1275
+ break;
1276
+ case 7:
1277
+ mismatchedLeavesData[0] = dataSet.hashTree.getLeafData(0);
1278
+ case 8:
1279
+ if (!((0, _keys.default)(mismatchedLeavesData).length > 0)) {
1280
+ _context8.next = 10;
1281
+ break;
1282
+ }
1283
+ _context8.next = 9;
1284
+ return this.sendSyncRequestToLocus(dataSet, mismatchedLeavesData);
1285
+ case 9:
1286
+ syncResponse = _context8.sent;
1287
+ // sync API may return nothing (in that case data will arrive via messages)
1288
+ // or it may return a response in the same format as messages
1289
+ if (syncResponse) {
1290
+ this.handleMessage(syncResponse, 'via sync API');
1291
+ }
1292
+ case 10:
1293
+ case "end":
1294
+ return _context8.stop();
1295
+ }
1296
+ }, _callee7, this, [[2, 4]]);
1297
+ }));
1298
+ function performSync(_x0, _x1, _x10) {
1299
+ return _performSync.apply(this, arguments);
1300
+ }
1301
+ return performSync;
1302
+ }()
1204
1303
  /**
1205
1304
  * Runs the sync algorithm for the given data set.
1206
1305
  *
1207
1306
  * @param {DataSet} receivedDataSet - The data set to run the sync algorithm for.
1208
1307
  * @returns {void}
1209
1308
  */
1309
+ )
1210
1310
  }, {
1211
1311
  key: "runSyncAlgorithm",
1212
1312
  value: function runSyncAlgorithm(receivedDataSet) {
@@ -1231,93 +1331,99 @@ var HashTreeParser = /*#__PURE__*/function () {
1231
1331
  clearTimeout(dataSet.timer);
1232
1332
  }
1233
1333
  _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " setting \"").concat(dataSet.name, "\" sync timer for ").concat(delay));
1234
- dataSet.timer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee7() {
1235
- var rootHash, mismatchedLeavesData, receivedHashes, _yield$_this0$getHash, hashes, latestDataSetInfo, mismatchedLeaveIndexes, syncResponse, _t3;
1236
- return _regenerator.default.wrap(function (_context8) {
1237
- while (1) switch (_context8.prev = _context8.next) {
1334
+ dataSet.timer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee8() {
1335
+ var rootHash;
1336
+ return _regenerator.default.wrap(function (_context9) {
1337
+ while (1) switch (_context9.prev = _context9.next) {
1238
1338
  case 0:
1239
1339
  dataSet.timer = undefined;
1240
1340
  if (dataSet.hashTree) {
1241
- _context8.next = 1;
1341
+ _context9.next = 1;
1242
1342
  break;
1243
1343
  }
1244
1344
  _loggerProxy.default.logger.warn("HashTreeParser#runSyncAlgorithm --> ".concat(_this0.debugId, " Data set \"").concat(dataSet.name, "\" no longer has a hash tree, cannot run sync algorithm"));
1245
- return _context8.abrupt("return");
1345
+ return _context9.abrupt("return");
1246
1346
  case 1:
1247
1347
  rootHash = dataSet.hashTree.getRootHash();
1248
1348
  if (!(dataSet.root !== rootHash)) {
1249
- _context8.next = 11;
1349
+ _context9.next = 3;
1250
1350
  break;
1251
1351
  }
1252
- _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(_this0.debugId, " Root hash mismatch: received=").concat(dataSet.root, ", ours=").concat(rootHash, ", syncing data set \"").concat(dataSet.name, "\""));
1253
- mismatchedLeavesData = {};
1254
- if (!(dataSet.leafCount !== 1)) {
1255
- _context8.next = 7;
1256
- break;
1257
- }
1258
- _context8.prev = 2;
1259
- _context8.next = 3;
1260
- return _this0.getHashesFromLocus(dataSet.name, rootHash);
1261
- case 3:
1262
- _yield$_this0$getHash = _context8.sent;
1263
- hashes = _yield$_this0$getHash.hashes;
1264
- latestDataSetInfo = _yield$_this0$getHash.dataSet;
1265
- receivedHashes = hashes;
1266
- dataSet.hashTree.resize(latestDataSetInfo.leafCount);
1267
- _context8.next = 6;
1268
- break;
1269
- case 4:
1270
- _context8.prev = 4;
1271
- _t3 = _context8["catch"](2);
1272
- if (!(_t3.statusCode === 409)) {
1273
- _context8.next = 5;
1274
- break;
1275
- }
1276
- // this is a leaf count mismatch, we should do nothing, just wait for another heartbeat message from Locus
1277
- _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this0.debugId, " Got 409 when fetching hashes for data set \"").concat(dataSet.name, "\": ").concat(_t3.message));
1278
- return _context8.abrupt("return");
1279
- case 5:
1280
- throw _t3;
1281
- case 6:
1282
- // identify mismatched leaves
1283
- mismatchedLeaveIndexes = dataSet.hashTree.diffHashes(receivedHashes);
1284
- mismatchedLeaveIndexes.forEach(function (index) {
1285
- mismatchedLeavesData[index] = dataSet.hashTree.getLeafData(index);
1286
- });
1287
- _context8.next = 8;
1352
+ _context9.next = 2;
1353
+ return _this0.performSync(dataSet, rootHash, "Root hash mismatch: received=".concat(dataSet.root, ", ours=").concat(rootHash));
1354
+ case 2:
1355
+ _context9.next = 4;
1288
1356
  break;
1289
- case 7:
1290
- mismatchedLeavesData[0] = dataSet.hashTree.getLeafData(0);
1291
- case 8:
1292
- if (!((0, _keys.default)(mismatchedLeavesData).length > 0)) {
1293
- _context8.next = 10;
1294
- break;
1295
- }
1296
- _context8.next = 9;
1297
- return _this0.sendSyncRequestToLocus(dataSet, mismatchedLeavesData);
1298
- case 9:
1299
- syncResponse = _context8.sent;
1300
- // sync API may return nothing (in that case data will arrive via messages)
1301
- // or it may return a response in the same format as messages
1302
- if (syncResponse) {
1303
- _this0.handleMessage(syncResponse, 'via sync API');
1304
- }
1305
- case 10:
1306
- _context8.next = 12;
1307
- break;
1308
- case 11:
1357
+ case 3:
1309
1358
  _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(_this0.debugId, " \"").concat(dataSet.name, "\" root hash matching: ").concat(rootHash, ", version=").concat(dataSet.version));
1310
- case 12:
1359
+ case 4:
1311
1360
  case "end":
1312
- return _context8.stop();
1361
+ return _context9.stop();
1313
1362
  }
1314
- }, _callee7, null, [[2, 4]]);
1363
+ }, _callee8);
1315
1364
  })), delay);
1316
1365
  } else {
1317
1366
  _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " No delay for \"").concat(dataSet.name, "\" data set, skipping sync timer reset/setup"));
1318
1367
  }
1319
1368
  }
1320
1369
 
1370
+ /**
1371
+ * Resets the heartbeat watchdog timers for the specified data sets. Each data set has its own
1372
+ * watchdog timer that monitors whether heartbeats are being received within the expected interval.
1373
+ * If a heartbeat is not received for a specific data set within heartbeatIntervalMs plus
1374
+ * a backoff-calculated time, the sync algorithm is initiated for that data set
1375
+ *
1376
+ * @param {Array<DataSet>} receivedDataSets - The data sets from the received message for which watchdog timers should be reset
1377
+ * @returns {void}
1378
+ */
1379
+ }, {
1380
+ key: "resetHeartbeatWatchdogs",
1381
+ value: function resetHeartbeatWatchdogs(receivedDataSets) {
1382
+ var _this1 = this;
1383
+ if (!this.heartbeatIntervalMs) {
1384
+ return;
1385
+ }
1386
+ var _iterator9 = _createForOfIteratorHelper(receivedDataSets),
1387
+ _step9;
1388
+ try {
1389
+ var _loop2 = function _loop2() {
1390
+ var receivedDataSet = _step9.value;
1391
+ var dataSet = _this1.dataSets[receivedDataSet.name];
1392
+ if (!(dataSet !== null && dataSet !== void 0 && dataSet.hashTree)) {
1393
+ // eslint-disable-next-line no-continue
1394
+ return 1; // continue
1395
+ }
1396
+ if (dataSet.heartbeatWatchdogTimer) {
1397
+ clearTimeout(dataSet.heartbeatWatchdogTimer);
1398
+ dataSet.heartbeatWatchdogTimer = undefined;
1399
+ }
1400
+ var backoffTime = _this1.getWeightedBackoffTime(dataSet.backoff);
1401
+ var delay = _this1.heartbeatIntervalMs + backoffTime;
1402
+ dataSet.heartbeatWatchdogTimer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee9() {
1403
+ return _regenerator.default.wrap(function (_context0) {
1404
+ while (1) switch (_context0.prev = _context0.next) {
1405
+ case 0:
1406
+ dataSet.heartbeatWatchdogTimer = undefined;
1407
+ _loggerProxy.default.logger.warn("HashTreeParser#resetHeartbeatWatchdogs --> ".concat(_this1.debugId, " Heartbeat watchdog fired for data set \"").concat(dataSet.name, "\" - no heartbeat received within expected interval, initiating sync"));
1408
+ _context0.next = 1;
1409
+ return _this1.performSync(dataSet, dataSet.hashTree.getRootHash(), "heartbeat watchdog expired");
1410
+ case 1:
1411
+ case "end":
1412
+ return _context0.stop();
1413
+ }
1414
+ }, _callee9);
1415
+ })), delay);
1416
+ };
1417
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
1418
+ if (_loop2()) continue;
1419
+ }
1420
+ } catch (err) {
1421
+ _iterator9.e(err);
1422
+ } finally {
1423
+ _iterator9.f();
1424
+ }
1425
+ }
1426
+
1321
1427
  /**
1322
1428
  * Stops all timers for the data sets to prevent any further sync attempts.
1323
1429
  * @returns {void}
@@ -1330,6 +1436,10 @@ var HashTreeParser = /*#__PURE__*/function () {
1330
1436
  clearTimeout(dataSet.timer);
1331
1437
  dataSet.timer = undefined;
1332
1438
  }
1439
+ if (dataSet.heartbeatWatchdogTimer) {
1440
+ clearTimeout(dataSet.heartbeatWatchdogTimer);
1441
+ dataSet.heartbeatWatchdogTimer = undefined;
1442
+ }
1333
1443
  });
1334
1444
  }
1335
1445
 
@@ -1342,7 +1452,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1342
1452
  }, {
1343
1453
  key: "getHashesFromLocus",
1344
1454
  value: function getHashesFromLocus(dataSetName, currentRootHash) {
1345
- var _this1 = this;
1455
+ var _this10 = this;
1346
1456
  _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(this.debugId, " Requesting hashes for data set \"").concat(dataSetName, "\""));
1347
1457
  var dataSet = this.dataSets[dataSetName];
1348
1458
  var url = "".concat(dataSet.url, "/hashtree");
@@ -1357,16 +1467,16 @@ var HashTreeParser = /*#__PURE__*/function () {
1357
1467
  var hashes = (_response$body = response.body) === null || _response$body === void 0 ? void 0 : _response$body.hashes;
1358
1468
  var dataSetFromResponse = (_response$body2 = response.body) === null || _response$body2 === void 0 ? void 0 : _response$body2.dataSet;
1359
1469
  if (!hashes || !(0, _isArray.default)(hashes)) {
1360
- _loggerProxy.default.logger.warn("HashTreeParser#getHashesFromLocus --> ".concat(_this1.debugId, " Locus returned invalid hashes, response body="), response.body);
1470
+ _loggerProxy.default.logger.warn("HashTreeParser#getHashesFromLocus --> ".concat(_this10.debugId, " Locus returned invalid hashes, response body="), response.body);
1361
1471
  throw new Error("Locus returned invalid hashes: ".concat(hashes));
1362
1472
  }
1363
- _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this1.debugId, " Received hashes for data set \"").concat(dataSetName, "\": ").concat((0, _stringify.default)(hashes)));
1473
+ _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this10.debugId, " Received hashes for data set \"").concat(dataSetName, "\": ").concat((0, _stringify.default)(hashes)));
1364
1474
  return {
1365
1475
  hashes: hashes,
1366
1476
  dataSet: dataSetFromResponse
1367
1477
  };
1368
1478
  }).catch(function (error) {
1369
- _loggerProxy.default.logger.error("HashTreeParser#getHashesFromLocus --> ".concat(_this1.debugId, " Error ").concat(error.statusCode, " fetching hashes for data set \"").concat(dataSetName, "\":"), error);
1479
+ _loggerProxy.default.logger.error("HashTreeParser#getHashesFromLocus --> ".concat(_this10.debugId, " Error ").concat(error.statusCode, " fetching hashes for data set \"").concat(dataSetName, "\":"), error);
1370
1480
  throw error;
1371
1481
  });
1372
1482
  }
@@ -1381,7 +1491,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1381
1491
  }, {
1382
1492
  key: "sendSyncRequestToLocus",
1383
1493
  value: function sendSyncRequestToLocus(dataSet, mismatchedLeavesData) {
1384
- var _this10 = this;
1494
+ var _this11 = this;
1385
1495
  _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(this.debugId, " Sending sync request for data set \"").concat(dataSet.name, "\""));
1386
1496
  var url = "".concat(dataSet.url, "/sync");
1387
1497
  var body = {
@@ -1403,14 +1513,14 @@ var HashTreeParser = /*#__PURE__*/function () {
1403
1513
  },
1404
1514
  body: body
1405
1515
  }).then(function (resp) {
1406
- _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this10.debugId, " Sync request succeeded for \"").concat(dataSet.name, "\""));
1516
+ _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this11.debugId, " Sync request succeeded for \"").concat(dataSet.name, "\""));
1407
1517
  if (!resp.body || (0, _lodash.isEmpty)(resp.body)) {
1408
- _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this10.debugId, " Got ").concat(resp.statusCode, " with empty body for sync request for data set \"").concat(dataSet.name, "\", data should arrive via messages"));
1518
+ _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this11.debugId, " Got ").concat(resp.statusCode, " with empty body for sync request for data set \"").concat(dataSet.name, "\", data should arrive via messages"));
1409
1519
  return null;
1410
1520
  }
1411
1521
  return resp.body;
1412
1522
  }).catch(function (error) {
1413
- _loggerProxy.default.logger.error("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this10.debugId, " Error ").concat(error.statusCode, " sending sync request for data set \"").concat(dataSet.name, "\":"), error);
1523
+ _loggerProxy.default.logger.error("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this11.debugId, " Error ").concat(error.statusCode, " sending sync request for data set \"").concat(dataSet.name, "\":"), error);
1414
1524
  throw error;
1415
1525
  });
1416
1526
  }