@webex/plugin-meetings 3.12.0-next.5 → 3.12.0-next.50

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.
Files changed (136) hide show
  1. package/AGENTS.md +9 -0
  2. package/dist/aiEnableRequest/index.js +15 -2
  3. package/dist/aiEnableRequest/index.js.map +1 -1
  4. package/dist/breakouts/breakout.js +6 -2
  5. package/dist/breakouts/breakout.js.map +1 -1
  6. package/dist/breakouts/index.js +1 -1
  7. package/dist/config.js +1 -0
  8. package/dist/config.js.map +1 -1
  9. package/dist/constants.js +6 -3
  10. package/dist/constants.js.map +1 -1
  11. package/dist/controls-options-manager/constants.js +11 -1
  12. package/dist/controls-options-manager/constants.js.map +1 -1
  13. package/dist/controls-options-manager/index.js +38 -24
  14. package/dist/controls-options-manager/index.js.map +1 -1
  15. package/dist/controls-options-manager/util.js +91 -0
  16. package/dist/controls-options-manager/util.js.map +1 -1
  17. package/dist/hashTree/constants.js +10 -1
  18. package/dist/hashTree/constants.js.map +1 -1
  19. package/dist/hashTree/hashTreeParser.js +593 -358
  20. package/dist/hashTree/hashTreeParser.js.map +1 -1
  21. package/dist/hashTree/utils.js +22 -0
  22. package/dist/hashTree/utils.js.map +1 -1
  23. package/dist/index.js +7 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/interceptors/locusRetry.js +23 -8
  26. package/dist/interceptors/locusRetry.js.map +1 -1
  27. package/dist/interpretation/index.js +10 -1
  28. package/dist/interpretation/index.js.map +1 -1
  29. package/dist/interpretation/siLanguage.js +1 -1
  30. package/dist/locus-info/controlsUtils.js +4 -1
  31. package/dist/locus-info/controlsUtils.js.map +1 -1
  32. package/dist/locus-info/index.js +277 -86
  33. package/dist/locus-info/index.js.map +1 -1
  34. package/dist/locus-info/types.js +16 -0
  35. package/dist/locus-info/types.js.map +1 -1
  36. package/dist/media/properties.js +1 -0
  37. package/dist/media/properties.js.map +1 -1
  38. package/dist/meeting/in-meeting-actions.js +3 -1
  39. package/dist/meeting/in-meeting-actions.js.map +1 -1
  40. package/dist/meeting/index.js +842 -521
  41. package/dist/meeting/index.js.map +1 -1
  42. package/dist/meeting/util.js +19 -2
  43. package/dist/meeting/util.js.map +1 -1
  44. package/dist/meetings/index.js +199 -77
  45. package/dist/meetings/index.js.map +1 -1
  46. package/dist/meetings/meetings.types.js +6 -1
  47. package/dist/meetings/meetings.types.js.map +1 -1
  48. package/dist/meetings/request.js +39 -0
  49. package/dist/meetings/request.js.map +1 -1
  50. package/dist/meetings/util.js +67 -5
  51. package/dist/meetings/util.js.map +1 -1
  52. package/dist/member/index.js +10 -0
  53. package/dist/member/index.js.map +1 -1
  54. package/dist/member/types.js.map +1 -1
  55. package/dist/member/util.js +3 -0
  56. package/dist/member/util.js.map +1 -1
  57. package/dist/metrics/constants.js +2 -1
  58. package/dist/metrics/constants.js.map +1 -1
  59. package/dist/recording-controller/index.js +1 -3
  60. package/dist/recording-controller/index.js.map +1 -1
  61. package/dist/types/config.d.ts +1 -0
  62. package/dist/types/constants.d.ts +2 -0
  63. package/dist/types/controls-options-manager/constants.d.ts +6 -1
  64. package/dist/types/controls-options-manager/index.d.ts +10 -0
  65. package/dist/types/hashTree/constants.d.ts +1 -0
  66. package/dist/types/hashTree/hashTreeParser.d.ts +61 -15
  67. package/dist/types/hashTree/utils.d.ts +11 -0
  68. package/dist/types/index.d.ts +2 -0
  69. package/dist/types/interceptors/locusRetry.d.ts +4 -4
  70. package/dist/types/locus-info/index.d.ts +46 -6
  71. package/dist/types/locus-info/types.d.ts +17 -1
  72. package/dist/types/media/properties.d.ts +1 -0
  73. package/dist/types/meeting/in-meeting-actions.d.ts +2 -0
  74. package/dist/types/meeting/index.d.ts +70 -1
  75. package/dist/types/meeting/util.d.ts +8 -0
  76. package/dist/types/meetings/index.d.ts +18 -1
  77. package/dist/types/meetings/meetings.types.d.ts +15 -0
  78. package/dist/types/meetings/request.d.ts +14 -0
  79. package/dist/types/member/index.d.ts +1 -0
  80. package/dist/types/member/types.d.ts +1 -0
  81. package/dist/types/member/util.d.ts +1 -0
  82. package/dist/types/metrics/constants.d.ts +1 -0
  83. package/dist/webinar/index.js +361 -235
  84. package/dist/webinar/index.js.map +1 -1
  85. package/package.json +22 -22
  86. package/src/aiEnableRequest/index.ts +16 -0
  87. package/src/breakouts/breakout.ts +2 -1
  88. package/src/config.ts +1 -0
  89. package/src/constants.ts +5 -1
  90. package/src/controls-options-manager/constants.ts +14 -1
  91. package/src/controls-options-manager/index.ts +47 -24
  92. package/src/controls-options-manager/util.ts +81 -1
  93. package/src/hashTree/constants.ts +9 -0
  94. package/src/hashTree/hashTreeParser.ts +306 -160
  95. package/src/hashTree/utils.ts +17 -0
  96. package/src/index.ts +5 -0
  97. package/src/interceptors/locusRetry.ts +25 -4
  98. package/src/interpretation/index.ts +25 -8
  99. package/src/locus-info/controlsUtils.ts +3 -1
  100. package/src/locus-info/index.ts +276 -93
  101. package/src/locus-info/types.ts +19 -1
  102. package/src/media/properties.ts +1 -0
  103. package/src/meeting/in-meeting-actions.ts +4 -0
  104. package/src/meeting/index.ts +315 -26
  105. package/src/meeting/util.ts +20 -2
  106. package/src/meetings/index.ts +104 -43
  107. package/src/meetings/meetings.types.ts +19 -0
  108. package/src/meetings/request.ts +43 -0
  109. package/src/meetings/util.ts +80 -1
  110. package/src/member/index.ts +10 -0
  111. package/src/member/types.ts +1 -0
  112. package/src/member/util.ts +3 -0
  113. package/src/metrics/constants.ts +1 -0
  114. package/src/recording-controller/index.ts +1 -2
  115. package/src/webinar/index.ts +162 -21
  116. package/test/unit/spec/aiEnableRequest/index.ts +86 -0
  117. package/test/unit/spec/breakouts/breakout.ts +7 -3
  118. package/test/unit/spec/controls-options-manager/index.js +140 -29
  119. package/test/unit/spec/controls-options-manager/util.js +165 -0
  120. package/test/unit/spec/hashTree/hashTreeParser.ts +1294 -191
  121. package/test/unit/spec/hashTree/utils.ts +88 -1
  122. package/test/unit/spec/interceptors/locusRetry.ts +205 -4
  123. package/test/unit/spec/interpretation/index.ts +26 -4
  124. package/test/unit/spec/locus-info/controlsUtils.js +172 -57
  125. package/test/unit/spec/locus-info/index.js +443 -81
  126. package/test/unit/spec/meeting/in-meeting-actions.ts +2 -0
  127. package/test/unit/spec/meeting/index.js +836 -41
  128. package/test/unit/spec/meeting/muteState.js +3 -0
  129. package/test/unit/spec/meeting/utils.js +33 -0
  130. package/test/unit/spec/meetings/index.js +275 -10
  131. package/test/unit/spec/meetings/request.js +141 -0
  132. package/test/unit/spec/meetings/utils.js +161 -0
  133. package/test/unit/spec/member/index.js +7 -0
  134. package/test/unit/spec/member/util.js +24 -0
  135. package/test/unit/spec/recording-controller/index.js +9 -8
  136. package/test/unit/spec/webinar/index.ts +141 -16
@@ -17,15 +17,15 @@ _Object$defineProperty(exports, "__esModule", {
17
17
  });
18
18
  exports.default = exports.MeetingEndedError = exports.LocusInfoUpdateType = void 0;
19
19
  var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
20
- var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
21
20
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
21
+ var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
22
22
  var _isArray = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/array/is-array"));
23
23
  var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
24
24
  var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
25
25
  var _parseInt2 = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/parse-int"));
26
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray"));
26
27
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
27
28
  var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/typeof"));
28
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray"));
29
29
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
30
30
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
31
31
  var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
