@webex/plugin-meetings 3.11.0-next.2 → 3.11.0-next.21

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 (64) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/hashTree/hashTree.js +18 -0
  4. package/dist/hashTree/hashTree.js.map +1 -1
  5. package/dist/hashTree/hashTreeParser.js +307 -139
  6. package/dist/hashTree/hashTreeParser.js.map +1 -1
  7. package/dist/hashTree/types.js +2 -1
  8. package/dist/hashTree/types.js.map +1 -1
  9. package/dist/hashTree/utils.js +10 -0
  10. package/dist/hashTree/utils.js.map +1 -1
  11. package/dist/interpretation/index.js +1 -1
  12. package/dist/interpretation/siLanguage.js +1 -1
  13. package/dist/locus-info/index.js +55 -42
  14. package/dist/locus-info/index.js.map +1 -1
  15. package/dist/media/MediaConnectionAwaiter.js +57 -1
  16. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  17. package/dist/media/properties.js +4 -2
  18. package/dist/media/properties.js.map +1 -1
  19. package/dist/meeting/index.js +33 -22
  20. package/dist/meeting/index.js.map +1 -1
  21. package/dist/meeting/util.js +108 -2
  22. package/dist/meeting/util.js.map +1 -1
  23. package/dist/meetings/index.js +76 -26
  24. package/dist/meetings/index.js.map +1 -1
  25. package/dist/metrics/constants.js +2 -1
  26. package/dist/metrics/constants.js.map +1 -1
  27. package/dist/multistream/mediaRequestManager.js +1 -1
  28. package/dist/multistream/mediaRequestManager.js.map +1 -1
  29. package/dist/reactions/reactions.type.js.map +1 -1
  30. package/dist/types/hashTree/hashTree.d.ts +7 -0
  31. package/dist/types/hashTree/hashTreeParser.d.ts +47 -12
  32. package/dist/types/hashTree/types.d.ts +1 -0
  33. package/dist/types/hashTree/utils.d.ts +6 -0
  34. package/dist/types/locus-info/index.d.ts +9 -2
  35. package/dist/types/media/MediaConnectionAwaiter.d.ts +10 -1
  36. package/dist/types/media/properties.d.ts +2 -1
  37. package/dist/types/meeting/index.d.ts +8 -5
  38. package/dist/types/meeting/util.d.ts +28 -0
  39. package/dist/types/meetings/index.d.ts +3 -1
  40. package/dist/types/metrics/constants.d.ts +1 -0
  41. package/dist/types/reactions/reactions.type.d.ts +1 -0
  42. package/dist/webinar/index.js +1 -1
  43. package/package.json +22 -22
  44. package/src/hashTree/hashTree.ts +17 -0
  45. package/src/hashTree/hashTreeParser.ts +294 -96
  46. package/src/hashTree/types.ts +1 -0
  47. package/src/hashTree/utils.ts +9 -0
  48. package/src/locus-info/index.ts +83 -35
  49. package/src/media/MediaConnectionAwaiter.ts +41 -1
  50. package/src/media/properties.ts +3 -1
  51. package/src/meeting/index.ts +24 -11
  52. package/src/meeting/util.ts +132 -1
  53. package/src/meetings/index.ts +93 -8
  54. package/src/metrics/constants.ts +1 -0
  55. package/src/multistream/mediaRequestManager.ts +1 -1
  56. package/src/reactions/reactions.type.ts +1 -0
  57. package/test/unit/spec/hashTree/hashTree.ts +66 -0
  58. package/test/unit/spec/hashTree/hashTreeParser.ts +942 -110
  59. package/test/unit/spec/locus-info/index.js +88 -17
  60. package/test/unit/spec/media/MediaConnectionAwaiter.ts +41 -1
  61. package/test/unit/spec/media/properties.ts +12 -3
  62. package/test/unit/spec/meeting/index.js +160 -2
  63. package/test/unit/spec/meeting/utils.js +294 -22
  64. package/test/unit/spec/meetings/index.js +594 -17
@@ -5,7 +5,7 @@ var _Array$from = require("@babel/runtime-corejs2/core-js/array/from");
5
5
  var _Symbol = require("@babel/runtime-corejs2/core-js/symbol");
6
6
  var _Symbol$iterator = require("@babel/runtime-corejs2/core-js/symbol/iterator");
7
7
  var _Array$isArray2 = require("@babel/runtime-corejs2/core-js/array/is-array");
8
- var _Object$keys3 = require("@babel/runtime-corejs2/core-js/object/keys");
8
+ var _Object$keys4 = require("@babel/runtime-corejs2/core-js/object/keys");
9
9
  var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
10
10
  var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
11
11
  var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptors");
@@ -40,7 +40,7 @@ var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy")
40
40
  var _constants = require("../constants");
41
41
  var _constants2 = require("./constants");
42
42
  var _utils = require("./utils");
43
- function ownKeys(e, r) { var t = _Object$keys3(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; }
43
+ 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
44
  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; }
45
45
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && r[_Symbol$iterator] || r["@@iterator"]; if (!t) { if (_Array$isArray2(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
46
46
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
@@ -63,6 +63,11 @@ var MeetingEndedError = /*#__PURE__*/function (_Error) {
63
63
  (0, _inherits2.default)(MeetingEndedError, _Error);
64
64
  return (0, _createClass2.default)(MeetingEndedError);
65
65
  }(/*#__PURE__*/(0, _wrapNativeSuper2.default)(Error));
66
+ /* Currently Locus always sends Metadata objects only in the "self" dataset.
67
+ * If this ever changes, update all the code that relies on this constant.
68
+ */
69
+ var MetadataDataSetName = _constants2.DataSetNames.SELF;
70
+
66
71
  /**
67
72
  * Parses hash tree eventing locus data
68
73
  */
@@ -73,7 +78,7 @@ var HashTreeParser = /*#__PURE__*/function () {
73
78
  * @param {Object} options.initialLocus The initial locus data containing the hash tree information
74
79
  */
75
80
  function HashTreeParser(options) {
76
- var _locus$self;
81
+ var _locus$links, _locus$links$resource, _locus$links$resource2, _options$metadata, _options$metadata2, _options$metadata2$vi;
77
82
  (0, _classCallCheck2.default)(this, HashTreeParser);
78
83
  (0, _defineProperty2.default)(this, "dataSets", {});
79
84
  (0, _defineProperty2.default)(this, "visibleDataSetsUrl", void 0);
@@ -89,12 +94,17 @@ var HashTreeParser = /*#__PURE__*/function () {
89
94
  this.debugId = options.debugId;
90
95
  this.webexRequest = options.webexRequest;
91
96
  this.locusInfoUpdateCallback = options.locusInfoUpdateCallback;
92
- this.visibleDataSets = (locus === null || locus === void 0 ? void 0 : (_locus$self = locus.self) === null || _locus$self === void 0 ? void 0 : _locus$self.visibleDataSets) || [];
93
- if (this.visibleDataSets.length === 0) {
94
- _loggerProxy.default.logger.warn("HashTreeParser#constructor --> ".concat(this.debugId, " No visibleDataSets found in locus.self"));
97
+ this.visibleDataSetsUrl = locus === null || locus === void 0 ? void 0 : (_locus$links = locus.links) === null || _locus$links === void 0 ? void 0 : (_locus$links$resource = _locus$links.resources) === null || _locus$links$resource === void 0 ? void 0 : (_locus$links$resource2 = _locus$links$resource.visibleDataSets) === null || _locus$links$resource2 === void 0 ? void 0 : _locus$links$resource2.url;
98
+ this.visibleDataSets = (0, _lodash.cloneDeep)(((_options$metadata = options.metadata) === null || _options$metadata === void 0 ? void 0 : _options$metadata.visibleDataSets) || []);
99
+ if (((_options$metadata2 = options.metadata) === null || _options$metadata2 === void 0 ? void 0 : (_options$metadata2$vi = _options$metadata2.visibleDataSets) === null || _options$metadata2$vi === void 0 ? void 0 : _options$metadata2$vi.length) === 0) {
100
+ _loggerProxy.default.logger.warn("HashTreeParser#constructor --> ".concat(this.debugId, " No visibleDataSets found in Metadata"));
95
101
  }
96
102
  // object mapping dataset names to arrays of leaf data
97
103
  var leafData = this.analyzeLocusHtMeta(locus);
104
+ if (options.metadata) {
105
+ // add also the metadata that's outside of locus object itself
106
+ this.analyzeMetadata(leafData, options.metadata);
107
+ }
98
108
  _loggerProxy.default.logger.info("HashTreeParser#constructor --> creating HashTreeParser for datasets: ".concat((0, _stringify.default)(dataSets.map(function (ds) {
99
109
  return ds.name;
100
110
  }))));
@@ -106,7 +116,7 @@ var HashTreeParser = /*#__PURE__*/function () {
106
116
  var name = dataSet.name,
107
117
  leafCount = dataSet.leafCount;
108
118
  this.dataSets[name] = _objectSpread(_objectSpread({}, dataSet), {}, {
109
- hashTree: this.visibleDataSets.includes(name) ? new _hashTree.default(leafData[name] || [], leafCount) : undefined
119
+ hashTree: this.isVisibleDataSet(name) ? new _hashTree.default(leafData[name] || [], leafCount) : undefined
110
120
  });
111
121
  }
112
122
  } catch (err) {
@@ -117,30 +127,44 @@ var HashTreeParser = /*#__PURE__*/function () {
117
127
  }
118
128
 
119
129
  /**
120
- * Initializes a new visible data set by creating a hash tree for it, adding it to all the internal structures,
121
- * and sending an initial sync request to Locus with empty leaf data - that will trigger Locus to gives us all the data
122
- * from that dataset (in the response or via messages).
123
- *
124
- * @param {DataSet} dataSet The new data set to be added
125
- * @returns {Promise}
130
+ * Checks if the given data set name is in the list of visible data sets
131
+ * @param {string} dataSetName data set name to check
132
+ * @returns {Boolean} True if the data set is visible, false otherwise
126
133
  */
127
134
  return (0, _createClass2.default)(HashTreeParser, [{
135
+ key: "isVisibleDataSet",
136
+ value: function isVisibleDataSet(dataSetName) {
137
+ return this.visibleDataSets.some(function (vds) {
138
+ return vds.name === dataSetName;
139
+ });
140
+ }
141
+
142
+ /**
143
+ * Initializes a new visible data set by creating a hash tree for it, adding it to all the internal structures,
144
+ * and sending an initial sync request to Locus with empty leaf data - that will trigger Locus to gives us all the data
145
+ * from that dataset (in the response or via messages).
146
+ *
147
+ * @param {VisibleDataSetInfo} visibleDataSetInfo Information about the new visible data set
148
+ * @param {DataSet} dataSetInfo The new data set to be added
149
+ * @returns {Promise}
150
+ */
151
+ }, {
128
152
  key: "initializeNewVisibleDataSet",
129
- value: function initializeNewVisibleDataSet(dataSet) {
130
- if (this.visibleDataSets.includes(dataSet.name)) {
131
- _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Data set \"").concat(dataSet.name, "\" already exists, skipping init"));
153
+ value: function initializeNewVisibleDataSet(visibleDataSetInfo, dataSetInfo) {
154
+ if (this.isVisibleDataSet(dataSetInfo.name)) {
155
+ _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Data set \"").concat(dataSetInfo.name, "\" already exists, skipping init"));
132
156
  return _promise.default.resolve({
133
157
  updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
134
158
  updatedObjects: []
135
159
  });
136
160
  }
137
- _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Adding visible data set \"").concat(dataSet.name, "\""));
138
- this.visibleDataSets.push(dataSet.name);
139
- var hashTree = new _hashTree.default([], dataSet.leafCount);
140
- this.dataSets[dataSet.name] = _objectSpread(_objectSpread({}, dataSet), {}, {
161
+ _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSet --> ".concat(this.debugId, " Adding visible data set \"").concat(dataSetInfo.name, "\""));
162
+ this.visibleDataSets.push(visibleDataSetInfo);
163
+ var hashTree = new _hashTree.default([], dataSetInfo.leafCount);
164
+ this.dataSets[dataSetInfo.name] = _objectSpread(_objectSpread({}, dataSetInfo), {}, {
141
165
  hashTree: hashTree
142
166
  });
143
- return this.sendInitializationSyncRequestToLocus(dataSet.name, 'new visible data set');
167
+ return this.sendInitializationSyncRequestToLocus(dataSetInfo.name, 'new visible data set');
144
168
  }
145
169
 
146
170
  /**
@@ -173,17 +197,20 @@ var HashTreeParser = /*#__PURE__*/function () {
173
197
  }
174
198
 
175
199
  /**
176
- * Queries Locus for information about all the data sets
200
+ * Queries Locus for all up-to-date information about all visible data sets
177
201
  *
178
- * @param {string} url - url from which we can get info about all data sets
179
202
  * @returns {Promise}
180
203
  */
181
204
  }, {
182
- key: "getAllDataSetsMetadata",
183
- value: function getAllDataSetsMetadata(url) {
205
+ key: "getAllVisibleDataSetsFromLocus",
206
+ value: function getAllVisibleDataSetsFromLocus() {
207
+ if (!this.visibleDataSetsUrl) {
208
+ _loggerProxy.default.logger.warn("HashTreeParser#getAllVisibleDataSetsFromLocus --> ".concat(this.debugId, " No visibleDataSetsUrl, cannot get data sets information"));
209
+ return _promise.default.resolve([]);
210
+ }
184
211
  return this.webexRequest({
185
212
  method: _constants.HTTP_VERBS.GET,
186
- uri: url
213
+ uri: this.visibleDataSetsUrl
187
214
  }).then(function (response) {
188
215
  return response.body.dataSets;
189
216
  });
@@ -199,17 +226,18 @@ var HashTreeParser = /*#__PURE__*/function () {
199
226
  key: "initializeFromMessage",
200
227
  value: (function () {
201
228
  var _initializeFromMessage = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(message) {
202
- var dataSets;
229
+ var visibleDataSets;
203
230
  return _regenerator.default.wrap(function (_context) {
204
231
  while (1) switch (_context.prev = _context.next) {
205
232
  case 0:
206
- _loggerProxy.default.logger.info("HashTreeParser#initializeFromMessage --> ".concat(this.debugId, " visibleDataSetsUrl=").concat(message.visibleDataSetsUrl));
233
+ this.visibleDataSetsUrl = message.visibleDataSetsUrl;
234
+ _loggerProxy.default.logger.info("HashTreeParser#initializeFromMessage --> ".concat(this.debugId, " visibleDataSetsUrl=").concat(this.visibleDataSetsUrl));
207
235
  _context.next = 1;
208
- return this.getAllDataSetsMetadata(message.visibleDataSetsUrl);
236
+ return this.getAllVisibleDataSetsFromLocus();
209
237
  case 1:
210
- dataSets = _context.sent;
238
+ visibleDataSets = _context.sent;
211
239
  _context.next = 2;
212
- return this.initializeDataSets(dataSets, 'initialization from message');
240
+ return this.initializeDataSets(visibleDataSets, 'initialization from message');
213
241
  case 2:
214
242
  case "end":
215
243
  return _context.stop();
@@ -235,25 +263,26 @@ var HashTreeParser = /*#__PURE__*/function () {
235
263
  key: "initializeFromGetLociResponse",
236
264
  value: (function () {
237
265
  var _initializeFromGetLociResponse = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2(locus) {
238
- var _locus$links, _locus$links$resource, _locus$links$resource2;
239
- var dataSets;
266
+ var _locus$links2, _locus$links2$resourc, _locus$links2$resourc2;
267
+ var visibleDataSets;
240
268
  return _regenerator.default.wrap(function (_context2) {
241
269
  while (1) switch (_context2.prev = _context2.next) {
242
270
  case 0:
243
- if (locus !== null && locus !== void 0 && (_locus$links = locus.links) !== null && _locus$links !== void 0 && (_locus$links$resource = _locus$links.resources) !== null && _locus$links$resource !== void 0 && (_locus$links$resource2 = _locus$links$resource.visibleDataSets) !== null && _locus$links$resource2 !== void 0 && _locus$links$resource2.url) {
271
+ 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) {
244
272
  _context2.next = 1;
245
273
  break;
246
274
  }
247
275
  _loggerProxy.default.logger.warn("HashTreeParser#initializeFromGetLociResponse --> ".concat(this.debugId, " missing visibleDataSets url in GET Loci response, cannot initialize hash trees"));
248
276
  return _context2.abrupt("return");
249
277
  case 1:
250
- _loggerProxy.default.logger.info("HashTreeParser#initializeFromGetLociResponse --> ".concat(this.debugId, " visibleDataSets url: ").concat(locus.links.resources.visibleDataSets.url));
278
+ this.visibleDataSetsUrl = locus.links.resources.visibleDataSets.url;
279
+ _loggerProxy.default.logger.info("HashTreeParser#initializeFromGetLociResponse --> ".concat(this.debugId, " visibleDataSets url: ").concat(this.visibleDataSetsUrl));
251
280
  _context2.next = 2;
252
- return this.getAllDataSetsMetadata(locus.links.resources.visibleDataSets.url);
281
+ return this.getAllVisibleDataSetsFromLocus();
253
282
  case 2:
254
- dataSets = _context2.sent;
283
+ visibleDataSets = _context2.sent;
255
284
  _context2.next = 3;
256
- return this.initializeDataSets(dataSets, 'initialization from GET /loci response');
285
+ return this.initializeDataSets(visibleDataSets, 'initialization from GET /loci response');
257
286
  case 3:
258
287
  case "end":
259
288
  return _context2.stop();
@@ -268,7 +297,7 @@ var HashTreeParser = /*#__PURE__*/function () {
268
297
  /**
269
298
  * Initializes data sets by doing an initialization sync on each visible data set that doesn't have a hash tree yet.
270
299
  *
271
- * @param {DataSet[]} dataSets Array of DataSet objects to initialize
300
+ * @param {DataSet[]} visibleDataSets Array of visible DataSet objects to initialize
272
301
  * @param {string} debugText Text to include in logs for debugging purposes
273
302
  * @returns {Promise}
274
303
  */
@@ -276,13 +305,13 @@ var HashTreeParser = /*#__PURE__*/function () {
276
305
  }, {
277
306
  key: "initializeDataSets",
278
307
  value: (function () {
279
- var _initializeDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(dataSets, debugText) {
280
- var updatedObjects, _iterator2, _step2, dataSet, name, leafCount, _data, _t;
308
+ var _initializeDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(visibleDataSets, debugText) {
309
+ var updatedObjects, _iterator2, _step2, dataSet, name, leafCount, url, _data, _t;
281
310
  return _regenerator.default.wrap(function (_context3) {
282
311
  while (1) switch (_context3.prev = _context3.next) {
283
312
  case 0:
284
313
  updatedObjects = [];
285
- _iterator2 = _createForOfIteratorHelper(dataSets);
314
+ _iterator2 = _createForOfIteratorHelper(visibleDataSets);
286
315
  _context3.prev = 1;
287
316
  _iterator2.s();
288
317
  case 2:
@@ -291,14 +320,20 @@ var HashTreeParser = /*#__PURE__*/function () {
291
320
  break;
292
321
  }
293
322
  dataSet = _step2.value;
294
- name = dataSet.name, leafCount = dataSet.leafCount;
323
+ name = dataSet.name, leafCount = dataSet.leafCount, url = dataSet.url;
295
324
  if (!this.dataSets[name]) {
296
325
  _loggerProxy.default.logger.info("HashTreeParser#initializeDataSets --> ".concat(this.debugId, " initializing dataset \"").concat(name, "\" (").concat(debugText, ")"));
297
326
  this.dataSets[name] = _objectSpread({}, dataSet);
298
327
  } else {
299
328
  _loggerProxy.default.logger.info("HashTreeParser#initializeDataSets --> ".concat(this.debugId, " dataset \"").concat(name, "\" already exists (").concat(debugText, ")"));
300
329
  }
301
- if (!(this.visibleDataSets.includes(name) && !this.dataSets[name].hashTree)) {
330
+ if (!this.isVisibleDataSet(name)) {
331
+ this.visibleDataSets.push({
332
+ name: name,
333
+ url: url
334
+ });
335
+ }
336
+ if (this.dataSets[name].hashTree) {
302
337
  _context3.next = 5;
303
338
  break;
304
339
  }
@@ -434,6 +469,38 @@ var HashTreeParser = /*#__PURE__*/function () {
434
469
  return leafInfo;
435
470
  }
436
471
 
472
+ /**
473
+ * Analyzes the Metadata object that is sent outside of Locus object, and appends its data to passed in leafInfo
474
+ * structure.
475
+ *
476
+ * @param {Record<string, LeafInfo[]>} leafInfo the structure to which the Metadata info will be appended
477
+ * @param {Metadata} metadata Metadata object
478
+ * @returns {void}
479
+ */
480
+ }, {
481
+ key: "analyzeMetadata",
482
+ value: function analyzeMetadata(leafInfo, metadata) {
483
+ var _htMeta$dataSetNames;
484
+ var htMeta = metadata.htMeta;
485
+ if ((htMeta === null || htMeta === void 0 ? void 0 : (_htMeta$dataSetNames = htMeta.dataSetNames) === null || _htMeta$dataSetNames === void 0 ? void 0 : _htMeta$dataSetNames.length) === 1 && htMeta.dataSetNames[0].toLowerCase() === MetadataDataSetName) {
486
+ var _metadata$htMeta$elem = metadata.htMeta.elementId,
487
+ type = _metadata$htMeta$elem.type,
488
+ id = _metadata$htMeta$elem.id,
489
+ version = _metadata$htMeta$elem.version;
490
+ var dataSetName = htMeta.dataSetNames[0];
491
+ if (!leafInfo[dataSetName]) {
492
+ leafInfo[dataSetName] = [];
493
+ }
494
+ leafInfo[dataSetName].push({
495
+ type: type,
496
+ id: id,
497
+ version: version
498
+ });
499
+ } else {
500
+ throw new Error("".concat(this.debugId, " Metadata htMeta has unexpected dataSetNames: ").concat(htMeta && htMeta.dataSetNames.join(',')));
501
+ }
502
+ }
503
+
437
504
  /**
438
505
  * Checks if the provided hash tree message indicates the end of the meeting and that there won't be any more updates.
439
506
  *
@@ -482,6 +549,51 @@ var HashTreeParser = /*#__PURE__*/function () {
482
549
  });
483
550
  }
484
551
 
552
+ /**
553
+ * Handles updates to Metadata object that we receive from Locus via other means than messages. Right now
554
+ * that means only in the API response alongside locus object.
555
+ *
556
+ * @param {Metadata} metadata received in Locus update other than a message (for example in an API response)
557
+ * @param {HashTreeObject[]} updatedObjects a list of updated hash tree objects to which any updates resulting from new Metadata will be added
558
+ * @returns {void}
559
+ */
560
+ }, {
561
+ key: "handleMetadataUpdate",
562
+ value: function handleMetadataUpdate(metadata, updatedObjects) {
563
+ var _this$dataSets$Metada,
564
+ _this3 = this;
565
+ var dataSetsRequiringInitialization = [];
566
+
567
+ // current assumption based on Locus docs is that Metadata object lives always in "self" data set
568
+ var hashTree = (_this$dataSets$Metada = this.dataSets[MetadataDataSetName]) === null || _this$dataSets$Metada === void 0 ? void 0 : _this$dataSets$Metada.hashTree;
569
+ if (!hashTree) {
570
+ _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(this.debugId, " received Metadata object but no hash tree for \"").concat(MetadataDataSetName, "\" data set exists"));
571
+ } else {
572
+ var metadataUpdated = hashTree.putItem(metadata.htMeta.elementId);
573
+ if (metadataUpdated) {
574
+ // metadata in Locus API response is in a slightly different format than the objects in messages, so need to adapt it
575
+ var metadataObject = {
576
+ htMeta: metadata.htMeta,
577
+ data: metadata
578
+ };
579
+ updatedObjects.push(metadataObject);
580
+ var _this$checkForVisible = this.checkForVisibleDataSetChanges([metadataObject]),
581
+ changeDetected = _this$checkForVisible.changeDetected,
582
+ removedDataSets = _this$checkForVisible.removedDataSets,
583
+ addedDataSets = _this$checkForVisible.addedDataSets;
584
+ if (changeDetected) {
585
+ dataSetsRequiringInitialization = this.processVisibleDataSetChanges(removedDataSets, addedDataSets, updatedObjects);
586
+ }
587
+ if (dataSetsRequiringInitialization.length > 0) {
588
+ // there are some data sets that we need to initialize asynchronously
589
+ queueMicrotask(function () {
590
+ _this3.initializeNewVisibleDataSets(dataSetsRequiringInitialization);
591
+ });
592
+ }
593
+ }
594
+ }
595
+ }
596
+
485
597
  /**
486
598
  * This method should be called when we receive a partial locus DTO that contains dataSets and htMeta information
487
599
  * It updates the hash trees with the new leaf data based on the received Locus
@@ -492,9 +604,10 @@ var HashTreeParser = /*#__PURE__*/function () {
492
604
  }, {
493
605
  key: "handleLocusUpdate",
494
606
  value: function handleLocusUpdate(update) {
495
- var _this3 = this;
607
+ var _this4 = this;
496
608
  var dataSets = update.dataSets,
497
- locus = update.locus;
609
+ locus = update.locus,
610
+ metadata = update.metadata;
498
611
  if (!dataSets) {
499
612
  _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(this.debugId, " received hash tree update without dataSets"));
500
613
  }
@@ -517,11 +630,16 @@ var HashTreeParser = /*#__PURE__*/function () {
517
630
  copyData: true
518
631
  });
519
632
 
633
+ // if we got metadata, process it (currently that means only potential visible data set list changes)
634
+ if (metadata) {
635
+ this.handleMetadataUpdate(metadata, updatedObjects);
636
+ }
637
+
520
638
  // then process the data in hash trees, if it is a new version, then add it to updatedObjects
521
639
  (0, _keys.default)(leafInfo).forEach(function (dataSetName) {
522
- if (_this3.dataSets[dataSetName]) {
523
- if (_this3.dataSets[dataSetName].hashTree) {
524
- var appliedChangesList = _this3.dataSets[dataSetName].hashTree.putItems(leafInfo[dataSetName].map(function (leaf) {
640
+ if (_this4.dataSets[dataSetName]) {
641
+ if (_this4.dataSets[dataSetName].hashTree) {
642
+ var appliedChangesList = _this4.dataSets[dataSetName].hashTree.putItems(leafInfo[dataSetName].map(function (leaf) {
525
643
  return {
526
644
  id: leaf.id,
527
645
  type: leaf.type,
@@ -548,10 +666,10 @@ var HashTreeParser = /*#__PURE__*/function () {
548
666
  });
549
667
  } else {
550
668
  // no hash tree means that the data set is not visible
551
- _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(_this3.debugId, " received leaf data for data set \"").concat(dataSetName, "\" that has no hash tree created, ignoring"));
669
+ _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(_this4.debugId, " received leaf data for data set \"").concat(dataSetName, "\" that has no hash tree created, ignoring"));
552
670
  }
553
671
  } else {
554
- _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(_this3.debugId, " received leaf data for unknown data set \"").concat(dataSetName, "\", ignoring"));
672
+ _loggerProxy.default.logger.warn("HashTreeParser#handleLocusUpdate --> ".concat(_this4.debugId, " received leaf data for unknown data set \"").concat(dataSetName, "\", ignoring"));
555
673
  }
556
674
  });
557
675
  if (updatedObjects.length === 0) {
@@ -562,9 +680,6 @@ var HashTreeParser = /*#__PURE__*/function () {
562
680
  updatedObjects: updatedObjects
563
681
  });
564
682
  }
565
-
566
- // todo: once Locus design on how visible data sets will be communicated in subsequent API responses is confirmed,
567
- // we'll need to check here if visible data sets have changed and update this.visibleDataSets, remove/create hash trees etc
568
683
  }
569
684
 
570
685
  /**
@@ -578,7 +693,7 @@ var HashTreeParser = /*#__PURE__*/function () {
578
693
  value: function updateDataSetInfo(receivedDataSet) {
579
694
  if (!this.dataSets[receivedDataSet.name]) {
580
695
  this.dataSets[receivedDataSet.name] = _objectSpread({}, receivedDataSet);
581
- _loggerProxy.default.logger.info("HashTreeParser#handleMessage --> ".concat(this.debugId, " created entry for \"").concat(receivedDataSet.name, "\" dataset: version=").concat(receivedDataSet.version, ", root=").concat(receivedDataSet.root));
696
+ _loggerProxy.default.logger.info("HashTreeParser#updateDataSetInfo --> ".concat(this.debugId, " created entry for \"").concat(receivedDataSet.name, "\" dataset: version=").concat(receivedDataSet.version, ", root=").concat(receivedDataSet.root));
582
697
  return;
583
698
  }
584
699
  // update our version of the dataSet
@@ -590,7 +705,7 @@ var HashTreeParser = /*#__PURE__*/function () {
590
705
  maxMs: receivedDataSet.backoff.maxMs,
591
706
  exponent: receivedDataSet.backoff.exponent
592
707
  };
593
- _loggerProxy.default.logger.info("HashTreeParser#handleMessage --> ".concat(this.debugId, " updated \"").concat(receivedDataSet.name, "\" to version=").concat(receivedDataSet.version, ", root=").concat(receivedDataSet.root));
708
+ _loggerProxy.default.logger.info("HashTreeParser#updateDataSetInfo --> ".concat(this.debugId, " updated \"").concat(receivedDataSet.name, "\" dataset to version=").concat(receivedDataSet.version, ", root=").concat(receivedDataSet.root));
594
709
  }
595
710
  }
596
711
 
@@ -602,24 +717,31 @@ var HashTreeParser = /*#__PURE__*/function () {
602
717
  }, {
603
718
  key: "checkForVisibleDataSetChanges",
604
719
  value: function checkForVisibleDataSetChanges(updatedObjects) {
605
- var _this4 = this;
720
+ var _this5 = this;
606
721
  var removedDataSets = [];
607
722
  var addedDataSets = [];
608
723
 
609
- // visibleDataSets can only be changed by self object updates
724
+ // visibleDataSets can only be changed by Metadata object updates
610
725
  updatedObjects.forEach(function (object) {
611
726
  var _object$data;
612
- // todo: in the future visibleDataSets will be in "Metadata" object, not in "self"
613
- if ((0, _utils.isSelf)(object) && (_object$data = object.data) !== null && _object$data !== void 0 && _object$data.visibleDataSets) {
727
+ if ((0, _utils.isMetadata)(object) && (_object$data = object.data) !== null && _object$data !== void 0 && _object$data.visibleDataSets) {
614
728
  var newVisibleDataSets = object.data.visibleDataSets;
615
- removedDataSets = _this4.visibleDataSets.filter(function (ds) {
616
- return !newVisibleDataSets.includes(ds);
729
+ removedDataSets = _this5.visibleDataSets.filter(function (ds) {
730
+ return !newVisibleDataSets.some(function (nvs) {
731
+ return nvs.name === ds.name;
732
+ });
617
733
  });
618
- addedDataSets = newVisibleDataSets.filter(function (ds) {
619
- return !_this4.visibleDataSets.includes(ds);
734
+ addedDataSets = newVisibleDataSets.filter(function (nvs) {
735
+ return _this5.visibleDataSets.every(function (ds) {
736
+ return ds.name !== nvs.name;
737
+ });
620
738
  });
621
739
  if (removedDataSets.length > 0 || addedDataSets.length > 0) {
622
- _loggerProxy.default.logger.info("HashTreeParser#checkForVisibleDataSetChanges --> ".concat(_this4.debugId, " visible data sets change: removed: ").concat(removedDataSets.join(', '), ", added: ").concat(addedDataSets.join(', ')));
740
+ _loggerProxy.default.logger.info("HashTreeParser#checkForVisibleDataSetChanges --> ".concat(_this5.debugId, " visible data sets change: removed: ").concat(removedDataSets.map(function (ds) {
741
+ return ds.name;
742
+ }).join(', '), ", added: ").concat(addedDataSets.map(function (ds) {
743
+ return ds.name;
744
+ }).join(', ')));
623
745
  }
624
746
  }
625
747
  });
@@ -657,38 +779,40 @@ var HashTreeParser = /*#__PURE__*/function () {
657
779
  * visible data sets and they require async initialization, the names of these data sets
658
780
  * are returned in an array.
659
781
  *
660
- * @param {string[]} removedDataSets - The list of removed data sets.
661
- * @param {string[]} addedDataSets - The list of added data sets.
782
+ * @param {VisibleDataSetInfo[]} removedDataSets - The list of removed data sets.
783
+ * @param {VisibleDataSetInfo[]} addedDataSets - The list of added data sets.
662
784
  * @param {HashTreeObject[]} updatedObjects - The list of updated hash tree objects to which changes will be added.
663
- * @returns {string[]} names of data sets that couldn't be initialized synchronously
785
+ * @returns {VisibleDataSetInfo[]} list of data sets that couldn't be initialized synchronously
664
786
  */
665
787
  }, {
666
788
  key: "processVisibleDataSetChanges",
667
789
  value: function processVisibleDataSetChanges(removedDataSets, addedDataSets, updatedObjects) {
668
- var _this5 = this;
790
+ var _this6 = this;
669
791
  var dataSetsRequiringInitialization = [];
670
792
 
671
793
  // if a visible data set was removed, we need to tell our client that all objects from it are removed
672
794
  var removedObjects = [];
673
795
  removedDataSets.forEach(function (ds) {
674
- var _this5$dataSets$ds;
675
- if ((_this5$dataSets$ds = _this5.dataSets[ds]) !== null && _this5$dataSets$ds !== void 0 && _this5$dataSets$ds.hashTree) {
676
- for (var i = 0; i < _this5.dataSets[ds].hashTree.numLeaves; i += 1) {
677
- removedObjects.push.apply(removedObjects, (0, _toConsumableArray2.default)(_this5.dataSets[ds].hashTree.getLeafData(i).map(function (elementId) {
796
+ var _this6$dataSets$ds$na;
797
+ if ((_this6$dataSets$ds$na = _this6.dataSets[ds.name]) !== null && _this6$dataSets$ds$na !== void 0 && _this6$dataSets$ds$na.hashTree) {
798
+ for (var i = 0; i < _this6.dataSets[ds.name].hashTree.numLeaves; i += 1) {
799
+ removedObjects.push.apply(removedObjects, (0, _toConsumableArray2.default)(_this6.dataSets[ds.name].hashTree.getLeafData(i).map(function (elementId) {
678
800
  return {
679
801
  htMeta: {
680
802
  elementId: elementId,
681
- dataSetNames: [ds]
803
+ dataSetNames: [ds.name]
682
804
  },
683
805
  data: null
684
806
  };
685
807
  })));
686
808
  }
687
- _this5.deleteHashTree(ds);
809
+ _this6.deleteHashTree(ds.name);
688
810
  }
689
811
  });
690
812
  this.visibleDataSets = this.visibleDataSets.filter(function (vds) {
691
- return !removedDataSets.includes(vds);
813
+ return !removedDataSets.some(function (rds) {
814
+ return rds.name === vds.name;
815
+ });
692
816
  });
693
817
  updatedObjects.push.apply(updatedObjects, removedObjects);
694
818
 
@@ -698,22 +822,22 @@ var HashTreeParser = /*#__PURE__*/function () {
698
822
  try {
699
823
  for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
700
824
  var ds = _step6.value;
701
- var dataSetInfo = this.dataSets[ds];
825
+ var dataSetInfo = this.dataSets[ds.name];
702
826
  if (dataSetInfo) {
703
- if (this.visibleDataSets.includes(dataSetInfo.name)) {
704
- _loggerProxy.default.logger.info("HashTreeParser#processVisibleDataSetChanges --> ".concat(this.debugId, " Data set \"").concat(ds, "\" is already visible, skipping"));
827
+ if (this.isVisibleDataSet(dataSetInfo.name)) {
828
+ _loggerProxy.default.logger.info("HashTreeParser#processVisibleDataSetChanges --> ".concat(this.debugId, " Data set \"").concat(ds.name, "\" is already visible, skipping"));
705
829
 
706
830
  // eslint-disable-next-line no-continue
707
831
  continue;
708
832
  }
709
- _loggerProxy.default.logger.info("HashTreeParser#processVisibleDataSetChanges --> ".concat(this.debugId, " Adding visible data set \"").concat(ds, "\""));
833
+ _loggerProxy.default.logger.info("HashTreeParser#processVisibleDataSetChanges --> ".concat(this.debugId, " Adding visible data set \"").concat(ds.name, "\""));
710
834
  this.visibleDataSets.push(ds);
711
835
  var hashTree = new _hashTree.default([], dataSetInfo.leafCount);
712
836
  this.dataSets[dataSetInfo.name] = _objectSpread(_objectSpread({}, dataSetInfo), {}, {
713
837
  hashTree: hashTree
714
838
  });
715
839
  } else {
716
- _loggerProxy.default.logger.info("HashTreeParser#processVisibleDataSetChanges --> ".concat(this.debugId, " visible data set \"").concat(ds, "\" added but no info about it in our dataSets structures"));
840
+ _loggerProxy.default.logger.info("HashTreeParser#processVisibleDataSetChanges --> ".concat(this.debugId, " visible data set \"").concat(ds.name, "\" added but no info about it in our dataSets structures"));
717
841
  // todo: add a metric here
718
842
  dataSetsRequiringInitialization.push(ds);
719
843
  }
@@ -730,21 +854,20 @@ var HashTreeParser = /*#__PURE__*/function () {
730
854
  * Adds entries to the passed in updateObjects array
731
855
  * for the changes that result from adding and removing visible data sets.
732
856
  *
733
- * @param {HashTreeMessage} message - The hash tree message that triggered the visible data set changes.
734
- * @param {string[]} addedDataSets - The list of added data sets.
857
+ * @param {VisibleDataSetInfo[]} addedDataSets - The list of added data sets.
735
858
  * @returns {Promise<void>}
736
859
  */
737
860
  }, {
738
861
  key: "initializeNewVisibleDataSets",
739
862
  value: (function () {
740
- var _initializeNewVisibleDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4(message, addedDataSets) {
741
- var _this6 = this;
863
+ var _initializeNewVisibleDataSets = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4(addedDataSets) {
864
+ var _this7 = this;
742
865
  var allDataSets, _iterator7, _step7, _loop, _t2;
743
866
  return _regenerator.default.wrap(function (_context5) {
744
867
  while (1) switch (_context5.prev = _context5.next) {
745
868
  case 0:
746
869
  _context5.next = 1;
747
- return this.getAllDataSetsMetadata(message.visibleDataSetsUrl);
870
+ return this.getAllVisibleDataSetsFromLocus();
748
871
  case 1:
749
872
  allDataSets = _context5.sent;
750
873
  _iterator7 = _createForOfIteratorHelper(addedDataSets);
@@ -756,22 +879,22 @@ var HashTreeParser = /*#__PURE__*/function () {
756
879
  case 0:
757
880
  ds = _step7.value;
758
881
  dataSetInfo = allDataSets.find(function (d) {
759
- return d.name === ds;
882
+ return d.name === ds.name;
760
883
  });
761
- _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSets --> ".concat(_this6.debugId, " initializing data set \"").concat(ds, "\""));
884
+ _loggerProxy.default.logger.info("HashTreeParser#initializeNewVisibleDataSets --> ".concat(_this7.debugId, " initializing data set \"").concat(ds.name, "\""));
762
885
  if (dataSetInfo) {
763
886
  _context4.next = 1;
764
887
  break;
765
888
  }
766
- _loggerProxy.default.logger.warn("HashTreeParser#handleHashTreeMessage --> ".concat(_this6.debugId, " missing info about data set \"").concat(ds, "\" in Locus response from visibleDataSetsUrl"));
889
+ _loggerProxy.default.logger.warn("HashTreeParser#handleHashTreeMessage --> ".concat(_this7.debugId, " missing info about data set \"").concat(ds.name, "\" in Locus response from visibleDataSetsUrl"));
767
890
  _context4.next = 3;
768
891
  break;
769
892
  case 1:
770
893
  _context4.next = 2;
771
- return _this6.initializeNewVisibleDataSet(dataSetInfo);
894
+ return _this7.initializeNewVisibleDataSet(ds, dataSetInfo);
772
895
  case 2:
773
896
  updates = _context4.sent;
774
- _this6.callLocusInfoUpdateCallback(updates);
897
+ _this7.callLocusInfoUpdateCallback(updates);
775
898
  case 3:
776
899
  case "end":
777
900
  return _context4.stop();
@@ -805,7 +928,7 @@ var HashTreeParser = /*#__PURE__*/function () {
805
928
  }
806
929
  }, _callee4, this, [[2, 6, 7, 8]]);
807
930
  }));
808
- function initializeNewVisibleDataSets(_x5, _x6) {
931
+ function initializeNewVisibleDataSets(_x5) {
809
932
  return _initializeNewVisibleDataSets.apply(this, arguments);
810
933
  }
811
934
  return initializeNewVisibleDataSets;
@@ -823,8 +946,8 @@ var HashTreeParser = /*#__PURE__*/function () {
823
946
  value: (function () {
824
947
  var _parseMessage = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5(message, debugText) {
825
948
  var _message$locusStateEl,
826
- _this7 = this;
827
- var dataSets, visibleDataSetsUrl, isRosterDropped, updatedObjects, dataSetsRequiringInitialization, selfUpdates, updatedSelfObjects, _this$checkForVisible, changeDetected, removedDataSets, addedDataSets;
949
+ _this8 = this;
950
+ var dataSets, visibleDataSetsUrl, isRosterDropped, updatedObjects, dataSetsRequiringInitialization, metadataUpdates, updatedMetadataObjects, _this$checkForVisible2, changeDetected, removedDataSets, addedDataSets;
828
951
  return _regenerator.default.wrap(function (_context6) {
829
952
  while (1) switch (_context6.prev = _context6.next) {
830
953
  case 0:
@@ -838,7 +961,7 @@ var HashTreeParser = /*#__PURE__*/function () {
838
961
  // first, update our metadata about the datasets with info from the message
839
962
  this.visibleDataSetsUrl = visibleDataSetsUrl;
840
963
  dataSets.forEach(function (dataSet) {
841
- return _this7.updateDataSetInfo(dataSet);
964
+ return _this8.updateDataSetInfo(dataSet);
842
965
  });
843
966
  if (!this.isEndMessage(message)) {
844
967
  _context6.next = 1;
@@ -853,27 +976,24 @@ var HashTreeParser = /*#__PURE__*/function () {
853
976
  isRosterDropped = false;
854
977
  updatedObjects = []; // when we detect new visible datasets, it may be that the metadata about them is not
855
978
  // available in the message, they will require separate async initialization
856
- dataSetsRequiringInitialization = []; // first find out if there are any visible data set changes - they're signalled in SELF object updates
857
- selfUpdates = (message.locusStateElements || []).filter(function (object) {
858
- return (
859
- // todo: SPARK-744859 once Locus supports it, we will filter for "Metadata" type here instead of "self"
860
- (0, _utils.isSelf)(object)
861
- );
979
+ dataSetsRequiringInitialization = []; // first find out if there are any visible data set changes - they're signalled in Metadata object updates
980
+ metadataUpdates = (message.locusStateElements || []).filter(function (object) {
981
+ return (0, _utils.isMetadata)(object);
862
982
  });
863
- if (selfUpdates.length > 0) {
864
- updatedSelfObjects = [];
865
- selfUpdates.forEach(function (object) {
983
+ if (metadataUpdates.length > 0) {
984
+ updatedMetadataObjects = [];
985
+ metadataUpdates.forEach(function (object) {
866
986
  // todo: once Locus supports it, we will use the "view" field here instead of dataSetNames
867
987
  var _iterator8 = _createForOfIteratorHelper(object.htMeta.dataSetNames),
868
988
  _step8;
869
989
  try {
870
990
  for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
871
- var _this7$dataSets$dataS;
991
+ var _this8$dataSets$dataS;
872
992
  var dataSetName = _step8.value;
873
- var hashTree = (_this7$dataSets$dataS = _this7.dataSets[dataSetName]) === null || _this7$dataSets$dataS === void 0 ? void 0 : _this7$dataSets$dataS.hashTree;
993
+ var hashTree = (_this8$dataSets$dataS = _this8.dataSets[dataSetName]) === null || _this8$dataSets$dataS === void 0 ? void 0 : _this8$dataSets$dataS.hashTree;
874
994
  if (hashTree && object.data) {
875
995
  if (hashTree.putItem(object.htMeta.elementId)) {
876
- updatedSelfObjects.push(object);
996
+ updatedMetadataObjects.push(object);
877
997
  }
878
998
  }
879
999
  }
@@ -883,8 +1003,8 @@ var HashTreeParser = /*#__PURE__*/function () {
883
1003
  _iterator8.f();
884
1004
  }
885
1005
  });
886
- updatedObjects.push.apply(updatedObjects, updatedSelfObjects);
887
- _this$checkForVisible = this.checkForVisibleDataSetChanges(updatedSelfObjects), changeDetected = _this$checkForVisible.changeDetected, removedDataSets = _this$checkForVisible.removedDataSets, addedDataSets = _this$checkForVisible.addedDataSets;
1006
+ updatedObjects.push.apply(updatedObjects, updatedMetadataObjects);
1007
+ _this$checkForVisible2 = this.checkForVisibleDataSetChanges(updatedMetadataObjects), changeDetected = _this$checkForVisible2.changeDetected, removedDataSets = _this$checkForVisible2.removedDataSets, addedDataSets = _this$checkForVisible2.addedDataSets;
888
1008
  if (changeDetected) {
889
1009
  dataSetsRequiringInitialization = this.processVisibleDataSetChanges(removedDataSets, addedDataSets, updatedObjects);
890
1010
  }
@@ -894,8 +1014,8 @@ var HashTreeParser = /*#__PURE__*/function () {
894
1014
  // and hash trees created for the new visible data sets,
895
1015
  // so we can now process all the updates from the message
896
1016
  dataSets.forEach(function (dataSet) {
897
- if (_this7.dataSets[dataSet.name]) {
898
- var hashTree = _this7.dataSets[dataSet.name].hashTree;
1017
+ if (_this8.dataSets[dataSet.name]) {
1018
+ var hashTree = _this8.dataSets[dataSet.name].hashTree;
899
1019
  if (hashTree) {
900
1020
  var locusStateElementsForThisSet = message.locusStateElements.filter(function (object) {
901
1021
  return object.htMeta.dataSetNames.includes(dataSet.name);
@@ -922,11 +1042,11 @@ var HashTreeParser = /*#__PURE__*/function () {
922
1042
  }
923
1043
  });
924
1044
  } else {
925
- _loggerProxy.default.logger.info("Locus-info:index#parseMessage --> ".concat(_this7.debugId, " unexpected (not visible) dataSet ").concat(dataSet.name, " received in hash tree message"));
1045
+ _loggerProxy.default.logger.info("Locus-info:index#parseMessage --> ".concat(_this8.debugId, " unexpected (not visible) dataSet ").concat(dataSet.name, " received in hash tree message"));
926
1046
  }
927
1047
  }
928
1048
  if (!isRosterDropped) {
929
- _this7.runSyncAlgorithm(dataSet);
1049
+ _this8.runSyncAlgorithm(dataSet);
930
1050
  }
931
1051
  });
932
1052
  if (!isRosterDropped) {
@@ -944,7 +1064,7 @@ var HashTreeParser = /*#__PURE__*/function () {
944
1064
  if (dataSetsRequiringInitialization.length > 0) {
945
1065
  // there are some data sets that we need to initialize asynchronously
946
1066
  queueMicrotask(function () {
947
- _this7.initializeNewVisibleDataSets(message, dataSetsRequiringInitialization);
1067
+ _this8.initializeNewVisibleDataSets(dataSetsRequiringInitialization);
948
1068
  });
949
1069
  }
950
1070
  if (updatedObjects.length === 0) {
@@ -960,7 +1080,7 @@ var HashTreeParser = /*#__PURE__*/function () {
960
1080
  }
961
1081
  }, _callee5, this);
962
1082
  }));
963
- function parseMessage(_x7, _x8) {
1083
+ function parseMessage(_x6, _x7) {
964
1084
  return _parseMessage.apply(this, arguments);
965
1085
  }
966
1086
  return parseMessage;
@@ -1000,7 +1120,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1000
1120
  }
1001
1121
  }, _callee6, this);
1002
1122
  }));
1003
- function handleMessage(_x9, _x0) {
1123
+ function handleMessage(_x8, _x9) {
1004
1124
  return _handleMessage.apply(this, arguments);
1005
1125
  }
1006
1126
  return handleMessage;
@@ -1015,9 +1135,49 @@ var HashTreeParser = /*#__PURE__*/function () {
1015
1135
  }, {
1016
1136
  key: "callLocusInfoUpdateCallback",
1017
1137
  value: function callLocusInfoUpdateCallback(updates) {
1138
+ var _this9 = this;
1018
1139
  var updateType = updates.updateType,
1019
1140
  updatedObjects = updates.updatedObjects;
1020
- if (updateType !== LocusInfoUpdateType.OBJECTS_UPDATED || (updatedObjects === null || updatedObjects === void 0 ? void 0 : updatedObjects.length) > 0) {
1141
+ if (updateType === LocusInfoUpdateType.OBJECTS_UPDATED && (updatedObjects === null || updatedObjects === void 0 ? void 0 : updatedObjects.length) > 0) {
1142
+ // Filter out updates for objects that already have a higher version in their datasets,
1143
+ // or removals for objects that still exist in any of their datasets
1144
+ var filteredUpdates = updatedObjects.filter(function (object) {
1145
+ var elementId = object.htMeta.elementId;
1146
+ var type = elementId.type,
1147
+ id = elementId.id,
1148
+ version = elementId.version;
1149
+
1150
+ // Check all datasets
1151
+ for (var _i2 = 0, _Object$keys3 = (0, _keys.default)(_this9.dataSets); _i2 < _Object$keys3.length; _i2++) {
1152
+ var dataSetName = _Object$keys3[_i2];
1153
+ var dataSet = _this9.dataSets[dataSetName];
1154
+
1155
+ // only visible datasets have hash trees set
1156
+ if (dataSet !== null && dataSet !== void 0 && dataSet.hashTree) {
1157
+ var existingVersion = dataSet.hashTree.getItemVersion(id, type);
1158
+ if (existingVersion !== undefined) {
1159
+ if (object.data) {
1160
+ // For updates: filter out if any dataset has a higher version
1161
+ if (existingVersion > version) {
1162
+ _loggerProxy.default.logger.info("HashTreeParser#callLocusInfoUpdateCallback --> ".concat(_this9.debugId, " Filtering out update for ").concat(type, ":").concat(id, " v").concat(version, " because dataset \"").concat(dataSetName, "\" has v").concat(existingVersion));
1163
+ return false;
1164
+ }
1165
+ } else if (existingVersion >= version) {
1166
+ // For removals: filter out if the object still exists in any dataset
1167
+ _loggerProxy.default.logger.info("HashTreeParser#callLocusInfoUpdateCallback --> ".concat(_this9.debugId, " Filtering out removal for ").concat(type, ":").concat(id, " v").concat(version, " because dataset \"").concat(dataSetName, "\" still has v").concat(existingVersion));
1168
+ return false;
1169
+ }
1170
+ }
1171
+ }
1172
+ }
1173
+ return true;
1174
+ });
1175
+ if (filteredUpdates.length > 0) {
1176
+ this.locusInfoUpdateCallback(updateType, {
1177
+ updatedObjects: filteredUpdates
1178
+ });
1179
+ }
1180
+ } else if (updateType !== LocusInfoUpdateType.OBJECTS_UPDATED) {
1021
1181
  this.locusInfoUpdateCallback(updateType, {
1022
1182
  updatedObjects: updatedObjects
1023
1183
  });
@@ -1048,7 +1208,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1048
1208
  }, {
1049
1209
  key: "runSyncAlgorithm",
1050
1210
  value: function runSyncAlgorithm(receivedDataSet) {
1051
- var _this8 = this;
1211
+ var _this0 = this;
1052
1212
  var dataSet = this.dataSets[receivedDataSet.name];
1053
1213
  if (!dataSet) {
1054
1214
  _loggerProxy.default.logger.warn("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " No data set found for ").concat(receivedDataSet.name, ", skipping sync algorithm"));
@@ -1070,7 +1230,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1070
1230
  }
1071
1231
  _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(this.debugId, " setting \"").concat(dataSet.name, "\" sync timer for ").concat(delay));
1072
1232
  dataSet.timer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee7() {
1073
- var rootHash, mismatchedLeavesData, receivedHashes, _yield$_this8$getHash, hashes, latestDataSetInfo, mismatchedLeaveIndexes, syncResponse, _t3;
1233
+ var rootHash, mismatchedLeavesData, receivedHashes, _yield$_this0$getHash, hashes, latestDataSetInfo, mismatchedLeaveIndexes, syncResponse, _t3;
1074
1234
  return _regenerator.default.wrap(function (_context8) {
1075
1235
  while (1) switch (_context8.prev = _context8.next) {
1076
1236
  case 0:
@@ -1079,7 +1239,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1079
1239
  _context8.next = 1;
1080
1240
  break;
1081
1241
  }
1082
- _loggerProxy.default.logger.warn("HashTreeParser#runSyncAlgorithm --> ".concat(_this8.debugId, " Data set \"").concat(dataSet.name, "\" no longer has a hash tree, cannot run sync algorithm"));
1242
+ _loggerProxy.default.logger.warn("HashTreeParser#runSyncAlgorithm --> ".concat(_this0.debugId, " Data set \"").concat(dataSet.name, "\" no longer has a hash tree, cannot run sync algorithm"));
1083
1243
  return _context8.abrupt("return");
1084
1244
  case 1:
1085
1245
  rootHash = dataSet.hashTree.getRootHash();
@@ -1087,7 +1247,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1087
1247
  _context8.next = 11;
1088
1248
  break;
1089
1249
  }
1090
- _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(_this8.debugId, " Root hash mismatch: received=").concat(dataSet.root, ", ours=").concat(rootHash, ", syncing data set \"").concat(dataSet.name, "\""));
1250
+ _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, "\""));
1091
1251
  mismatchedLeavesData = {};
1092
1252
  if (!(dataSet.leafCount !== 1)) {
1093
1253
  _context8.next = 7;
@@ -1095,11 +1255,11 @@ var HashTreeParser = /*#__PURE__*/function () {
1095
1255
  }
1096
1256
  _context8.prev = 2;
1097
1257
  _context8.next = 3;
1098
- return _this8.getHashesFromLocus(dataSet.name);
1258
+ return _this0.getHashesFromLocus(dataSet.name, rootHash);
1099
1259
  case 3:
1100
- _yield$_this8$getHash = _context8.sent;
1101
- hashes = _yield$_this8$getHash.hashes;
1102
- latestDataSetInfo = _yield$_this8$getHash.dataSet;
1260
+ _yield$_this0$getHash = _context8.sent;
1261
+ hashes = _yield$_this0$getHash.hashes;
1262
+ latestDataSetInfo = _yield$_this0$getHash.dataSet;
1103
1263
  receivedHashes = hashes;
1104
1264
  dataSet.hashTree.resize(latestDataSetInfo.leafCount);
1105
1265
  _context8.next = 6;
@@ -1112,7 +1272,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1112
1272
  break;
1113
1273
  }
1114
1274
  // this is a leaf count mismatch, we should do nothing, just wait for another heartbeat message from Locus
1115
- _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this8.debugId, " Got 409 when fetching hashes for data set \"").concat(dataSet.name, "\": ").concat(_t3.message));
1275
+ _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this0.debugId, " Got 409 when fetching hashes for data set \"").concat(dataSet.name, "\": ").concat(_t3.message));
1116
1276
  return _context8.abrupt("return");
1117
1277
  case 5:
1118
1278
  throw _t3;
@@ -1132,19 +1292,19 @@ var HashTreeParser = /*#__PURE__*/function () {
1132
1292
  break;
1133
1293
  }
1134
1294
  _context8.next = 9;
1135
- return _this8.sendSyncRequestToLocus(dataSet, mismatchedLeavesData);
1295
+ return _this0.sendSyncRequestToLocus(dataSet, mismatchedLeavesData);
1136
1296
  case 9:
1137
1297
  syncResponse = _context8.sent;
1138
1298
  // sync API may return nothing (in that case data will arrive via messages)
1139
1299
  // or it may return a response in the same format as messages
1140
1300
  if (syncResponse) {
1141
- _this8.handleMessage(syncResponse, 'via sync API');
1301
+ _this0.handleMessage(syncResponse, 'via sync API');
1142
1302
  }
1143
1303
  case 10:
1144
1304
  _context8.next = 12;
1145
1305
  break;
1146
1306
  case 11:
1147
- _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(_this8.debugId, " \"").concat(dataSet.name, "\" root hash matching: ").concat(rootHash, ", version=").concat(dataSet.version));
1307
+ _loggerProxy.default.logger.info("HashTreeParser#runSyncAlgorithm --> ".concat(_this0.debugId, " \"").concat(dataSet.name, "\" root hash matching: ").concat(rootHash, ", version=").concat(dataSet.version));
1148
1308
  case 12:
1149
1309
  case "end":
1150
1310
  return _context8.stop();
@@ -1174,33 +1334,37 @@ var HashTreeParser = /*#__PURE__*/function () {
1174
1334
  /**
1175
1335
  * Gets the current hashes from the locus for a specific data set.
1176
1336
  * @param {string} dataSetName
1337
+ * @param {string} currentRootHash
1177
1338
  * @returns {string[]}
1178
1339
  */
1179
1340
  }, {
1180
1341
  key: "getHashesFromLocus",
1181
- value: function getHashesFromLocus(dataSetName) {
1182
- var _this9 = this;
1342
+ value: function getHashesFromLocus(dataSetName, currentRootHash) {
1343
+ var _this1 = this;
1183
1344
  _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(this.debugId, " Requesting hashes for data set \"").concat(dataSetName, "\""));
1184
1345
  var dataSet = this.dataSets[dataSetName];
1185
1346
  var url = "".concat(dataSet.url, "/hashtree");
1186
1347
  return this.webexRequest({
1187
1348
  method: _constants.HTTP_VERBS.GET,
1188
- uri: url
1349
+ uri: url,
1350
+ qs: {
1351
+ rootHash: currentRootHash
1352
+ }
1189
1353
  }).then(function (response) {
1190
1354
  var _response$body, _response$body2;
1191
1355
  var hashes = (_response$body = response.body) === null || _response$body === void 0 ? void 0 : _response$body.hashes;
1192
1356
  var dataSetFromResponse = (_response$body2 = response.body) === null || _response$body2 === void 0 ? void 0 : _response$body2.dataSet;
1193
1357
  if (!hashes || !(0, _isArray.default)(hashes)) {
1194
- _loggerProxy.default.logger.warn("HashTreeParser#getHashesFromLocus --> ".concat(_this9.debugId, " Locus returned invalid hashes, response body="), response.body);
1358
+ _loggerProxy.default.logger.warn("HashTreeParser#getHashesFromLocus --> ".concat(_this1.debugId, " Locus returned invalid hashes, response body="), response.body);
1195
1359
  throw new Error("Locus returned invalid hashes: ".concat(hashes));
1196
1360
  }
1197
- _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this9.debugId, " Received hashes for data set \"").concat(dataSetName, "\": ").concat((0, _stringify.default)(hashes)));
1361
+ _loggerProxy.default.logger.info("HashTreeParser#getHashesFromLocus --> ".concat(_this1.debugId, " Received hashes for data set \"").concat(dataSetName, "\": ").concat((0, _stringify.default)(hashes)));
1198
1362
  return {
1199
1363
  hashes: hashes,
1200
1364
  dataSet: dataSetFromResponse
1201
1365
  };
1202
1366
  }).catch(function (error) {
1203
- _loggerProxy.default.logger.error("HashTreeParser#getHashesFromLocus --> ".concat(_this9.debugId, " Error ").concat(error.statusCode, " fetching hashes for data set \"").concat(dataSetName, "\":"), error);
1367
+ _loggerProxy.default.logger.error("HashTreeParser#getHashesFromLocus --> ".concat(_this1.debugId, " Error ").concat(error.statusCode, " fetching hashes for data set \"").concat(dataSetName, "\":"), error);
1204
1368
  throw error;
1205
1369
  });
1206
1370
  }
@@ -1215,7 +1379,7 @@ var HashTreeParser = /*#__PURE__*/function () {
1215
1379
  }, {
1216
1380
  key: "sendSyncRequestToLocus",
1217
1381
  value: function sendSyncRequestToLocus(dataSet, mismatchedLeavesData) {
1218
- var _this0 = this;
1382
+ var _this10 = this;
1219
1383
  _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(this.debugId, " Sending sync request for data set \"").concat(dataSet.name, "\""));
1220
1384
  var url = "".concat(dataSet.url, "/sync");
1221
1385
  var body = {
@@ -1228,19 +1392,23 @@ var HashTreeParser = /*#__PURE__*/function () {
1228
1392
  elementIds: mismatchedLeavesData[index]
1229
1393
  });
1230
1394
  });
1395
+ var ourCurrentRootHash = dataSet.hashTree ? dataSet.hashTree.getRootHash() : _constants2.EMPTY_HASH;
1231
1396
  return this.webexRequest({
1232
1397
  method: _constants.HTTP_VERBS.POST,
1233
1398
  uri: url,
1399
+ qs: {
1400
+ rootHash: ourCurrentRootHash
1401
+ },
1234
1402
  body: body
1235
1403
  }).then(function (resp) {
1236
- _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this0.debugId, " Sync request succeeded for \"").concat(dataSet.name, "\""));
1404
+ _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this10.debugId, " Sync request succeeded for \"").concat(dataSet.name, "\""));
1237
1405
  if (!resp.body || (0, _lodash.isEmpty)(resp.body)) {
1238
- _loggerProxy.default.logger.info("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this0.debugId, " Got ").concat(resp.statusCode, " with empty body for sync request for data set \"").concat(dataSet.name, "\", data should arrive via messages"));
1406
+ _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"));
1239
1407
  return null;
1240
1408
  }
1241
1409
  return resp.body;
1242
1410
  }).catch(function (error) {
1243
- _loggerProxy.default.logger.error("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this0.debugId, " Error ").concat(error.statusCode, " sending sync request for data set \"").concat(dataSet.name, "\":"), error);
1411
+ _loggerProxy.default.logger.error("HashTreeParser#sendSyncRequestToLocus --> ".concat(_this10.debugId, " Error ").concat(error.statusCode, " sending sync request for data set \"").concat(dataSet.name, "\":"), error);
1244
1412
  throw error;
1245
1413
  });
1246
1414
  }