@@ -37,8 +37,11 @@ var _wrapNativeSuper2 = _interopRequireDefault(require("@babel/runtime-corejs2/h
37
37
  var _lodash = require("lodash");
38
38
  var _hashTree = _interopRequireDefault(require("./hashTree"));
39
39
  var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy"));
40
- var _constants = require("../constants");
41
- var _constants2 = require("./constants");
40
+ var _metrics = _interopRequireDefault(require("../metrics"));
41
+ var _constants = _interopRequireDefault(require("../metrics/constants"));
42
+ var _constants2 = require("../constants");
43
+ var _constants3 = require("./constants");
44
+ var _types = require("./types");
42
45
  var _utils = require("./utils");
43
46
  function ownKeys(e, r) { var t = _Object$keys4(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
44
47
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -66,8 +69,8 @@ var MeetingEndedError = exports.MeetingEndedError = /*#__PURE__*/function (_Erro
66
69
  /* Currently Locus always sends Metadata objects only in the "self" dataset.
67
70
  * If this ever changes, update all the code that relies on this constant.
68
71
  */
69
- var MetadataDataSetName = _constants2.DataSetNames.SELF;
70
- var PossibleSentinelMessageDataSetNames = [_constants2.DataSetNames.MAIN, _constants2.DataSetNames.SELF, _constants2.DataSetNames.UNJOINED];
72
+ var MetadataDataSetName = _constants3.DataSetNames.SELF;
73
+ var PossibleSentinelMessageDataSetNames = [_constants3.DataSetNames.MAIN, _constants3.DataSetNames.SELF, _constants3.DataSetNames.UNJOINED];
71
74
 
72
75
  /**
73
76
  * Parses hash tree eventing locus data
@@ -91,6 +94,10 @@ var HashTreeParser = /*#__PURE__*/function () {
91
94
  (0, _defineProperty2.default)(this, "heartbeatIntervalMs", void 0);
92
95
  (0, _defineProperty2.default)(this, "excludedDataSets", void 0);
93
96
  (0, _defineProperty2.default)(this, "state", void 0);
97
+ (0, _defineProperty2.default)(this, "syncQueue", []);
98
+ (0, _defineProperty2.default)(this, "isSyncInProgress", false);
99
+ (0, _defineProperty2.default)(this, "isSyncAllInProgress", false);
100
+ (0, _defineProperty2.default)(this, "syncQueueProcessingPromise", _promise.default.resolve());
94
101
  var _options$initialLocus = options.initialLocus,
95
102
  dataSets = _options$initialLocus.dataSets,
96
103
  locus = _options$initialLocus.locus; // extract dataSets from initialLocus
@@ -211,80 +218,65 @@ var HashTreeParser = /*#__PURE__*/function () {
211
218
  */
212
219
  }, {
213
220
  key: "initializeNewVisibleDataSet",
214
- value: function initializeNewVisibleDataSet(visibleDataSetInfo, dataSetInfo) {
215
- if (this.isVisibleDataSet(dataSetInfo.name)) {
216
- _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Data set \"").concat(dataSetInfo.name, "\" already exists, skipping init"));
217
- return _promise.default.resolve({
218
- updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
219
- updatedObjects: []
220
- });
221
- }
222
- _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Adding visible data set \"").concat(dataSetInfo.name, "\""));
223
- if (!this.addToVisibleDataSetsList(visibleDataSetInfo)) {
224
- return _promise.default.resolve({
225
- updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
226
- updatedObjects: []
227
- });
228
- }
229
- var hashTree = new _hashTree.default([], dataSetInfo.leafCount);
230
- this.dataSets[dataSetInfo.name] = _objectSpread(_objectSpread({}, dataSetInfo), {}, {
231
- hashTree: hashTree
232
- });
233
- return this.sendInitializationSyncRequestToLocus(dataSetInfo.name, 'new visible data set');
234
- }
235
-
236
- /**
237
- * Sends a special sync request to Locus with all leaves empty - this is a way to get all the data for a given dataset.
238
- *
239
- * @param {string} datasetName - name of the dataset for which to send the request
240
- * @param {string} debugText - text to include in logs
241
- * @returns {Promise}
242
- */
243
- }, {
244
- key: "sendInitializationSyncRequestToLocus",
245
- value: function sendInitializationSyncRequestToLocus(datasetName, debugText) {
246
- var _this2 = this;
247
- var dataset = this.dataSets[datasetName];
248
- if (!dataset) {
249
- _loggerProxy.default.logger.warn("HashTreeParser#sendInitializationSyncRequestToLocus --> ".concat(this.debugId, " No data set found for ").concat(datasetName, ", cannot send the request for leaf data"));
250
- return _promise.default.resolve(null);
221
+ value: (function () {
222
+ var _initializeNewVisibleDataSet = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(visibleDataSetInfo, dataSetInfo) {
223
+ var hashTree;
224
+ return _regenerator.default.wrap(function (_context) {
225
+ while (1) switch (_context.prev = _context.next) {
226
+ case 0:
227
+ if (!this.isVisibleDataSet(dataSetInfo.name)) {
228
+ _context.next = 1;
229
+ break;
230
+ }
231
+ _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Data set \"").concat(dataSetInfo.name, "\" already exists, skipping init"));
232
+ return _context.abrupt("return");
233
+ case 1:
234
+ _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Adding visible data set \"").concat(dataSetInfo.name, "\""));
235
+ if (this.addToVisibleDataSetsList(visibleDataSetInfo)) {
236
+ _context.next = 2;
237
+ break;
238
+ }
239
+ return _context.abrupt("return");
240
+ case 2:
241
+ hashTree = new _hashTree.default([], dataSetInfo.leafCount);
242
+ this.dataSets[dataSetInfo.name] = _objectSpread(_objectSpread({}, dataSetInfo), {}, {
243
+ hashTree: hashTree
244
+ });
245
+ this.enqueueSyncForDataset(dataSetInfo.name, 'new visible data set initialization', true);
246
+ _context.next = 3;
247
+ return this.syncQueueProcessingPromise;
248
+ case 3:
249
+ case "end":
250
+ return _context.stop();
251
+ }
252
+ }, _callee, this);
253
+ }));
254
+ function initializeNewVisibleDataSet(_x, _x2) {
255
+ return _initializeNewVisibleDataSet.apply(this, arguments);
251
256
  }
252
- var emptyLeavesData = new Array(dataset.leafCount).fill([]);
253
- _loggerProxy.default.logger.info("HashTreeParser#sendInitializationSyncRequestToLocus --> ".concat(this.debugId, " Sending initial sync request to Locus for data set \"").concat(datasetName, "\" with empty leaf data"));
254
- return this.sendSyncRequestToLocus(this.dataSets[datasetName], emptyLeavesData).then(function (syncResponse) {
255
- if (syncResponse) {
256
- return {
257
- updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
258
- updatedObjects: _this2.parseMessage(syncResponse, "via empty leaves /sync API call for ".concat(debugText))
259
- };
260
- }
261
- return {
262
- updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
263
- updatedObjects: []
264
- };
265
- });
266
- }
267
-
257
+ return initializeNewVisibleDataSet;
258
+ }()
268
259
  /**
269
260
  * Queries Locus for all up-to-date information about all visible data sets
270
261
  *
271
262
  * @returns {Promise}
272
263
  */
264
+ )
273
265
  }, {
274
266
  key: "getAllVisibleDataSetsFromLocus",
275
267
  value: function getAllVisibleDataSetsFromLocus() {
276
- var _this3 = this;
268
+ var _this2 = this;
277
269
  if (!this.visibleDataSetsUrl) {
278
270
  _loggerProxy.default.logger.warn("HashTreeParser#getAllVisibleDataSetsFromLocus --> ".concat(this.debugId, " No visibleDataSetsUrl, cannot get data sets information"));
279
271
  return _promise.default.resolve([]);
280
272
  }
281
273
  return this.webexRequest({
282
- method: _constants.HTTP_VERBS.GET,
274
+ method: _constants2.HTTP_VERBS.GET,
283
275
  uri: this.visibleDataSetsUrl
284
276
  }).then(function (response) {
285
277
  return response.body.dataSets;
286
278
  }).catch(function (error) {
287
- _this3.checkForSentinelHttpResponse(error);
279
+ _this2.checkForSentinelHttpResponse(error);
288
280
  throw error;
289
281
  });
290
282
  }
@@ -298,26 +290,26 @@ var HashTreeParser = /*#__PURE__*/function () {
298
290
  }, {
299
291
  key: "initializeFromMessage",
300
292
  value: (function () {
301
- var _initializeFromMessage = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(message) {
293
+ var _initializeFromMessage = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2(message) {
302
294
  var visibleDataSets;
303
- return _regenerator.default.wrap(function (_context) {
304
- while (1) switch (_context.prev = _context.next) {
295
+ return _regenerator.default.wrap(function (_context2) {
296
+ while (1) switch (_context2.prev = _context2.next) {
305
297
  case 0:
306
298
  this.visibleDataSetsUrl = message.visibleDataSetsUrl;
307
299
  _loggerProxy.default.logger.info("HashTreeParser#initializeFromMessage --> ".concat(this.debugId, " visibleDataSetsUrl=").concat(this.visibleDataSetsUrl));
308
- _context.next = 1;
300
+ _context2.next = 1;
309
301
  return this.getAllVisibleDataSetsFromLocus();
310
302
  case 1:
311
- visibleDataSets = _context.sent;
312
- _context.next = 2;
303
+ visibleDataSets = _context2.sent;
304
+ _context2.next = 2;
313
305
  return this.initializeDataSets(visibleDataSets, 'initialization from message');
314
306
  case 2:
315
307
  case "end":
316
- return _context.stop();
308
+ return _context2.stop();
317
309
  }
318
- }, _callee, this);
310
+ }, _callee2, this);
319
311
  }));
320
- function initializeFromMessage(_x) {
312
+ function initializeFromMessage(_x3) {
321
313
  return _initializeFromMessage.apply(this, arguments);
322
314
  }
323
315
  return initializeFromMessage;
@@ -335,34 +327,34 @@ var HashTreeParser = /*#__PURE__*/function () {
335
327
  }, {
336
328
  key: "initializeFromGetLociResponse",
337
329
  value: (function () {
338
- var _initializeFromGetLociResponse = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2(locus) {
330
+ var _initializeFromGetLociResponse = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(locus) {
339
331
  var _locus$links2, _locus$links2$resourc, _locus$links2$resourc2;
340
332
  var visibleDataSets;
341
- return _regenerator.default.wrap(function (_context2) {
342
- while (1) switch (_context2.prev = _context2.next) {
333
+ return _regenerator.default.wrap(function (_context3) {
334
+ while (1) switch (_context3.prev = _context3.next) {
343
335
  case 0:
344
336
  if (locus !== null && locus !== void 0 && (_locus$links2 = locus.links) !== null && _locus$links2 !== void 0 && (_locus$links2$resourc = _locus$links2.resources) !== null && _locus$links2$resourc !== void 0 && (_locus$links2$resourc2 = _locus$links2$resourc.visibleDataSets) !== null && _locus$links2$resourc2 !== void 0 && _locus$links2$resourc2.url) {
345
- _context2.next = 1;
337
+ _context3.next = 1;
346
338
  break;
347
339
  }
348
340
  _loggerProxy.default.logger.warn("HashTreeParser#initializeFromGetLociResponse --> ".concat(this.debugId, " missing visibleDataSets url in GET Loci response, cannot initialize hash trees"));
349
- return _context2.abrupt("return");
341
+ return _context3.abrupt("return");
350
342
  case 1:
351
343
  this.visibleDataSetsUrl = locus.links.resources.visibleDataSets.url;
352
344
  _loggerProxy.default.logger.info("HashTreeParser#initializeFromGetLociResponse --> ".concat(this.debugId, " visibleDataSets url: ").concat(this.visibleDataSetsUrl));
353
- _context2.next = 2;
345
+ _context3.next = 2;
354
346
  return this.getAllVisibleDataSetsFromLocus();
355
347
  case 2:
356
- visibleDataSets = _context2.sent;
357
- _context2.next = 3;
348
+ visibleDataSets = _context3.sent;
349
+ _context3.next = 3;
358
350
  return this.initializeDataSets(visibleDataSets, 'initialization from GET /loci response');
359
351
  case 3:
360
352
  case "end":
361
- return _context2.stop();
353
+ return _context3.stop();
362
354
  }
363
- }, _callee2, this);
355
+ }, _callee3, this);
364
356
  }));
365
- function initializeFromGetLociResponse(_x2) {
357
+ function initializeFromGetLociResponse(_x4) {
366
358
  return _initializeFromGetLociResponse.apply(this, arguments);
367
359
  }
368
360
  return initializeFromGetLociResponse;
@@ -378,24 +370,23 @@ var HashTreeParser = /*#__PURE__*/function () {
378
370
  }, {
379
371
  key: "initializeDataSets",
380
372
  value: (function () {
381
- var _initializeDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(visibleDataSets, debugText) {
382
- var updatedObjects, _iterator2, _step2, dataSet, name, leafCount, url, _data, _t;
383
- return _regenerator.default.wrap(function (_context3) {
384
- while (1) switch (_context3.prev = _context3.next) {
373
+ var _initializeDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4(visibleDataSets, debugText) {
374
+ var _iterator2, _step2, dataSet, name, leafCount, url, _t;
375
+ return _regenerator.default.wrap(function (_context4) {
376
+ while (1) switch (_context4.prev = _context4.next) {
385
377
  case 0:
386
378
  if (!(this.state === 'stopped')) {
387
- _context3.next = 1;
379
+ _context4.next = 1;
388
380
  break;
389
381
  }
390
- return _context3.abrupt("return");
382
+ return _context4.abrupt("return");
391
383
  case 1:
392
- updatedObjects = [];
393
- _iterator2 = _createForOfIteratorHelper(visibleDataSets);
394
- _context3.prev = 2;
384
+ _iterator2 = _createForOfIteratorHelper((0, _utils.sortByInitPriority)(visibleDataSets, _constants3.DATA_SET_INIT_PRIORITY));
385
+ _context4.prev = 2;
395
386
  _iterator2.s();
396
387
  case 3:
397
388
  if ((_step2 = _iterator2.n()).done) {
398
- _context3.next = 7;
389
+ _context4.next = 6;
399
390
  break;
400
391
  }
401
392
  dataSet = _step2.value;
@@ -407,59 +398,47 @@ var HashTreeParser = /*#__PURE__*/function () {
407
398
  _loggerProxy.default.logger.info("HashTreeParser#initializeDataSets --> ".concat(this.debugId, " dataset \"").concat(name, "\" already exists (").concat(debugText, ")"));
408
399
  }
409
400
  if (this.isVisibleDataSet(name)) {
410
- _context3.next = 4;
401
+ _context4.next = 4;
411
402
  break;
412
403
  }
413
404
  if (this.addToVisibleDataSetsList({
414
405
  name: name,
415
406
  url: url
416
407
  })) {
417
- _context3.next = 4;
408
+ _context4.next = 4;
418
409
  break;
419
410
  }
420
- return _context3.abrupt("continue", 6);
411
+ return _context4.abrupt("continue", 5);
421
412
  case 4:
422
- if (this.dataSets[name].hashTree) {
423
- _context3.next = 6;
424
- break;
413
+ if (!this.dataSets[name].hashTree) {
414
+ _loggerProxy.default.logger.info("HashTreeParser#initializeDataSets --> ".concat(this.debugId, " creating hash tree for visible dataset \"").concat(name, "\" (").concat(debugText, ")"));
415
+ this.dataSets[name].hashTree = new _hashTree.default([], leafCount);
416
+ this.enqueueSyncForDataset(name, "initialization sync for ".concat(debugText), true);
425
417
  }
426
- _loggerProxy.default.logger.info("HashTreeParser#initializeDataSets --> ".concat(this.debugId, " creating hash tree for visible dataset \"").concat(name, "\" (").concat(debugText, ")"));
427
- this.dataSets[name].hashTree = new _hashTree.default([], leafCount);
428
-
429
- // eslint-disable-next-line no-await-in-loop
430
- _context3.next = 5;
431
- return this.sendInitializationSyncRequestToLocus(name, debugText);
432
418
  case 5:
433
- _data = _context3.sent;
434
- if (_data.updateType === LocusInfoUpdateType.OBJECTS_UPDATED) {
435
- updatedObjects.push.apply(updatedObjects, (0, _toConsumableArray2.default)(_data.updatedObjects || []));
436
- }
419
+ _context4.next = 3;
420
+ break;
437
421
  case 6:
438
- _context3.next = 3;
422
+ _context4.next = 8;
439
423
  break;
440
424
  case 7:
441
- _context3.next = 9;
442
- break;
443
- case 8:
444
- _context3.prev = 8;
445
- _t = _context3["catch"](2);
425
+ _context4.prev = 7;
426
+ _t = _context4["catch"](2);
446
427
  _iterator2.e(_t);
447
- case 9:
448
- _context3.prev = 9;
428
+ case 8:
429
+ _context4.prev = 8;
449
430
  _iterator2.f();
450
- return _context3.finish(9);
431
+ return _context4.finish(8);
432
+ case 9:
433
+ _context4.next = 10;
434
+ return this.syncQueueProcessingPromise;
451
435
  case 10:
452
- this.callLocusInfoUpdateCallback({
453
- updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
454
- updatedObjects: updatedObjects
455
- });
456
- case 11:
457
436
  case "end":
458
- return _context3.stop();
437
+ return _context4.stop();
459
438
  }
460
- }, _callee3, this, [[2, 8, 9, 10]]);
439
+ }, _callee4, this, [[2, 7, 8, 9]]);
461
440
  }));
462
- function initializeDataSets(_x3, _x4) {
441
+ function initializeDataSets(_x5, _x6) {
463
442
  return _initializeDataSets.apply(this, arguments);
464
443
  }
465
444
  return initializeDataSets;
@@ -483,7 +462,7 @@ var HashTreeParser = /*#__PURE__*/function () {
483
462
  copyData = _ref$copyData === void 0 ? false : _ref$copyData;
484
463
  // object mapping dataset names to arrays of leaf data
485
464
  var leafInfo = {};
486
- var _findAndStoreMetaData = function findAndStoreMetaData(currentLocusPart) {
465
+ var _findAndStoreMetaData = function findAndStoreMetaData(currentLocusPart, currentLocusPartName) {
487
466
  if ((0, _typeof2.default)(currentLocusPart) !== 'object' || currentLocusPart === null) {
488
467
  return;
489
468
  }
@@ -499,10 +478,16 @@ var HashTreeParser = /*#__PURE__*/function () {
499
478
  version: version
500
479
  };
501
480
  if (copyData) {
502
- newLeafInfo.data = (0, _lodash.cloneDeep)(currentLocusPart);
481
+ if (type.toLowerCase() === _types.ObjectType.control) {
482
+ // control entries require special handling, because they are signalled by Locus
483
+ // differently when coming in messages vs API responses
484
+ newLeafInfo.data = (0, _defineProperty2.default)({}, currentLocusPartName, (0, _lodash.cloneDeep)(currentLocusPart));
485
+ } else {
486
+ newLeafInfo.data = (0, _lodash.cloneDeep)(currentLocusPart);
503
487
 
504
- // remove any nested other objects that have their own htMeta
505
- (0, _utils.deleteNestedObjectsWithHtMeta)(newLeafInfo.data);
488
+ // remove any nested other objects that have their own htMeta
489
+ (0, _utils.deleteNestedObjectsWithHtMeta)(newLeafInfo.data);
490
+ }
506
491
  }
507
492
  var _iterator3 = _createForOfIteratorHelper(dataSetNames),
508
493
  _step3;
@@ -521,12 +506,14 @@ var HashTreeParser = /*#__PURE__*/function () {
521
506
  }
522
507
  }
523
508
  if ((0, _isArray.default)(currentLocusPart)) {
524
- var _iterator4 = _createForOfIteratorHelper(currentLocusPart),
509
+ var _iterator4 = _createForOfIteratorHelper(currentLocusPart.entries()),
525
510
  _step4;
526
511
  try {
527
512
  for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
528
- var item = _step4.value;
529
- _findAndStoreMetaData(item);
513
+ var _step4$value = (0, _slicedToArray2.default)(_step4.value, 2),
514
+ index = _step4$value[0],
515
+ item = _step4$value[1];
516
+ _findAndStoreMetaData(item, index.toString());
530
517
  }
531
518
  } catch (err) {
532
519
  _iterator4.e(err);
@@ -537,12 +524,12 @@ var HashTreeParser = /*#__PURE__*/function () {
537
524
  for (var _i = 0, _Object$keys = (0, _keys.default)(currentLocusPart); _i < _Object$keys.length; _i++) {
538
525
  var key = _Object$keys[_i];
539
526
  if (Object.prototype.hasOwnProperty.call(currentLocusPart, key)) {
540
- _findAndStoreMetaData(currentLocusPart[key]);
527
+ _findAndStoreMetaData(currentLocusPart[key], key);
541
528
  }
542
529
  }
543
530
  }
544
531
  };
545
- _findAndStoreMetaData(locus);
532
+ _findAndStoreMetaData(locus, 'locus');
546
533
  return leafInfo;
547
534
  }
548
535
 
@@ -587,9 +574,9 @@ var HashTreeParser = /*#__PURE__*/function () {
587
574
  }, {
588
575
  key: "isEndMessage",
589
576
  value: function isEndMessage(message) {
590
- var _this4 = this;
577
+ var _this3 = this;
591
578
  return message.dataSets.some(function (dataSet) {
592
- if (dataSet.leafCount === 1 && dataSet.root === _constants2.EMPTY_HASH && (!_this4.dataSets[dataSet.name] || _this4.dataSets[dataSet.name].version < dataSet.version) && PossibleSentinelMessageDataSetNames.includes(dataSet.name.toLowerCase())) {
579
+ if (dataSet.leafCount === 1 && dataSet.root === _constants3.EMPTY_HASH && (!_this3.dataSets[dataSet.name] || _this3.dataSets[dataSet.name].version < dataSet.version) && PossibleSentinelMessageDataSetNames.includes(dataSet.name.toLowerCase())) {
593
580
  // this is a special way for Locus to indicate that this meeting has ended
594
581
  return true;
595
582
  }
@@ -606,7 +593,7 @@ var HashTreeParser = /*#__PURE__*/function () {
606
593
  }, {
607
594
  key: "handleRootHashHeartBeatMessage",
608
595
  value: function handleRootHashHeartBeatMessage(message) {
609
- var _this5 = this;
596
+ var _this4 = this;
610
597
  var dataSets = message.dataSets;
611
598
  _loggerProxy.default.logger.info("HashTreeParser#handleRootHashMessage --> ".concat(this.debugId, " Received heartbeat root hash message with data sets: ").concat((0, _stringify.default)(dataSets.map(function (_ref2) {
612
599
  var name = _ref2.name,
@@ -621,8 +608,8 @@ var HashTreeParser = /*#__PURE__*/function () {
621
608
  };
622
609
  }))));
623
610
  dataSets.forEach(function (dataSet) {
624
- _this5.updateDataSetInfo(dataSet);
625
- _this5.runSyncAlgorithm(dataSet);
611
+ _this4.updateDataSetInfo(dataSet);
612
+ _this4.runSyncAlgorithm(dataSet);
626
613
  });
627
614
  }
628
615
 
@@ -635,18 +622,18 @@ var HashTreeParser = /*#__PURE__*/function () {
635
622
  }, {
636
623
  key: "queueInitForNewVisibleDataSets",
637
624
  value: function queueInitForNewVisibleDataSets(dataSetsRequiringInitialization) {
638
- var _this6 = this;
625
+ var _this5 = this;
639
626
  _loggerProxy.default.logger.info("HashTreeParser#queueInitForNewVisibleDataSets --> ".concat(this.debugId, " queuing initialization of new visible datasets: ").concat(dataSetsRequiringInitialization.map(function (ds) {
640
627
  return ds.name;
641
628
  }).join(', ')));
642
629
  queueMicrotask(function () {
643
- _this6.initializeNewVisibleDataSets(dataSetsRequiringInitialization).catch(function (error) {
630
+ _this5.initializeNewVisibleDataSets(dataSetsRequiringInitialization).catch(function (error) {
644
631
  if (error instanceof MeetingEndedError) {
645
- _this6.callLocusInfoUpdateCallback({
632
+ _this5.callLocusInfoUpdateCallback({
646
633
  updateType: LocusInfoUpdateType.MEETING_ENDED
647
634
  });
648
635
  } else {
649
- _loggerProxy.default.logger.warn("HashTreeParser#queueInitForNewVisibleDataSets --> ".concat(_this6.debugId, " error while initializing new visible datasets: ").concat(dataSetsRequiringInitialization.map(function (ds) {
636
+ _loggerProxy.default.logger.warn("HashTreeParser#queueInitForNewVisibleDataSets --> ".concat(_this5.debugId, " error while initializing new visible datasets: ").concat(dataSetsRequiringInitialization.map(function (ds) {
650
637
  return ds.name;
651
638
  }).join(', '), ": "), error);
652
639
  }
@@ -706,7 +693,7 @@ var HashTreeParser = /*#__PURE__*/function () {
706
693
  }, {
707
694
  key: "handleLocusUpdate",
708
695
  value: function handleLocusUpdate(update) {
709
- var _this7 = this;
696
+ var _this6 = this;
710
697
  if (this.state === 'stopped') {
711
698
  return;
712
699
  }
@@ -714,6 +701,7 @@ var HashTreeParser = /*#__PURE__*/function () {
714
701
  locus = update.locus,
715
702
  metadata = update.metadata;
716
703
  if (!dataSets) {
704
+ // this happens for example when we handle GET /loci response
717
705
  _loggerProxy.default.logger.info("HashTreeParser#handleLocusUpdate --> ".concat(this.debugId, " received hash tree update without dataSets"));
718
706
  } else {
719
707
  var _iterator5 = _createForOfIteratorHelper(dataSets),
@@ -743,9 +731,9 @@ var HashTreeParser = /*#__PURE__*/function () {
743
731
 
744
732
  // then process the data in hash trees, if it is a new version, then add it to updatedObjects
745
733
  (0, _keys.default)(leafInfo).forEach(function (dataSetName) {
746
- if (_this7.dataSets[dataSetName]) {
747
- if (_this7.dataSets[dataSetName].hashTree) {
748
- var appliedChangesList = _this7.dataSets[dataSetName].hashTree.putItems(leafInfo[dataSetName].map(function (leaf) {
734
+ if (_this6.dataSets[dataSetName]) {
735
+ if (_this6.dataSets[dataSetName].hashTree) {
736
+ var appliedChangesList = _this6.dataSets[dataSetName].hashTree.putItems(leafInfo[dataSetName].map(function (leaf) {
749
737
  return {
750
738
  id: leaf.id,
751
739
  type: leaf.type,
@@ -772,10 +760,10 @@ var HashTreeParser = /*#__PURE__*/function () {
772
760
  });
773
761
  } else {
774
762
  // no hash tree means that the data set is not visible
775
- _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(_this7.debugId, " received leaf data for data set \"").concat(dataSetName, "\" that has no hash tree created, ignoring"));
763
+ _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(_this6.debugId, " received leaf data for data set \"").concat(dataSetName, "\" that has no hash tree created, ignoring"));
776
764
  }
777
765
  } else {
778
- _loggerProxy.default.logger.info("HashTreeParser#handleLocusUpdate --> ".concat(_this7.debugId, " received leaf data for unknown data set \"").concat(dataSetName, "\", ignoring"));
766
+ _loggerProxy.default.logger.info("HashTreeParser#handleLocusUpdate --> ".concat(_this6.debugId, " received leaf data for unknown data set \"").concat(dataSetName, "\", ignoring"));
779
767
  }
780
768
  });
781
769
  if (updatedObjects.length === 0) {
@@ -815,6 +803,21 @@ var HashTreeParser = /*#__PURE__*/function () {
815
803
  }
816
804
  }
817
805
 
806
+ /**
807
+ * Updates the leaf count for a data set, resizing its hash tree accordingly.
808
+ *
809
+ * @param {InternalDataSet} dataSet - The data set to update
810
+ * @param {number} newLeafCount - The new leaf count
811
+ * @returns {void}
812
+ */
813
+ }, {
814
+ key: "updateDataSetLeafCount",
815
+ value: function updateDataSetLeafCount(dataSet, newLeafCount) {
816
+ var _dataSet$hashTree;
817
+ (_dataSet$hashTree = dataSet.hashTree) === null || _dataSet$hashTree === void 0 ? void 0 : _dataSet$hashTree.resize(newLeafCount);
818
+ dataSet.leafCount = newLeafCount;
819
+ }
820
+
818
821
  /**
819
822
  * Checks for changes in the visible data sets based on the updated objects.
820
823
  * @param {HashTreeObject[]} updatedObjects - The list of updated hash tree objects.
@@ -823,7 +826,7 @@ var HashTreeParser = /*#__PURE__*/function () {
823
826
  }, {
824
827
  key: "checkForVisibleDataSetChanges",
825
828
  value: function checkForVisibleDataSetChanges(updatedObjects) {
826
- var _this8 = this;
829
+ var _this7 = this;
827
830
  var removedDataSets = [];
828
831
  var addedDataSets = [];
829
832
 
@@ -832,20 +835,20 @@ var HashTreeParser = /*#__PURE__*/function () {
832
835
  var _object$data;
833
836
  if ((0, _utils.isMetadata)(object) && (_object$data = object.data) !== null && _object$data !== void 0 && _object$data.visibleDataSets) {
834
837
  var newVisibleDataSets = object.data.visibleDataSets.filter(function (vds) {
835
- return !_this8.isExcludedDataSet(vds.name);
838
+ return !_this7.isExcludedDataSet(vds.name);
836
839
  });
837
- removedDataSets = _this8.visibleDataSets.filter(function (ds) {
840
+ removedDataSets = _this7.visibleDataSets.filter(function (ds) {
838
841
  return !newVisibleDataSets.some(function (nvs) {
839
842
  return nvs.name === ds.name;
840
843
  });
841
844
  });
842
845
  addedDataSets = newVisibleDataSets.filter(function (nvs) {
843
- return _this8.visibleDataSets.every(function (ds) {
846
+ return _this7.visibleDataSets.every(function (ds) {
844
847
  return ds.name !== nvs.name;
845
848
  });
846
849
  });
847
850
  if (removedDataSets.length > 0 || addedDataSets.length > 0) {
848
- _loggerProxy.default.logger.info("HashTreeParser#checkForVisibleDataSetChanges --> ".concat(_this8.debugId, " visible data sets change: removed: ").concat(removedDataSets.map(function (ds) {
851
+ _loggerProxy.default.logger.info("HashTreeParser#checkForVisibleDataSetChanges --> ".concat(_this7.debugId, " visible data sets change: removed: ").concat(removedDataSets.map(function (ds) {
849
852
  return ds.name;
850
853
  }).join(', '), ", added: ").concat(addedDataSets.map(function (ds) {
851
854
  return ds.name;
@@ -899,16 +902,16 @@ var HashTreeParser = /*#__PURE__*/function () {
899
902
  }, {
900
903
  key: "processVisibleDataSetChanges",
901
904
  value: function processVisibleDataSetChanges(removedDataSets, addedDataSets, updatedObjects) {
902
- var _this9 = this;
905
+ var _this8 = this;
903
906
  var dataSetsRequiringInitialization = [];
904
907
 
905
908
  // if a visible data set was removed, we need to tell our client that all objects from it are removed
906
909
  var removedObjects = [];
907
910
  removedDataSets.forEach(function (ds) {
908
- var _this9$dataSets$ds$na;
909
- if ((_this9$dataSets$ds$na = _this9.dataSets[ds.name]) !== null && _this9$dataSets$ds$na !== void 0 && _this9$dataSets$ds$na.hashTree) {
910
- for (var i = 0; i < _this9.dataSets[ds.name].hashTree.numLeaves; i += 1) {
911
- removedObjects.push.apply(removedObjects, (0, _toConsumableArray2.default)(_this9.dataSets[ds.name].hashTree.getLeafData(i).map(function (elementId) {
911
+ var _this8$dataSets$ds$na;
912
+ if ((_this8$dataSets$ds$na = _this8.dataSets[ds.name]) !== null && _this8$dataSets$ds$na !== void 0 && _this8$dataSets$ds$na.hashTree) {
913
+ for (var i = 0; i < _this8.dataSets[ds.name].hashTree.numLeaves; i += 1) {
914
+ removedObjects.push.apply(removedObjects, (0, _toConsumableArray2.default)(_this8.dataSets[ds.name].hashTree.getLeafData(i).map(function (elementId) {
912
915
  return {
913
916
  htMeta: {
914
917
  elementId: elementId,
@@ -918,7 +921,7 @@ var HashTreeParser = /*#__PURE__*/function () {
918
921
  };
919
922
  })));
920
923
  }
921
- _this9.deleteHashTree(ds.name);
924
+ _this8.deleteHashTree(ds.name);
922
925
  }
923
926
  });
924
927
  this.visibleDataSets = this.visibleDataSets.filter(function (vds) {
@@ -979,81 +982,78 @@ var HashTreeParser = /*#__PURE__*/function () {
979
982
  }, {
980
983
  key: "initializeNewVisibleDataSets",
981
984
  value: (function () {
982
- var _initializeNewVisibleDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4(addedDataSets) {
983
- var _this0 = this;
985
+ var _initializeNewVisibleDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5(addedDataSets) {
986
+ var _this9 = this;
984
987
  var allDataSets, _iterator7, _step7, _loop, _t2;
985
- return _regenerator.default.wrap(function (_context5) {
986
- while (1) switch (_context5.prev = _context5.next) {
988
+ return _regenerator.default.wrap(function (_context6) {
989
+ while (1) switch (_context6.prev = _context6.next) {
987
990
  case 0:
988
991
  if (!(this.state === 'stopped')) {
989
- _context5.next = 1;
992
+ _context6.next = 1;
990
993
  break;
991
994
  }
992
- return _context5.abrupt("return");
995
+ return _context6.abrupt("return");
993
996
  case 1:
994
- _context5.next = 2;
997
+ _context6.next = 2;
995
998
  return this.getAllVisibleDataSetsFromLocus();
996
999
  case 2:
997
- allDataSets = _context5.sent;
998
- _iterator7 = _createForOfIteratorHelper(addedDataSets);
999
- _context5.prev = 3;
1000
+ allDataSets = _context6.sent;
1001
+ _iterator7 = _createForOfIteratorHelper((0, _utils.sortByInitPriority)(addedDataSets, _constants3.DATA_SET_INIT_PRIORITY));
1002
+ _context6.prev = 3;
1000
1003
  _loop = /*#__PURE__*/_regenerator.default.mark(function _loop() {
1001
- var ds, dataSetInfo, updates;
1002
- return _regenerator.default.wrap(function (_context4) {
1003
- while (1) switch (_context4.prev = _context4.next) {
1004
+ var ds, dataSetInfo;
1005
+ return _regenerator.default.wrap(function (_context5) {
1006
+ while (1) switch (_context5.prev = _context5.next) {
1004
1007
  case 0:
1005
1008
  ds = _step7.value;
1006
1009
  dataSetInfo = allDataSets.find(function (d) {
1007
1010
  return d.name === ds.name;
1008
1011
  });
1009
- _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSets --> ".concat(_this0.debugId, " initializing data set \"").concat(ds.name, "\""));
1012
+ _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSets --> ".concat(_this9.debugId, " initializing data set \"").concat(ds.name, "\""));
1010
1013
  if (dataSetInfo) {
1011
- _context4.next = 1;
1014
+ _context5.next = 1;
1012
1015
  break;
1013
1016
  }
1014
- _loggerProxy.default.logger.warn("HashTreeParser#initializeNewVisibleDataSets --> ".concat(_this0.debugId, " missing info about data set \"").concat(ds.name, "\" in Locus response from visibleDataSetsUrl"));
1015
- _context4.next = 3;
1017
+ _loggerProxy.default.logger.warn("HashTreeParser#initializeNewVisibleDataSets --> ".concat(_this9.debugId, " missing info about data set \"").concat(ds.name, "\" in Locus response from visibleDataSetsUrl"));
1018
+ _context5.next = 2;
1016
1019
  break;
1017
1020
  case 1:
1018
- _context4.next = 2;
1019
- return _this0.initializeNewVisibleDataSet(ds, dataSetInfo);
1021
+ _context5.next = 2;
1022
+ return _this9.initializeNewVisibleDataSet(ds, dataSetInfo);
1020
1023
  case 2:
1021
- updates = _context4.sent;
1022
- _this0.callLocusInfoUpdateCallback(updates);
1023
- case 3:
1024
1024
  case "end":
1025
- return _context4.stop();
1025
+ return _context5.stop();
1026
1026
  }
1027
1027
  }, _loop);
1028
1028
  });
1029
1029
  _iterator7.s();
1030
1030
  case 4:
1031
1031
  if ((_step7 = _iterator7.n()).done) {
1032
- _context5.next = 6;
1032
+ _context6.next = 6;
1033
1033
  break;
1034
1034
  }
1035
- return _context5.delegateYield(_loop(), "t0", 5);
1035
+ return _context6.delegateYield(_loop(), "t0", 5);
1036
1036
  case 5:
1037
- _context5.next = 4;
1037
+ _context6.next = 4;
1038
1038
  break;
1039
1039
  case 6:
1040
- _context5.next = 8;
1040
+ _context6.next = 8;
1041
1041
  break;
1042
1042
  case 7:
1043
- _context5.prev = 7;
1044
- _t2 = _context5["catch"](3);
1043
+ _context6.prev = 7;
1044
+ _t2 = _context6["catch"](3);
1045
1045
  _iterator7.e(_t2);
1046
1046
  case 8:
1047
- _context5.prev = 8;
1047
+ _context6.prev = 8;
1048
1048
  _iterator7.f();
1049
- return _context5.finish(8);
1049
+ return _context6.finish(8);
1050
1050
  case 9:
1051
1051
  case "end":
1052
- return _context5.stop();
1052
+ return _context6.stop();
1053
1053
  }
1054
- }, _callee4, this, [[3, 7, 8, 9]]);
1054
+ }, _callee5, this, [[3, 7, 8, 9]]);
1055
1055
  }));
1056
- function initializeNewVisibleDataSets(_x5) {
1056
+ function initializeNewVisibleDataSets(_x7) {
1057
1057
  return _initializeNewVisibleDataSets.apply(this, arguments);
1058
1058
  }
1059
1059
  return initializeNewVisibleDataSets;
@@ -1070,8 +1070,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1070
1070
  key: "parseMessage",
1071
1071
  value: function parseMessage(message, debugText) {
1072
1072
  var _message$locusStateEl,
1073
- _this1 = this,
1074
- _message$locusStateEl2;
1073
+ _this0 = this;
1075
1074
  if (this.state === 'stopped') {
1076
1075
  return [];
1077
1076
  }
@@ -1086,7 +1085,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1086
1085
  // first, update our metadata about the datasets with info from the message
1087
1086
  this.visibleDataSetsUrl = visibleDataSetsUrl;
1088
1087
  dataSets.forEach(function (dataSet) {
1089
- return _this1.updateDataSetInfo(dataSet);
1088
+ return _this0.updateDataSetInfo(dataSet);
1090
1089
  });
1091
1090
  var updatedObjects = [];
1092
1091
 
@@ -1106,9 +1105,9 @@ var HashTreeParser = /*#__PURE__*/function () {
1106
1105
  _step8;
1107
1106
  try {
1108
1107
  for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
1109
- var _this1$dataSets$dataS;
1108
+ var _this0$dataSets$dataS;
1110
1109
  var dataSetName = _step8.value;
1111
- var hashTree = (_this1$dataSets$dataS = _this1.dataSets[dataSetName]) === null || _this1$dataSets$dataS === void 0 ? void 0 : _this1$dataSets$dataS.hashTree;
1110
+ var hashTree = (_this0$dataSets$dataS = _this0.dataSets[dataSetName]) === null || _this0$dataSets$dataS === void 0 ? void 0 : _this0$dataSets$dataS.hashTree;
1112
1111
  if (hashTree && object.data) {
1113
1112
  if (hashTree.putItem(object.htMeta.elementId)) {
1114
1113
  updatedMetadataObjects.push(object);
@@ -1130,13 +1129,13 @@ var HashTreeParser = /*#__PURE__*/function () {
1130
1129
  dataSetsRequiringInitialization = this.processVisibleDataSetChanges(removedDataSets, addedDataSets, updatedObjects);
1131
1130
  }
1132
1131
  }
1133
- if (((_message$locusStateEl2 = message.locusStateElements) === null || _message$locusStateEl2 === void 0 ? void 0 : _message$locusStateEl2.length) > 0) {
1132
+ if (message.locusStateElements && message.locusStateElements.length > 0) {
1134
1133
  // by this point we now have this.dataSets setup for data sets from this message
1135
1134
  // and hash trees created for the new visible data sets,
1136
1135
  // so we can now process all the updates from the message
1137
1136
  dataSets.forEach(function (dataSet) {
1138
- if (_this1.dataSets[dataSet.name]) {
1139
- var hashTree = _this1.dataSets[dataSet.name].hashTree;
1137
+ if (_this0.dataSets[dataSet.name]) {
1138
+ var hashTree = _this0.dataSets[dataSet.name].hashTree;
1140
1139
  if (hashTree) {
1141
1140
  var locusStateElementsForThisSet = message.locusStateElements.filter(function (object) {
1142
1141
  return object.htMeta.dataSetNames.includes(dataSet.name);
@@ -1160,10 +1159,10 @@ var HashTreeParser = /*#__PURE__*/function () {
1160
1159
  }
1161
1160
  });
1162
1161
  } else {
1163
- _loggerProxy.default.logger.info("Locus-info:index#parseMessage --> ".concat(_this1.debugId, " unexpected (not visible) dataSet ").concat(dataSet.name, " received in hash tree message"));
1162
+ _loggerProxy.default.logger.info("Locus-info:index#parseMessage --> ".concat(_this0.debugId, " unexpected (not visible) dataSet ").concat(dataSet.name, " received in hash tree message"));
1164
1163
  }
1165
1164
  }
1166
- _this1.runSyncAlgorithm(dataSet);
1165
+ _this0.runSyncAlgorithm(dataSet);
1167
1166
  });
1168
1167
  }
1169
1168
  if (dataSetsRequiringInitialization.length > 0) {
@@ -1220,25 +1219,25 @@ var HashTreeParser = /*#__PURE__*/function () {
1220
1219
  }, {
1221
1220
  key: "callLocusInfoUpdateCallback",
1222
1221
  value: function callLocusInfoUpdateCallback(updates) {
1223
- var _this10 = this;
1222
+ var _updates$updatedObjec,
1223
+ _this1 = this;
1224
1224
  if (this.state === 'stopped') {
1225
1225
  return;
1226
1226
  }
1227
- var updateType = updates.updateType,
1228
- updatedObjects = updates.updatedObjects;
1229
- if (updateType === LocusInfoUpdateType.OBJECTS_UPDATED && (updatedObjects === null || updatedObjects === void 0 ? void 0 : updatedObjects.length) > 0) {
1227
+ var updateType = updates.updateType;
1228
+ if (updateType === LocusInfoUpdateType.OBJECTS_UPDATED && ((_updates$updatedObjec = updates.updatedObjects) === null || _updates$updatedObjec === void 0 ? void 0 : _updates$updatedObjec.length) > 0) {
1230
1229
  // Filter out updates for objects that already have a higher version in their datasets,
1231
1230
  // or removals for objects that still exist in any of their datasets
1232
- var filteredUpdates = updatedObjects.filter(function (object) {
1231
+ var filteredUpdates = updates.updatedObjects.filter(function (object) {
1233
1232
  var elementId = object.htMeta.elementId;
1234
1233
  var type = elementId.type,
1235
1234
  id = elementId.id,
1236
1235
  version = elementId.version;
1237
1236
 
1238
1237
  // Check all datasets
1239
- for (var _i2 = 0, _Object$keys3 = (0, _keys.default)(_this10.dataSets); _i2 < _Object$keys3.length; _i2++) {
1238
+ for (var _i2 = 0, _Object$keys3 = (0, _keys.default)(_this1.dataSets); _i2 < _Object$keys3.length; _i2++) {
1240
1239
  var dataSetName = _Object$keys3[_i2];
1241
- var dataSet = _this10.dataSets[dataSetName];
1240
+ var dataSet = _this1.dataSets[dataSetName];
1242
1241
 
1243
1242
  // only visible datasets have hash trees set
1244
1243
  if (dataSet !== null && dataSet !== void 0 && dataSet.hashTree) {
@@ -1247,12 +1246,12 @@ var HashTreeParser = /*#__PURE__*/function () {
1247
1246
  if (object.data) {
1248
1247
  // For updates: filter out if any dataset has a higher version
1249
1248
  if (existingVersion > version) {
1250
- _loggerProxy.default.logger.info("HashTreeParser#callLocusInfoUpdateCallback --> ".concat(_this10.debugId, " Filtering out update for ").concat(type, ":").concat(id, " v").concat(version, " because dataset \"").concat(dataSetName, "\" has v").concat(existingVersion));
1249
+ _loggerProxy.default.logger.info("HashTreeParser#callLocusInfoUpdateCallback --> ".concat(_this1.debugId, " Filtering out update for ").concat(type, ":").concat(id, " v").concat(version, " because dataset \"").concat(dataSetName, "\" has v").concat(existingVersion));
1251
1250
  return false;
1252
1251
  }
1253
1252
  } else if (existingVersion >= version) {
1254
1253
  // For removals: filter out if the object still exists in any dataset
1255
- _loggerProxy.default.logger.info("HashTreeParser#callLocusInfoUpdateCallback --> ".concat(_this10.debugId, " Filtering out removal for ").concat(type, ":").concat(id, " v").concat(version, " because dataset \"").concat(dataSetName, "\" still has v").concat(existingVersion));
1254
+ _loggerProxy.default.logger.info("HashTreeParser#callLocusInfoUpdateCallback --> ".concat(_this1.debugId, " Filtering out removal for ").concat(type, ":").concat(id, " v").concat(version, " because dataset \"").concat(dataSetName, "\" still has v").concat(existingVersion));
1256
1255
  return false;
1257
1256
  }
1258
1257
  }
@@ -1261,13 +1260,14 @@ var HashTreeParser = /*#__PURE__*/function () {
1261
1260
  return true;
1262
1261
  });
1263
1262
  if (filteredUpdates.length > 0) {
1264
- this.locusInfoUpdateCallback(updateType, {
1263
+ this.locusInfoUpdateCallback({
1264
+ updateType: updateType,
1265
1265
  updatedObjects: filteredUpdates
1266
1266
  });
1267
1267
  }
1268
1268
  } else if (updateType !== LocusInfoUpdateType.OBJECTS_UPDATED) {
1269
- this.locusInfoUpdateCallback(updateType, {
1270
- updatedObjects: updatedObjects
1269
+ this.locusInfoUpdateCallback({
1270
+ updateType: updateType
1271
1271
  });
1272
1272
  }
1273
1273
  }
@@ -1291,84 +1291,116 @@ var HashTreeParser = /*#__PURE__*/function () {
1291
1291
  * Performs a sync for the given data set.
1292
1292
  *
1293
1293
  * @param {InternalDataSet} dataSet - The data set to sync
1294
- * @param {string} rootHash - Our current root hash for this data set
1295
1294
  * @param {string} reason - The reason for the sync (used for logging)
1295
+ * @param {boolean} [isInitialization] - Whether this is an initialization sync (sends empty leaves data instead of comparing hashes)
1296
1296
  * @returns {Promise<void>}
1297
1297
  */
1298
1298
  }, {
1299
1299
  key: "performSync",
1300
1300
  value: (function () {
1301
- var _performSync = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5(dataSet, rootHash, reason) {
1302
- var mismatchedLeavesData, receivedHashes, _yield$this$getHashes, hashes, latestDataSetInfo, mismatchedLeaveIndexes, syncResponse, _t3, _t4;
1303
- return _regenerator.default.wrap(function (_context6) {
1304
- while (1) switch (_context6.prev = _context6.next) {
1301
+ var _performSync = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee6(dataSet, reason, isInitialization) {
1302
+ var hashTree, rootHash, leavesData, receivedHashes, hashesResult, mismatchedLeaveIndexes, syncResponse, _t3, _t4;
1303
+ return _regenerator.default.wrap(function (_context7) {
1304
+ while (1) switch (_context7.prev = _context7.next) {
1305
1305
  case 0:
1306
1306
  if (dataSet.hashTree) {
1307
- _context6.next = 1;
1307
+ _context7.next = 1;
1308
1308
  break;
1309
1309
  }
1310
- return _context6.abrupt("return");
1310
+ return _context7.abrupt("return");
1311
1311
  case 1:
1312
- _context6.prev = 1;
1312
+ hashTree = dataSet.hashTree;
1313
+ rootHash = hashTree.getRootHash();
1314
+ _context7.prev = 2;
1313
1315
  _loggerProxy.default.logger.info("HashTreeParser#performSync --> ".concat(this.debugId, " ").concat(reason, ", syncing data set \"").concat(dataSet.name, "\""));
1314
- mismatchedLeavesData = {};
1316
+ leavesData = {};
1317
+ if (isInitialization) {
1318
+ _context7.next = 10;
1319
+ break;
1320
+ }
1315
1321
  if (!(dataSet.leafCount !== 1)) {
1316
- _context6.next = 7;
1322
+ _context7.next = 9;
1317
1323
  break;
1318
1324
  }
1319
- _context6.prev = 2;
1320
- _context6.next = 3;
1325
+ _context7.prev = 3;
1326
+ _context7.next = 4;
1321
1327
  return this.getHashesFromLocus(dataSet.name, rootHash);
1322
- case 3:
1323
- _yield$this$getHashes = _context6.sent;
1324
- hashes = _yield$this$getHashes.hashes;
1325
- latestDataSetInfo = _yield$this$getHashes.dataSet;
1326
- receivedHashes = hashes;
1327
- dataSet.hashTree.resize(latestDataSetInfo.leafCount);
1328
- _context6.next = 6;
1329
- break;
1330
1328
  case 4:
1331
- _context6.prev = 4;
1332
- _t3 = _context6["catch"](2);
1333
- if (!(_t3.statusCode === 409)) {
1334
- _context6.next = 5;
1329
+ hashesResult = _context7.sent;
1330
+ if (hashesResult) {
1331
+ _context7.next = 5;
1332
+ break;
1333
+ }
1334
+ return _context7.abrupt("return");
1335
+ case 5:
1336
+ receivedHashes = hashesResult.hashes;
1337
+ this.updateDataSetLeafCount(dataSet, hashesResult.dataSet.leafCount);
1338
+ _context7.next = 8;
1339
+ break;
1340
+ case 6:
1341
+ _context7.prev = 6;
1342
+ _t3 = _context7["catch"](3);
1343
+ if (!((_t3 === null || _t3 === void 0 ? void 0 : _t3.statusCode) === 409)) {
1344
+ _context7.next = 7;
1335
1345
  break;
1336
1346
  }
1337
1347
  // this is a leaf count mismatch, we should do nothing, just wait for another heartbeat message from Locus
1338
1348
  _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(this.debugId, " Got 409 when fetching hashes for data set \"").concat(dataSet.name, "\": ").concat(_t3.message));
1339
- return _context6.abrupt("return");
1340
- case 5:
1349
+ return _context7.abrupt("return");
1350
+ case 7:
1341
1351
  throw _t3;
1342
- case 6:
1352
+ case 8:
1343
1353
  // identify mismatched leaves
1344
- mismatchedLeaveIndexes = dataSet.hashTree.diffHashes(receivedHashes);
1354
+ mismatchedLeaveIndexes = hashTree.diffHashes(receivedHashes);
1345
1355
  mismatchedLeaveIndexes.forEach(function (index) {
1346
- mismatchedLeavesData[index] = dataSet.hashTree.getLeafData(index);
1356
+ leavesData[index] = hashTree.getLeafData(index);
1347
1357
  });
1348
- _context6.next = 8;
1358
+ _context7.next = 10;
1349
1359
  break;
1350
- case 7:
1351
- mismatchedLeavesData[0] = dataSet.hashTree.getLeafData(0);
1352
- case 8:
1353
- if (!((0, _keys.default)(mismatchedLeavesData).length > 0)) {
1354
- _context6.next = 10;
1360
+ case 9:
1361
+ leavesData = {
1362
+ 0: hashTree.getLeafData(0)
1363
+ };
1364
+ case 10:
1365
+ // request sync for mismatched leaves
1366
+ syncResponse = null;
1367
+ if (!isInitialization) {
1368
+ _context7.next = 12;
1355
1369
  break;
1356
1370
  }
1357
- _context6.next = 9;
1358
- return this.sendSyncRequestToLocus(dataSet, mismatchedLeavesData);
1359
- case 9:
1360
- syncResponse = _context6.sent;
1371
+ _context7.next = 11;
1372
+ return this.sendSyncRequestToLocus(dataSet, {
1373
+ isInitialization: true
1374
+ });
1375
+ case 11:
1376
+ syncResponse = _context7.sent;
1377
+ _context7.next = 14;
1378
+ break;
1379
+ case 12:
1380
+ if (!((0, _keys.default)(leavesData).length > 0)) {
1381
+ _context7.next = 14;
1382
+ break;
1383
+ }
1384
+ _context7.next = 13;
1385
+ return this.sendSyncRequestToLocus(dataSet, {
1386
+ mismatchedLeavesData: leavesData
1387
+ });
1388
+ case 13:
1389
+ syncResponse = _context7.sent;
1390
+ case 14:
1361
1391
  // sync API may return nothing (in that case data will arrive via messages)
1362
1392
  // or it may return a response in the same format as messages
1393
+ // We still need to restart the sync timer as a safety net in case the messages don't arrive.
1394
+ this.runSyncAlgorithm(dataSet);
1363
1395
  if (syncResponse) {
1396
+ // the format of sync response is the same as messages, so we can reuse the same handler
1364
1397
  this.handleMessage(syncResponse, 'via sync API');
1365
1398
  }
1366
- case 10:
1367
- _context6.next = 12;
1399
+ _context7.next = 16;
1368
1400
  break;
1369
- case 11:
1370
- _context6.prev = 11;
1371
- _t4 = _context6["catch"](1);
1401
+ case 15:
1402
+ _context7.prev = 15;
1403
+ _t4 = _context7["catch"](2);
1372
1404
  if (_t4 instanceof MeetingEndedError) {
1373
1405
  this.callLocusInfoUpdateCallback({
1374
1406
  updateType: LocusInfoUpdateType.MEETING_ENDED
@@ -1376,17 +1408,176 @@ var HashTreeParser = /*#__PURE__*/function () {
1376
1408
  } else {
1377
1409
  _loggerProxy.default.logger.warn("HashTreeParser#performSync --> ".concat(this.debugId, " error during sync for data set \"").concat(dataSet.name, "\":"), _t4);
1378
1410
  }
1379
- case 12:
1411
+ case 16:
1380
1412
  case "end":
1381
- return _context6.stop();
1413
+ return _context7.stop();
1382
1414
  }
1383
- }, _callee5, this, [[1, 11], [2, 4]]);
1415
+ }, _callee6, this, [[2, 15], [3, 6]]);
1384
1416
  }));
1385
- function performSync(_x6, _x7, _x8) {
1417
+ function performSync(_x8, _x9, _x0) {
1386
1418
  return _performSync.apply(this, arguments);
1387
1419
  }
1388
1420
  return performSync;
1389
1421
  }()
1422
+ /**
1423
+ * Enqueues a sync for the given data set. If the data set is already in the queue, the request is ignored.
1424
+ * This ensures that all syncs are executed sequentially and no more than 1 sync runs at a time.
1425
+ *
1426
+ * @param {string} dataSetName - The name of the data set to sync
1427
+ * @param {string} reason - The reason for the sync (used for logging)
1428
+ * @param {boolean} [isInitialization=false] - Whether this is an initialization sync (uses empty leaves data instead of hash comparison)
1429
+ * @returns {void}
1430
+ */
1431
+ )
1432
+ }, {
1433
+ key: "enqueueSyncForDataset",
1434
+ value: function enqueueSyncForDataset(dataSetName, reason) {
1435
+ var isInitialization = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1436
+ if (this.state === 'stopped') return;
1437
+ var existingEntry = this.syncQueue.find(function (entry) {
1438
+ return entry.dataSetName === dataSetName;
1439
+ });
1440
+ if (existingEntry) {
1441
+ if (isInitialization) {
1442
+ existingEntry.isInitialization = true;
1443
+ }
1444
+ _loggerProxy.default.logger.info("HashTreeParser#enqueueSyncForDataset --> ".concat(this.debugId, " data set \"").concat(dataSetName, "\" already in sync queue, skipping"));
1445
+ return;
1446
+ }
1447
+ this.syncQueue.push({
1448
+ dataSetName: dataSetName,
1449
+ reason: reason,
1450
+ isInitialization: isInitialization
1451
+ });
1452
+ if (!this.isSyncInProgress) {
1453
+ this.syncQueueProcessingPromise = this.processSyncQueue();
1454
+ }
1455
+ }
1456
+
1457
+ /**
1458
+ * Processes the sync queue sequentially. Only one instance of this method runs at a time.
1459
+ *
1460
+ * @returns {Promise<void>}
1461
+ */
1462
+ }, {
1463
+ key: "processSyncQueue",
1464
+ value: (function () {
1465
+ var _processSyncQueue = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee7() {
1466
+ var _ref7, dataSetName, reason, isInitialization, dataSet;
1467
+ return _regenerator.default.wrap(function (_context8) {
1468
+ while (1) switch (_context8.prev = _context8.next) {
1469
+ case 0:
1470
+ if (!this.isSyncInProgress) {
1471
+ _context8.next = 1;
1472
+ break;
1473
+ }
1474
+ return _context8.abrupt("return");
1475
+ case 1:
1476
+ this.isSyncInProgress = true;
1477
+ _context8.prev = 2;
1478
+ case 3:
1479
+ if (!(this.syncQueue.length > 0 && this.state !== 'stopped')) {
1480
+ _context8.next = 6;
1481
+ break;
1482
+ }
1483
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1484
+ _ref7 = this.syncQueue.shift(), dataSetName = _ref7.dataSetName, reason = _ref7.reason, isInitialization = _ref7.isInitialization;
1485
+ dataSet = this.dataSets[dataSetName];
1486
+ if (dataSet !== null && dataSet !== void 0 && dataSet.hashTree) {
1487
+ _context8.next = 4;
1488
+ break;
1489
+ }
1490
+ return _context8.abrupt("continue", 3);
1491
+ case 4:
1492
+ _context8.next = 5;
1493
+ return this.performSync(dataSet, reason, isInitialization);
1494
+ case 5:
1495
+ _context8.next = 3;
1496
+ break;
1497
+ case 6:
1498
+ _context8.prev = 6;
1499
+ this.isSyncInProgress = false;
1500
+ return _context8.finish(6);
1501
+ case 7:
1502
+ case "end":
1503
+ return _context8.stop();
1504
+ }
1505
+ }, _callee7, this, [[2,, 6, 7]]);
1506
+ }));
1507
+ function processSyncQueue() {
1508
+ return _processSyncQueue.apply(this, arguments);
1509
+ }
1510
+ return processSyncQueue;
1511
+ }()
1512
+ /**
1513
+ * Syncs all data sets that have hash trees, one by one in sequence, using the priority order
1514
+ * provided by sortByInitPriority(). Does nothing if the parser is stopped or if a syncAllDatasets
1515
+ * call is already in progress.
1516
+ *
1517
+ * @returns {Promise<void>}
1518
+ */
1519
+ )
1520
+ }, {
1521
+ key: "syncAllDatasets",
1522
+ value: (function () {
1523
+ var _syncAllDatasets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee8() {
1524
+ var dataSetsWithHashTrees, sorted, _iterator9, _step9, ds;
1525
+ return _regenerator.default.wrap(function (_context9) {
1526
+ while (1) switch (_context9.prev = _context9.next) {
1527
+ case 0:
1528
+ if (!(this.state === 'stopped')) {
1529
+ _context9.next = 1;
1530
+ break;
1531
+ }
1532
+ return _context9.abrupt("return");
1533
+ case 1:
1534
+ if (!this.isSyncAllInProgress) {
1535
+ _context9.next = 2;
1536
+ break;
1537
+ }
1538
+ return _context9.abrupt("return");
1539
+ case 2:
1540
+ this.isSyncAllInProgress = true;
1541
+ _context9.prev = 3;
1542
+ dataSetsWithHashTrees = (0, _values.default)(this.dataSets).filter(function (dataSet) {
1543
+ return dataSet === null || dataSet === void 0 ? void 0 : dataSet.hashTree;
1544
+ }).map(function (dataSet) {
1545
+ return {
1546
+ name: dataSet.name
1547
+ };
1548
+ });
1549
+ sorted = (0, _utils.sortByInitPriority)(dataSetsWithHashTrees, _constants3.DATA_SET_INIT_PRIORITY);
1550
+ _loggerProxy.default.logger.info("HashTreeParser#syncAllDatasets --> ".concat(this.debugId, " syncing datasets: ").concat(sorted.map(function (ds) {
1551
+ return ds.name;
1552
+ }).join(', ')));
1553
+ _iterator9 = _createForOfIteratorHelper(sorted);
1554
+ try {
1555
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
1556
+ ds = _step9.value;
1557
+ this.enqueueSyncForDataset(ds.name, 'syncAllDatasets');
1558
+ }
1559
+ } catch (err) {
1560
+ _iterator9.e(err);
1561
+ } finally {
1562
+ _iterator9.f();
1563
+ }
1564
+ _context9.next = 4;
1565
+ return this.syncQueueProcessingPromise;
1566
+ case 4:
1567
+ _context9.prev = 4;
1568
+ this.isSyncAllInProgress = false;
1569
+ return _context9.finish(4);
1570
+ case 5:
1571
+ case "end":
1572
+ return _context9.stop();
1573
+ }
1574
+ }, _callee8, this, [[3,, 4, 5]]);
1575
+ }));
1576
+ function syncAllDatasets() {
1577
+ return _syncAllDatasets.apply(this, arguments);
1578
+ }
1579
+ return syncAllDatasets;
1580
+ }()
1390
1581
  /**
1391
1582
  * Runs the sync algorithm for the given data set.
1392
1583
  *
@@ -1397,7 +1588,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1397
1588
  }, {
1398
1589
  key: "runSyncAlgorithm",
1399
1590
  value: function runSyncAlgorithm(receivedDataSet) {
1400
- var _this11 = this;
1591
+ var _this10 = this;
1401
1592
  var dataSet = this.dataSets[receivedDataSet.name];
1402
1593
  if (!dataSet) {
1403
1594
  _loggerProxy.default.logger.warn("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " No data set found for ").concat(receivedDataSet.name, ", skipping sync algorithm"));
@@ -1408,47 +1599,25 @@ var HashTreeParser = /*#__PURE__*/function () {
1408
1599
  return;
1409
1600
  }
1410
1601
  dataSet.hashTree.resize(receivedDataSet.leafCount);
1411
-
1412
- // temporary log for the workshop // todo: remove
1413
- var ourCurrentRootHash = dataSet.hashTree.getRootHash();
1414
- _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " dataSet=\"").concat(dataSet.name, "\" version=").concat(dataSet.version, " hashes before starting timer: ours=").concat(ourCurrentRootHash, " Locus=").concat(dataSet.root));
1415
1602
  var delay = dataSet.idleMs + this.getWeightedBackoffTime(dataSet.backoff);
1416
1603
  if (delay > 0) {
1417
1604
  if (dataSet.timer) {
1418
1605
  clearTimeout(dataSet.timer);
1419
1606
  }
1420
1607
  _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " setting \"").concat(dataSet.name, "\" sync timer for ").concat(delay));
1421
- dataSet.timer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee6() {
1422
- var rootHash;
1423
- return _regenerator.default.wrap(function (_context7) {
1424
- while (1) switch (_context7.prev = _context7.next) {
1425
- case 0:
1426
- dataSet.timer = undefined;
1427
- if (dataSet.hashTree) {
1428
- _context7.next = 1;
1429
- break;
1430
- }
1431
- _loggerProxy.default.logger.warn("HashTreeParser#runSyncAlgorithm --> ".concat(_this11.debugId, " Data set \"").concat(dataSet.name, "\" no longer has a hash tree, cannot run sync algorithm"));
1432
- return _context7.abrupt("return");
1433
- case 1:
1434
- rootHash = dataSet.hashTree.getRootHash();
1435
- if (!(dataSet.root !== rootHash)) {
1436
- _context7.next = 3;
1437
- break;
1438
- }
1439
- _context7.next = 2;
1440
- return _this11.performSync(dataSet, rootHash, "Root hash mismatch: received=".concat(dataSet.root, ", ours=").concat(rootHash));
1441
- case 2:
1442
- _context7.next = 4;
1443
- break;
1444
- case 3:
1445
- _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(_this11.debugId, " \"").concat(dataSet.name, "\" root hash matching: ").concat(rootHash, ", version=").concat(dataSet.version));
1446
- case 4:
1447
- case "end":
1448
- return _context7.stop();
1449
- }
1450
- }, _callee6);
1451
- })), delay);
1608
+ dataSet.timer = setTimeout(function () {
1609
+ dataSet.timer = undefined;
1610
+ if (!dataSet.hashTree) {
1611
+ _loggerProxy.default.logger.warn("HashTreeParser#runSyncAlgorithm --> ".concat(_this10.debugId, " Data set \"").concat(dataSet.name, "\" no longer has a hash tree, cannot run sync algorithm"));
1612
+ return;
1613
+ }
1614
+ var rootHash = dataSet.hashTree.getRootHash();
1615
+ if (dataSet.root !== rootHash) {
1616
+ _this10.enqueueSyncForDataset(dataSet.name, "Root hash mismatch: received=".concat(dataSet.root, ", ours=").concat(rootHash));
1617
+ } else {
1618
+ _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(_this10.debugId, " \"").concat(dataSet.name, "\" root hash matching: ").concat(rootHash, ", version=").concat(dataSet.version));
1619
+ }
1620
+ }, delay);
1452
1621
  } else {
1453
1622
  _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " No delay for \"").concat(dataSet.name, "\" data set, skipping sync timer reset/setup"));
1454
1623
  }
@@ -1466,16 +1635,16 @@ var HashTreeParser = /*#__PURE__*/function () {
1466
1635
  }, {
1467
1636
  key: "resetHeartbeatWatchdogs",
1468
1637
  value: function resetHeartbeatWatchdogs(receivedDataSets) {
1469
- var _this12 = this;
1638
+ var _this11 = this;
1470
1639
  if (!this.heartbeatIntervalMs) {
1471
1640
  return;
1472
1641
  }
1473
- var _iterator9 = _createForOfIteratorHelper(receivedDataSets),
1474
- _step9;
1642
+ var _iterator0 = _createForOfIteratorHelper(receivedDataSets),
1643
+ _step0;
1475
1644
  try {
1476
1645
  var _loop2 = function _loop2() {
1477
- var receivedDataSet = _step9.value;
1478
- var dataSet = _this12.dataSets[receivedDataSet.name];
1646
+ var receivedDataSet = _step0.value;
1647
+ var dataSet = _this11.dataSets[receivedDataSet.name];
1479
1648
  if (!(dataSet !== null && dataSet !== void 0 && dataSet.hashTree)) {
1480
1649
  // eslint-disable-next-line no-continue
1481
1650
  return 1; // continue
@@ -1484,30 +1653,22 @@ var HashTreeParser = /*#__PURE__*/function () {
1484
1653
  clearTimeout(dataSet.heartbeatWatchdogTimer);
1485
1654
  dataSet.heartbeatWatchdogTimer = undefined;
1486
1655
  }
1487
- var backoffTime = _this12.getWeightedBackoffTime(dataSet.backoff);
1488
- var delay = _this12.heartbeatIntervalMs + backoffTime;
1489
- dataSet.heartbeatWatchdogTimer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee7() {
1490
- return _regenerator.default.wrap(function (_context8) {
1491
- while (1) switch (_context8.prev = _context8.next) {
1492
- case 0:
1493
- dataSet.heartbeatWatchdogTimer = undefined;
1494
- _loggerProxy.default.logger.warn("HashTreeParser#resetHeartbeatWatchdogs --> ".concat(_this12.debugId, " Heartbeat watchdog fired for data set \"").concat(dataSet.name, "\" - no heartbeat received within expected interval, initiating sync"));
1495
- _context8.next = 1;
1496
- return _this12.performSync(dataSet, dataSet.hashTree.getRootHash(), "heartbeat watchdog expired");
1497
- case 1:
1498
- case "end":
1499
- return _context8.stop();
1500
- }
1501
- }, _callee7);
1502
- })), delay);
1656
+ var backoffTime = _this11.getWeightedBackoffTime(dataSet.backoff);
1657
+ var delay = _this11.heartbeatIntervalMs + backoffTime;
1658
+ dataSet.heartbeatWatchdogTimer = setTimeout(function () {
1659
+ dataSet.heartbeatWatchdogTimer = undefined;
1660
+ _loggerProxy.default.logger.warn("HashTreeParser#resetHeartbeatWatchdogs --> ".concat(_this11.debugId, " Heartbeat watchdog fired for data set \"").concat(dataSet.name, "\" - no heartbeat received within expected interval, initiating sync"));
1661
+ _this11.enqueueSyncForDataset(dataSet.name, "heartbeat watchdog expired");
1662
+ _this11.resetHeartbeatWatchdogs([dataSet]);
1663
+ }, delay);
1503
1664
  };
1504
- for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
1665
+ for (_iterator0.s(); !(_step0 = _iterator0.n()).done;) {
1505
1666
  if (_loop2()) continue;
1506
1667
  }
1507
1668
  } catch (err) {
1508
- _iterator9.e(err);
1669
+ _iterator0.e(err);
1509
1670
  } finally {
1510
- _iterator9.f();
1671
+ _iterator0.f();
1511
1672
  }
1512
1673
  }
1513
1674
 
@@ -1541,6 +1702,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1541
1702
  value: function stop() {
1542
1703
  _loggerProxy.default.logger.info("HashTreeParser#stop --> ".concat(this.debugId, " Stopping HashTreeParser, clearing timers and hash trees"));
1543
1704
  this.stopAllTimers();
1705
+ this.syncQueue = [];
1544
1706
  (0, _values.default)(this.dataSets).forEach(function (dataSet) {
1545
1707
  dataSet.hashTree = undefined;
1546
1708
  });
@@ -1549,29 +1711,41 @@ var HashTreeParser = /*#__PURE__*/function () {
1549
1711
  }
1550
1712
 
1551
1713
  /**
1552
- * Resumes the HashTreeParser that was previously stopped.
1714
+ * Cleans up the HashTreeParser, stopping all timers and clearing all internal state.
1715
+ * After calling this, the parser should not be used anymore.
1716
+ * @returns {void}
1717
+ */
1718
+ }, {
1719
+ key: "cleanUp",
1720
+ value: function cleanUp() {
1721
+ this.stop();
1722
+ this.dataSets = {};
1723
+ }
1724
+
1725
+ /**
1726
+ * Resumes the HashTreeParser that was previously stopped, using a hash tree message.
1553
1727
  * @param {HashTreeMessage} message - The message to resume with, it must contain metadata with visible data sets info
1554
1728
  * @returns {void}
1555
1729
  */
1556
1730
  }, {
1557
- key: "resume",
1558
- value: function resume(message) {
1559
- var _message$locusStateEl3, _metadataObject$data;
1731
+ key: "resumeFromMessage",
1732
+ value: function resumeFromMessage(message) {
1733
+ var _message$locusStateEl2, _metadataObject$data;
1560
1734
  // check that message contains metadata with visible data sets - this is essential to be able to resume
1561
- var metadataObject = (_message$locusStateEl3 = message.locusStateElements) === null || _message$locusStateEl3 === void 0 ? void 0 : _message$locusStateEl3.find(function (el) {
1735
+ var metadataObject = (_message$locusStateEl2 = message.locusStateElements) === null || _message$locusStateEl2 === void 0 ? void 0 : _message$locusStateEl2.find(function (el) {
1562
1736
  return (0, _utils.isMetadata)(el);
1563
1737
  });
1564
1738
  if (!(metadataObject !== null && metadataObject !== void 0 && (_metadataObject$data = metadataObject.data) !== null && _metadataObject$data !== void 0 && _metadataObject$data.visibleDataSets)) {
1565
- _loggerProxy.default.logger.warn("HashTreeParser#resume --> ".concat(this.debugId, " Cannot resume HashTreeParser because the message is missing metadata with visible data sets info"));
1739
+ _loggerProxy.default.logger.warn("HashTreeParser#resumeFromMessage --> ".concat(this.debugId, " Cannot resume HashTreeParser because the message is missing metadata with visible data sets info"));
1566
1740
  return;
1567
1741
  }
1568
1742
  this.setVisibleDataSets(metadataObject.data.visibleDataSets, message.dataSets);
1569
1743
  this.dataSets = {};
1570
- var _iterator0 = _createForOfIteratorHelper(message.dataSets),
1571
- _step0;
1744
+ var _iterator1 = _createForOfIteratorHelper(message.dataSets),
1745
+ _step1;
1572
1746
  try {
1573
- for (_iterator0.s(); !(_step0 = _iterator0.n()).done;) {
1574
- var dataSet = _step0.value;
1747
+ for (_iterator1.s(); !(_step1 = _iterator1.n()).done;) {
1748
+ var dataSet = _step1.value;
1575
1749
  var name = dataSet.name,
1576
1750
  leafCount = dataSet.leafCount;
1577
1751
  this.dataSets[name] = _objectSpread(_objectSpread({}, dataSet), {}, {
@@ -1579,16 +1753,47 @@ var HashTreeParser = /*#__PURE__*/function () {
1579
1753
  });
1580
1754
  }
1581
1755
  } catch (err) {
1582
- _iterator0.e(err);
1756
+ _iterator1.e(err);
1583
1757
  } finally {
1584
- _iterator0.f();
1758
+ _iterator1.f();
1585
1759
  }
1586
- _loggerProxy.default.logger.info("HashTreeParser#resume --> ".concat(this.debugId, " Resuming HashTreeParser with data sets: ").concat((0, _keys.default)(this.dataSets).join(', '), ", visible data sets: ").concat(this.visibleDataSets.map(function (ds) {
1760
+ _loggerProxy.default.logger.info("HashTreeParser#resumeFromMessage --> ".concat(this.debugId, " Resuming HashTreeParser with data sets: ").concat((0, _keys.default)(this.dataSets).join(', '), ", visible data sets: ").concat(this.visibleDataSets.map(function (ds) {
1587
1761
  return ds.name;
1588
1762
  }).join(', ')));
1589
1763
  this.state = 'active';
1590
1764
  this.handleMessage(message, 'on resume');
1591
1765
  }
1766
+
1767
+ /**
1768
+ * Resumes the HashTreeParser that was previously stopped, using a Locus API response.
1769
+ * Unlike resumeFromMessage(), this does not require metadata/dataSets in the input,
1770
+ * as it fetches all necessary information from Locus via initializeFromGetLociResponse.
1771
+ * @param {LocusDTO} locus - locus object from an API response
1772
+ * @returns {Promise}
1773
+ */
1774
+ }, {
1775
+ key: "resumeFromApiResponse",
1776
+ value: (function () {
1777
+ var _resumeFromApiResponse = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee9(locus) {
1778
+ return _regenerator.default.wrap(function (_context0) {
1779
+ while (1) switch (_context0.prev = _context0.next) {
1780
+ case 0:
1781
+ this.state = 'active';
1782
+ this.dataSets = {};
1783
+ _loggerProxy.default.logger.info("HashTreeParser#resumeFromApiResponse --> ".concat(this.debugId, " Resuming HashTreeParser from API response"));
1784
+ _context0.next = 1;
1785
+ return this.initializeFromGetLociResponse(locus);
1786
+ case 1:
1787
+ case "end":
1788
+ return _context0.stop();
1789
+ }
1790
+ }, _callee9, this);
1791
+ }));
1792
+ function resumeFromApiResponse(_x1) {
1793
+ return _resumeFromApiResponse.apply(this, arguments);
1794
+ }
1795
+ return resumeFromApiResponse;
1796
+ }())
1592
1797
  }, {
1593
1798
  key: "checkForSentinelHttpResponse",
1594
1799
  value: function checkForSentinelHttpResponse(error, dataSetName) {
@@ -1605,37 +1810,49 @@ var HashTreeParser = /*#__PURE__*/function () {
1605
1810
  * Gets the current hashes from the locus for a specific data set.
1606
1811
  * @param {string} dataSetName
1607
1812
  * @param {string} currentRootHash
1608
- * @returns {string[]}
1813
+ * @returns {Object|null} An object containing the hashes and leaf count, or null if the hashes match and no sync is needed
1609
1814
  */
1610
1815
  }, {
1611
1816
  key: "getHashesFromLocus",
1612
1817
  value: function getHashesFromLocus(dataSetName, currentRootHash) {
1613
- var _this13 = this;
1818
+ var _this12 = this;
1614
1819
  _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(this.debugId, " Requesting hashes for data set \"").concat(dataSetName, "\""));
1615
1820
  var dataSet = this.dataSets[dataSetName];
1616
1821
  var url = "".concat(dataSet.url, "/hashtree");
1617
1822
  return this.webexRequest({
1618
- method: _constants.HTTP_VERBS.GET,
1823
+ method: _constants2.HTTP_VERBS.GET,
1619
1824
  uri: url,
1620
1825
  qs: {
1621
1826
  rootHash: currentRootHash
1622
1827
  }
1623
1828
  }).then(function (response) {
1624
1829
  var _response$body, _response$body2;
1830
+ if (!response.body || (0, _lodash.isEmpty)(response.body)) {
1831
+ // 204 with empty body means our hashes match Locus, no sync needed
1832
+ _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this12.debugId, " Got ").concat(response.statusCode, " with empty body for data set \"").concat(dataSetName, "\", hashes match - no sync needed"));
1833
+ return null;
1834
+ }
1625
1835
  var hashes = (_response$body = response.body) === null || _response$body === void 0 ? void 0 : _response$body.hashes;
1626
1836
  var dataSetFromResponse = (_response$body2 = response.body) === null || _response$body2 === void 0 ? void 0 : _response$body2.dataSet;
1627
1837
  if (!hashes || !(0, _isArray.default)(hashes)) {
1628
- _loggerProxy.default.logger.warn("HashTreeParser#getHashesFromLocus --> ".concat(_this13.debugId, " Locus returned invalid hashes, response body="), response.body);
1838
+ _loggerProxy.default.logger.warn("HashTreeParser#getHashesFromLocus --> ".concat(_this12.debugId, " Locus returned invalid hashes, response body="), response.body);
1629
1839
  throw new Error("Locus returned invalid hashes: ".concat(hashes));
1630
1840
  }
1631
- _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this13.debugId, " Received hashes for data set \"").concat(dataSetName, "\": ").concat((0, _stringify.default)(hashes)));
1841
+ _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this12.debugId, " Received hashes for data set \"").concat(dataSetName, "\": ").concat((0, _stringify.default)(hashes)));
1632
1842
  return {
1633
1843
  hashes: hashes,
1634
1844
  dataSet: dataSetFromResponse
1635
1845
  };
1636
1846
  }).catch(function (error) {
1637
- _loggerProxy.default.logger.error("HashTreeParser#getHashesFromLocus --> ".concat(_this13.debugId, " Error ").concat(error.statusCode, " fetching hashes for data set \"").concat(dataSetName, "\":"), error);
1638
- _this13.checkForSentinelHttpResponse(error, dataSet.name);
1847
+ _loggerProxy.default.logger.error("HashTreeParser#getHashesFromLocus --> ".concat(_this12.debugId, " Error ").concat(error.statusCode, " fetching hashes for data set \"").concat(dataSetName, "\":"), error);
1848
+ _this12.checkForSentinelHttpResponse(error, dataSet.name);
1849
+ _metrics.default.sendBehavioralMetric(_constants.default.HASH_TREE_SYNC_FAILURE, {
1850
+ debugId: _this12.debugId,
1851
+ dataSetName: dataSetName,
1852
+ request: 'GET /hashtree',
1853
+ statusCode: error.statusCode,
1854
+ reason: error.message
1855
+ });
1639
1856
  throw error;
1640
1857
  });
1641
1858
  }
@@ -1644,43 +1861,61 @@ var HashTreeParser = /*#__PURE__*/function () {
1644
1861
  * Sends a sync request to Locus for the specified data set.
1645
1862
  *
1646
1863
  * @param {InternalDataSet} dataSet The data set to sync.
1647
- * @param {Record<number, LeafDataItem[]>} mismatchedLeavesData The mismatched leaves data to include in the sync request.
1864
+ * @param {Object} options Either `{ isInitialization: true }` for init syncs (uses leafCount=1 with empty leaf data) or `{ mismatchedLeavesData }` for normal syncs.
1648
1865
  * @returns {Promise<HashTreeMessage|null>}
1649
1866
  */
1650
1867
  }, {
1651
1868
  key: "sendSyncRequestToLocus",
1652
- value: function sendSyncRequestToLocus(dataSet, mismatchedLeavesData) {
1653
- var _this14 = this;
1869
+ value: function sendSyncRequestToLocus(dataSet, options) {
1870
+ var _this13 = this;
1654
1871
  _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(this.debugId, " Sending sync request for data set \"").concat(dataSet.name, "\""));
1872
+ var isInitialization = 'isInitialization' in options;
1655
1873
  var url = "".concat(dataSet.url, "/sync");
1656
1874
  var body = {
1657
- leafCount: dataSet.leafCount,
1875
+ leafCount: isInitialization ? 1 : dataSet.leafCount,
1658
1876
  leafDataEntries: []
1659
1877
  };
1660
- (0, _keys.default)(mismatchedLeavesData).forEach(function (index) {
1878
+ if (isInitialization) {
1879
+ // initialization sync: Locus requires leafCount=1 with a single empty leaf
1661
1880
  body.leafDataEntries.push({
1662
- leafIndex: (0, _parseInt2.default)(index, 10),
1663
- elementIds: mismatchedLeavesData[index]
1881
+ leafIndex: 0,
1882
+ elementIds: []
1664
1883
  });
1665
- });
1666
- var ourCurrentRootHash = dataSet.hashTree ? dataSet.hashTree.getRootHash() : _constants2.EMPTY_HASH;
1884
+ } else {
1885
+ var mismatchedLeavesData = options.mismatchedLeavesData;
1886
+ (0, _keys.default)(mismatchedLeavesData).forEach(function (index) {
1887
+ var leafIndex = (0, _parseInt2.default)(index, 10);
1888
+ body.leafDataEntries.push({
1889
+ leafIndex: leafIndex,
1890
+ elementIds: mismatchedLeavesData[leafIndex]
1891
+ });
1892
+ });
1893
+ }
1894
+ var ourCurrentRootHash = dataSet.hashTree ? dataSet.hashTree.getRootHash() : _constants3.EMPTY_HASH;
1667
1895
  return this.webexRequest({
1668
- method: _constants.HTTP_VERBS.POST,
1896
+ method: _constants2.HTTP_VERBS.POST,
1669
1897
  uri: url,
1670
1898
  qs: {
1671
1899
  rootHash: ourCurrentRootHash
1672
1900
  },
1673
1901
  body: body
1674
1902
  }).then(function (resp) {
1675
- _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this14.debugId, " Sync request succeeded for \"").concat(dataSet.name, "\""));
1903
+ _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this13.debugId, " Sync request succeeded for \"").concat(dataSet.name, "\""));
1676
1904
  if (!resp.body || (0, _lodash.isEmpty)(resp.body)) {
1677
- _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this14.debugId, " Got ").concat(resp.statusCode, " with empty body for sync request for data set \"").concat(dataSet.name, "\", data should arrive via messages"));
1905
+ _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this13.debugId, " Got ").concat(resp.statusCode, " with empty body for sync request for data set \"").concat(dataSet.name, "\", data should arrive via messages"));
1678
1906
  return null;
1679
1907
  }
1680
1908
  return resp.body;
1681
1909
  }).catch(function (error) {
1682
- _loggerProxy.default.logger.error("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this14.debugId, " Error ").concat(error.statusCode, " sending sync request for data set \"").concat(dataSet.name, "\":"), error);
1683
- _this14.checkForSentinelHttpResponse(error, dataSet.name);
1910
+ _loggerProxy.default.logger.error("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this13.debugId, " Error ").concat(error.statusCode, " sending sync request for data set \"").concat(dataSet.name, "\":"), error);
1911
+ _this13.checkForSentinelHttpResponse(error, dataSet.name);
1912
+ _metrics.default.sendBehavioralMetric(_constants.default.HASH_TREE_SYNC_FAILURE, {
1913
+ debugId: _this13.debugId,
1914
+ dataSetName: dataSet.name,
1915
+ request: 'POST /sync',
1916
+ statusCode: error.statusCode,
1917
+ reason: error.message
1918
+ });
1684
1919
  throw error;
1685
1920
  });
1686
1921
  }