@webex/plugin-meetings 3.12.0-next.10 → 3.12.0-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aiEnableRequest/index.js +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/hashTree/hashTreeParser.js +36 -20
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +38 -14
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/util.js +1 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/types/hashTree/hashTreeParser.d.ts +12 -2
- package/dist/types/locus-info/index.d.ts +8 -3
- package/dist/webinar/index.js +1 -1
- package/package.json +13 -13
- package/src/hashTree/hashTreeParser.ts +39 -22
- package/src/locus-info/index.ts +48 -24
- package/src/meeting/util.ts +1 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +59 -32
- package/test/unit/spec/locus-info/index.js +47 -22
- package/test/unit/spec/meeting/utils.js +4 -0
|
@@ -57,10 +57,15 @@ export const LocusInfoUpdateType = {
|
|
|
57
57
|
} as const;
|
|
58
58
|
|
|
59
59
|
export type LocusInfoUpdateType = Enum<typeof LocusInfoUpdateType>;
|
|
60
|
-
export type
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
export type LocusInfoUpdate =
|
|
61
|
+
| {
|
|
62
|
+
updateType: typeof LocusInfoUpdateType.OBJECTS_UPDATED;
|
|
63
|
+
updatedObjects: HashTreeObject[];
|
|
64
|
+
}
|
|
65
|
+
| {
|
|
66
|
+
updateType: typeof LocusInfoUpdateType.MEETING_ENDED;
|
|
67
|
+
};
|
|
68
|
+
export type LocusInfoUpdateCallback = (update: LocusInfoUpdate) => void;
|
|
64
69
|
|
|
65
70
|
interface LeafInfo {
|
|
66
71
|
type: ObjectType;
|
|
@@ -227,7 +232,7 @@ class HashTreeParser {
|
|
|
227
232
|
private initializeNewVisibleDataSet(
|
|
228
233
|
visibleDataSetInfo: VisibleDataSetInfo,
|
|
229
234
|
dataSetInfo: DataSet
|
|
230
|
-
): Promise<
|
|
235
|
+
): Promise<LocusInfoUpdate> {
|
|
231
236
|
if (this.isVisibleDataSet(dataSetInfo.name)) {
|
|
232
237
|
LoggerProxy.logger.info(
|
|
233
238
|
`HashTreeParser#initializeNewVisibleDataSet --> ${this.debugId} Data set "${dataSetInfo.name}" already exists, skipping init`
|
|
@@ -264,7 +269,7 @@ class HashTreeParser {
|
|
|
264
269
|
private sendInitializationSyncRequestToLocus(
|
|
265
270
|
datasetName: string,
|
|
266
271
|
debugText: string
|
|
267
|
-
): Promise<
|
|
272
|
+
): Promise<LocusInfoUpdate> {
|
|
268
273
|
const dataset = this.dataSets[datasetName];
|
|
269
274
|
|
|
270
275
|
if (!dataset) {
|
|
@@ -272,7 +277,7 @@ class HashTreeParser {
|
|
|
272
277
|
`HashTreeParser#sendInitializationSyncRequestToLocus --> ${this.debugId} No data set found for ${datasetName}, cannot send the request for leaf data`
|
|
273
278
|
);
|
|
274
279
|
|
|
275
|
-
return Promise.resolve(
|
|
280
|
+
return Promise.resolve({updateType: LocusInfoUpdateType.OBJECTS_UPDATED, updatedObjects: []});
|
|
276
281
|
}
|
|
277
282
|
|
|
278
283
|
const emptyLeavesData = new Array(dataset.leafCount).fill([]);
|
|
@@ -1014,7 +1019,7 @@ class HashTreeParser {
|
|
|
1014
1019
|
|
|
1015
1020
|
// when we detect new visible datasets, it may be that the metadata about them is not
|
|
1016
1021
|
// available in the message, they will require separate async initialization
|
|
1017
|
-
let dataSetsRequiringInitialization = [];
|
|
1022
|
+
let dataSetsRequiringInitialization: VisibleDataSetInfo[] = [];
|
|
1018
1023
|
|
|
1019
1024
|
// first find out if there are any visible data set changes - they're signalled in Metadata object updates
|
|
1020
1025
|
const metadataUpdates = (message.locusStateElements || []).filter((object) =>
|
|
@@ -1022,7 +1027,7 @@ class HashTreeParser {
|
|
|
1022
1027
|
);
|
|
1023
1028
|
|
|
1024
1029
|
if (metadataUpdates.length > 0) {
|
|
1025
|
-
const updatedMetadataObjects = [];
|
|
1030
|
+
const updatedMetadataObjects: HashTreeObject[] = [];
|
|
1026
1031
|
|
|
1027
1032
|
metadataUpdates.forEach((object) => {
|
|
1028
1033
|
// todo: once Locus supports it, we will use the "view" field here instead of dataSetNames
|
|
@@ -1051,7 +1056,7 @@ class HashTreeParser {
|
|
|
1051
1056
|
}
|
|
1052
1057
|
}
|
|
1053
1058
|
|
|
1054
|
-
if (message.locusStateElements
|
|
1059
|
+
if (message.locusStateElements && message.locusStateElements.length > 0) {
|
|
1055
1060
|
// by this point we now have this.dataSets setup for data sets from this message
|
|
1056
1061
|
// and hash trees created for the new visible data sets,
|
|
1057
1062
|
// so we can now process all the updates from the message
|
|
@@ -1147,20 +1152,17 @@ class HashTreeParser {
|
|
|
1147
1152
|
* @param {Object} updates parsed from a Locus message
|
|
1148
1153
|
* @returns {void}
|
|
1149
1154
|
*/
|
|
1150
|
-
private callLocusInfoUpdateCallback(updates: {
|
|
1151
|
-
updateType: LocusInfoUpdateType;
|
|
1152
|
-
updatedObjects?: HashTreeObject[];
|
|
1153
|
-
}) {
|
|
1155
|
+
private callLocusInfoUpdateCallback(updates: LocusInfoUpdate) {
|
|
1154
1156
|
if (this.state === 'stopped') {
|
|
1155
1157
|
return;
|
|
1156
1158
|
}
|
|
1157
1159
|
|
|
1158
|
-
const {updateType
|
|
1160
|
+
const {updateType} = updates;
|
|
1159
1161
|
|
|
1160
|
-
if (updateType === LocusInfoUpdateType.OBJECTS_UPDATED && updatedObjects?.length > 0) {
|
|
1162
|
+
if (updateType === LocusInfoUpdateType.OBJECTS_UPDATED && updates.updatedObjects?.length > 0) {
|
|
1161
1163
|
// Filter out updates for objects that already have a higher version in their datasets,
|
|
1162
1164
|
// or removals for objects that still exist in any of their datasets
|
|
1163
|
-
const filteredUpdates = updatedObjects.filter((object) => {
|
|
1165
|
+
const filteredUpdates = updates.updatedObjects.filter((object) => {
|
|
1164
1166
|
const {elementId} = object.htMeta;
|
|
1165
1167
|
const {type, id, version} = elementId;
|
|
1166
1168
|
|
|
@@ -1197,10 +1199,10 @@ class HashTreeParser {
|
|
|
1197
1199
|
});
|
|
1198
1200
|
|
|
1199
1201
|
if (filteredUpdates.length > 0) {
|
|
1200
|
-
this.locusInfoUpdateCallback(updateType,
|
|
1202
|
+
this.locusInfoUpdateCallback({updateType, updatedObjects: filteredUpdates});
|
|
1201
1203
|
}
|
|
1202
1204
|
} else if (updateType !== LocusInfoUpdateType.OBJECTS_UPDATED) {
|
|
1203
|
-
this.locusInfoUpdateCallback(updateType
|
|
1205
|
+
this.locusInfoUpdateCallback({updateType});
|
|
1204
1206
|
}
|
|
1205
1207
|
}
|
|
1206
1208
|
|
|
@@ -1457,6 +1459,16 @@ class HashTreeParser {
|
|
|
1457
1459
|
this.state = 'stopped';
|
|
1458
1460
|
}
|
|
1459
1461
|
|
|
1462
|
+
/**
|
|
1463
|
+
* Cleans up the HashTreeParser, stopping all timers and clearing all internal state.
|
|
1464
|
+
* After calling this, the parser should not be used anymore.
|
|
1465
|
+
* @returns {void}
|
|
1466
|
+
*/
|
|
1467
|
+
public cleanUp() {
|
|
1468
|
+
this.stop();
|
|
1469
|
+
this.dataSets = {};
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1460
1472
|
/**
|
|
1461
1473
|
* Resumes the HashTreeParser that was previously stopped.
|
|
1462
1474
|
* @param {HashTreeMessage} message - The message to resume with, it must contain metadata with visible data sets info
|
|
@@ -1591,15 +1603,20 @@ class HashTreeParser {
|
|
|
1591
1603
|
);
|
|
1592
1604
|
|
|
1593
1605
|
const url = `${dataSet.url}/sync`;
|
|
1594
|
-
const body
|
|
1606
|
+
const body: {
|
|
1607
|
+
leafCount: number;
|
|
1608
|
+
leafDataEntries: {leafIndex: number; elementIds: LeafDataItem[]}[];
|
|
1609
|
+
} = {
|
|
1595
1610
|
leafCount: dataSet.leafCount,
|
|
1596
1611
|
leafDataEntries: [],
|
|
1597
1612
|
};
|
|
1598
1613
|
|
|
1599
1614
|
Object.keys(mismatchedLeavesData).forEach((index) => {
|
|
1615
|
+
const leafIndex = parseInt(index, 10);
|
|
1616
|
+
|
|
1600
1617
|
body.leafDataEntries.push({
|
|
1601
|
-
leafIndex
|
|
1602
|
-
elementIds: mismatchedLeavesData[
|
|
1618
|
+
leafIndex,
|
|
1619
|
+
elementIds: mismatchedLeavesData[leafIndex],
|
|
1603
1620
|
});
|
|
1604
1621
|
});
|
|
1605
1622
|
|
package/src/locus-info/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
|
34
34
|
import HashTreeParser, {
|
|
35
35
|
DataSet,
|
|
36
36
|
HashTreeMessage,
|
|
37
|
+
LocusInfoUpdate,
|
|
37
38
|
LocusInfoUpdateType,
|
|
38
39
|
Metadata,
|
|
39
40
|
} from '../hashTree/hashTreeParser';
|
|
@@ -545,7 +546,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
545
546
|
dataSets: Array<DataSet>;
|
|
546
547
|
locus: any;
|
|
547
548
|
};
|
|
548
|
-
metadata: Metadata;
|
|
549
|
+
metadata: Metadata | null;
|
|
549
550
|
replacedAt?: string;
|
|
550
551
|
}): HashTreeParser {
|
|
551
552
|
const parser = new HashTreeParser({
|
|
@@ -553,7 +554,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
553
554
|
metadata,
|
|
554
555
|
webexRequest: this.webex.request.bind(this.webex),
|
|
555
556
|
locusInfoUpdateCallback: this.updateFromHashTree.bind(this, locusUrl),
|
|
556
|
-
debugId: `HT-${locusUrl.split('/')
|
|
557
|
+
debugId: `HT-${locusUrl.split('/')?.pop()?.substring(0, 4)}`,
|
|
557
558
|
excludedDataSets: this.webex.config.meetings.locus?.excludedDataSets,
|
|
558
559
|
});
|
|
559
560
|
|
|
@@ -656,7 +657,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
656
657
|
);
|
|
657
658
|
// first create the HashTreeParser, but don't initialize it with any data yet
|
|
658
659
|
const hashTreeParser = this.createHashTreeParser({
|
|
659
|
-
locusUrl: data.locus.url,
|
|
660
|
+
locusUrl: data.locus.url as string,
|
|
660
661
|
initialLocus: {
|
|
661
662
|
locus: null,
|
|
662
663
|
dataSets: [], // empty, because we don't have them yet
|
|
@@ -965,7 +966,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
965
966
|
// but it's buried inside the message, we need to find it and pass it to HashTreeParser constructor
|
|
966
967
|
const metadata = message.locusStateElements?.find((el) => isMetadata(el));
|
|
967
968
|
|
|
968
|
-
if (metadata
|
|
969
|
+
if (metadata && metadata.data?.visibleDataSets?.length > 0) {
|
|
969
970
|
LoggerProxy.logger.info(
|
|
970
971
|
`Locus-info:index#handleHashTreeParserSwitch --> no hash tree parser found for locusUrl ${message.locusUrl}, creating a new one`
|
|
971
972
|
);
|
|
@@ -1056,7 +1057,10 @@ export default class LocusInfo extends EventsScope {
|
|
|
1056
1057
|
|
|
1057
1058
|
const entry = this.hashTreeParsers.get(message.locusUrl);
|
|
1058
1059
|
|
|
1059
|
-
entry
|
|
1060
|
+
// the check is just for typescript, the case of no entry in hashTreeParsers is handled in handleHashTreeParserSwitch() above
|
|
1061
|
+
if (entry) {
|
|
1062
|
+
entry.parser.handleMessage(message);
|
|
1063
|
+
}
|
|
1060
1064
|
}
|
|
1061
1065
|
|
|
1062
1066
|
/**
|
|
@@ -1064,16 +1068,11 @@ export default class LocusInfo extends EventsScope {
|
|
|
1064
1068
|
* Updates our locus info based on the data parsed by the hash tree parser.
|
|
1065
1069
|
*
|
|
1066
1070
|
* @param {string} locusUrl - the locus URL for which the update is received
|
|
1067
|
-
* @param {
|
|
1068
|
-
* @param {Object} [data] - Additional data for the update, if applicable.
|
|
1071
|
+
* @param {LocusInfoUpdate} update - Details about the update.
|
|
1069
1072
|
* @returns {void}
|
|
1070
1073
|
*/
|
|
1071
|
-
private updateFromHashTree(
|
|
1072
|
-
|
|
1073
|
-
updateType: LocusInfoUpdateType,
|
|
1074
|
-
data?: {updatedObjects: HashTreeObject[]}
|
|
1075
|
-
) {
|
|
1076
|
-
switch (updateType) {
|
|
1074
|
+
private updateFromHashTree(locusUrl: string, update: LocusInfoUpdate) {
|
|
1075
|
+
switch (update.updateType) {
|
|
1077
1076
|
case LocusInfoUpdateType.OBJECTS_UPDATED: {
|
|
1078
1077
|
// initialize our new locus
|
|
1079
1078
|
let locus: LocusDTO = {
|
|
@@ -1087,7 +1086,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1087
1086
|
// first go over all the updates and check what happens with the main locus object
|
|
1088
1087
|
let locusObjectStateAfterUpdates: LocusObjectStateAfterUpdates =
|
|
1089
1088
|
LocusObjectStateAfterUpdates.unchanged;
|
|
1090
|
-
|
|
1089
|
+
update.updatedObjects.forEach((object) => {
|
|
1091
1090
|
if (object.htMeta.elementId.type.toLowerCase() === ObjectType.locus) {
|
|
1092
1091
|
if (locusObjectStateAfterUpdates === LocusObjectStateAfterUpdates.updated) {
|
|
1093
1092
|
// this code doesn't supported it right now,
|
|
@@ -1116,6 +1115,14 @@ export default class LocusInfo extends EventsScope {
|
|
|
1116
1115
|
|
|
1117
1116
|
const hashTreeParserEntry = this.hashTreeParsers.get(locusUrl);
|
|
1118
1117
|
|
|
1118
|
+
if (!hashTreeParserEntry) {
|
|
1119
|
+
LoggerProxy.logger.warn(
|
|
1120
|
+
`Locus-info:index#updateFromHashTree --> no HashTreeParser found for locusUrl ${locusUrl} when trying to apply updates from hash tree`
|
|
1121
|
+
);
|
|
1122
|
+
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1119
1126
|
if (!hashTreeParserEntry.initializedFromHashTree) {
|
|
1120
1127
|
// this is the first time we're getting an update for this locusUrl,
|
|
1121
1128
|
// so it's probably a move to/from breakout. We need to start from a clean state,
|
|
@@ -1124,7 +1131,8 @@ export default class LocusInfo extends EventsScope {
|
|
|
1124
1131
|
`Locus-info:index#updateFromHashTree --> first INITIAL update for locusUrl ${locusUrl}, starting from empty state`
|
|
1125
1132
|
);
|
|
1126
1133
|
hashTreeParserEntry.initializedFromHashTree = true;
|
|
1127
|
-
|
|
1134
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1135
|
+
locus.jsSdkMeta!.forceReplaceMembers = true;
|
|
1128
1136
|
} else if (
|
|
1129
1137
|
// if Locus object is unchanged or removed, we need to keep using the existing locus
|
|
1130
1138
|
// because the rest of the locusInfo code expects locus to always be present (with at least some of the fields)
|
|
@@ -1137,7 +1145,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1137
1145
|
// copy over all of existing locus except participants
|
|
1138
1146
|
LocusDtoTopLevelKeys.forEach((key) => {
|
|
1139
1147
|
if (key !== 'participants') {
|
|
1140
|
-
locus[key] = cloneDeep(this[key]);
|
|
1148
|
+
(locus as Record<string, any>)[key] = cloneDeep((this as Record<string, any>)[key]);
|
|
1141
1149
|
}
|
|
1142
1150
|
});
|
|
1143
1151
|
} else {
|
|
@@ -1145,14 +1153,16 @@ export default class LocusInfo extends EventsScope {
|
|
|
1145
1153
|
// (except participants, which need to stay empty - that means "no participant changes")
|
|
1146
1154
|
Object.values(ObjectTypeToLocusKeyMap).forEach((locusDtoKey) => {
|
|
1147
1155
|
if (locusDtoKey !== 'participants') {
|
|
1148
|
-
locus[locusDtoKey] = cloneDeep(
|
|
1156
|
+
(locus as Record<string, any>)[locusDtoKey] = cloneDeep(
|
|
1157
|
+
(this as Record<string, any>)[locusDtoKey]
|
|
1158
|
+
);
|
|
1149
1159
|
}
|
|
1150
1160
|
});
|
|
1151
1161
|
}
|
|
1152
1162
|
|
|
1153
1163
|
LoggerProxy.logger.info(
|
|
1154
1164
|
`Locus-info:index#updateFromHashTree --> LOCUS object is ${locusObjectStateAfterUpdates}, all updates: ${JSON.stringify(
|
|
1155
|
-
|
|
1165
|
+
update.updatedObjects.map((o) => ({
|
|
1156
1166
|
type: o.htMeta.elementId.type,
|
|
1157
1167
|
id: o.htMeta.elementId.id,
|
|
1158
1168
|
hasData: !!o.data,
|
|
@@ -1160,7 +1170,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1160
1170
|
)}`
|
|
1161
1171
|
);
|
|
1162
1172
|
// now apply all the updates from the hash tree onto the locus
|
|
1163
|
-
|
|
1173
|
+
update.updatedObjects.forEach((object) => {
|
|
1164
1174
|
locus = this.updateLocusFromHashTreeObject(object, locus);
|
|
1165
1175
|
});
|
|
1166
1176
|
|
|
@@ -1260,16 +1270,16 @@ export default class LocusInfo extends EventsScope {
|
|
|
1260
1270
|
* @param {string} debugText string explaining the trigger for this call, added to logs for debugging purposes
|
|
1261
1271
|
* @param {object} locus locus object
|
|
1262
1272
|
* @param {object} metadata locus hash trees metadata
|
|
1263
|
-
* @param {string} eventType locus event
|
|
1264
1273
|
* @param {DataSet[]} dataSets
|
|
1274
|
+
* @param {string} eventType locus event
|
|
1265
1275
|
* @returns {void}
|
|
1266
1276
|
*/
|
|
1267
1277
|
private onFullLocusWithHashTrees(
|
|
1268
1278
|
debugText: string,
|
|
1269
1279
|
locus: any,
|
|
1270
1280
|
metadata: Metadata,
|
|
1271
|
-
|
|
1272
|
-
|
|
1281
|
+
dataSets: Array<DataSet>,
|
|
1282
|
+
eventType?: string
|
|
1273
1283
|
) {
|
|
1274
1284
|
if (!this.hashTreeParsers.has(locus.url)) {
|
|
1275
1285
|
LoggerProxy.logger.info(
|
|
@@ -1289,7 +1299,8 @@ export default class LocusInfo extends EventsScope {
|
|
|
1289
1299
|
metadata,
|
|
1290
1300
|
});
|
|
1291
1301
|
// we have a full locus to start with, so we consider Locus info to be "initialized"
|
|
1292
|
-
|
|
1302
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1303
|
+
this.hashTreeParsers.get(locus.url)!.initializedFromHashTree = true;
|
|
1293
1304
|
this.onFullLocusCommon(locus, eventType);
|
|
1294
1305
|
} else {
|
|
1295
1306
|
// in this case the Locus we're getting is not necessarily the full one
|
|
@@ -1351,7 +1362,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1351
1362
|
);
|
|
1352
1363
|
}
|
|
1353
1364
|
// this is the new hashmap Locus DTO format (only applicable to webinars for now)
|
|
1354
|
-
this.onFullLocusWithHashTrees(debugText, locus, metadata,
|
|
1365
|
+
this.onFullLocusWithHashTrees(debugText, locus, metadata, dataSets, eventType);
|
|
1355
1366
|
} else {
|
|
1356
1367
|
this.onFullLocusClassic(debugText, locus, eventType);
|
|
1357
1368
|
}
|
|
@@ -2859,4 +2870,17 @@ export default class LocusInfo extends EventsScope {
|
|
|
2859
2870
|
clearMainSessionLocusCache() {
|
|
2860
2871
|
this.mainSessionLocusCache = null;
|
|
2861
2872
|
}
|
|
2873
|
+
|
|
2874
|
+
/**
|
|
2875
|
+
* Cleans up all hash tree parsers and clears internal maps.
|
|
2876
|
+
* @returns {void}
|
|
2877
|
+
* @memberof LocusInfo
|
|
2878
|
+
*/
|
|
2879
|
+
cleanUp() {
|
|
2880
|
+
this.hashTreeParsers.forEach((entry) => {
|
|
2881
|
+
entry.parser.cleanUp();
|
|
2882
|
+
});
|
|
2883
|
+
this.hashTreeParsers.clear();
|
|
2884
|
+
this.hashTreeObjectId2ParticipantId.clear();
|
|
2885
|
+
}
|
|
2862
2886
|
}
|
package/src/meeting/util.ts
CHANGED
|
@@ -371,6 +371,7 @@ const MeetingUtil = {
|
|
|
371
371
|
meeting.breakouts.cleanUp();
|
|
372
372
|
meeting.webinar.cleanUp();
|
|
373
373
|
meeting.simultaneousInterpretation.cleanUp();
|
|
374
|
+
meeting.locusInfo.cleanUp();
|
|
374
375
|
meeting.locusMediaRequest = undefined;
|
|
375
376
|
|
|
376
377
|
meeting.webex?.internal?.newMetrics?.callDiagnosticMetrics?.clearEventLimitsForCorrelationId(
|
|
@@ -553,8 +553,7 @@ describe('HashTreeParser', () => {
|
|
|
553
553
|
);
|
|
554
554
|
|
|
555
555
|
// Verify callback was called with OBJECTS_UPDATED and correct updatedObjects list
|
|
556
|
-
|
|
557
|
-
assert.calledWith(callback, LocusInfoUpdateType.OBJECTS_UPDATED, {
|
|
556
|
+
assert.calledWith(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
558
557
|
updatedObjects: [
|
|
559
558
|
{
|
|
560
559
|
htMeta: {
|
|
@@ -824,7 +823,7 @@ describe('HashTreeParser', () => {
|
|
|
824
823
|
expect(parser.dataSets.self.version).to.equal(2100);
|
|
825
824
|
expect(parser.dataSets['atd-unmuted'].version).to.equal(3100);
|
|
826
825
|
|
|
827
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
826
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
828
827
|
updatedObjects: [
|
|
829
828
|
{
|
|
830
829
|
htMeta: {
|
|
@@ -955,7 +954,7 @@ describe('HashTreeParser', () => {
|
|
|
955
954
|
{type: 'ControlEntry', id: 10101, version: 100}
|
|
956
955
|
]);
|
|
957
956
|
|
|
958
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
957
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
959
958
|
updatedObjects: [
|
|
960
959
|
{
|
|
961
960
|
htMeta: {
|
|
@@ -1045,7 +1044,7 @@ describe('HashTreeParser', () => {
|
|
|
1045
1044
|
assert.calledOnceWithExactly(mainPutItemsSpy, [{type: 'locus', id: 0, version: 201}]);
|
|
1046
1045
|
|
|
1047
1046
|
// Verify callback was called only for known dataset
|
|
1048
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1047
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1049
1048
|
updatedObjects: [
|
|
1050
1049
|
{
|
|
1051
1050
|
htMeta: {
|
|
@@ -1145,7 +1144,7 @@ describe('HashTreeParser', () => {
|
|
|
1145
1144
|
assert.calledOnceWithExactly(selfPutItemSpy, {type: 'metadata', id: 5, version: 51});
|
|
1146
1145
|
|
|
1147
1146
|
// Verify callback was called with metadata object and removed dataset objects
|
|
1148
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1147
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1149
1148
|
updatedObjects: [
|
|
1150
1149
|
// updated metadata object:
|
|
1151
1150
|
{
|
|
@@ -1306,7 +1305,7 @@ describe('HashTreeParser', () => {
|
|
|
1306
1305
|
assert.notCalled(atdUnmutedPutItemsSpy);
|
|
1307
1306
|
|
|
1308
1307
|
// Verify callback was called with the updated object
|
|
1309
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1308
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1310
1309
|
updatedObjects: [
|
|
1311
1310
|
{
|
|
1312
1311
|
htMeta: {
|
|
@@ -1534,7 +1533,7 @@ describe('HashTreeParser', () => {
|
|
|
1534
1533
|
]);
|
|
1535
1534
|
|
|
1536
1535
|
// Verify callback was called with OBJECTS_UPDATED and all updated objects
|
|
1537
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1536
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1538
1537
|
updatedObjects: [
|
|
1539
1538
|
{
|
|
1540
1539
|
htMeta: {
|
|
@@ -1599,9 +1598,7 @@ describe('HashTreeParser', () => {
|
|
|
1599
1598
|
parser.handleMessage(sentinelMessage, 'sentinel message');
|
|
1600
1599
|
|
|
1601
1600
|
// Verify callback was called with MEETING_ENDED
|
|
1602
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1603
|
-
updatedObjects: undefined,
|
|
1604
|
-
});
|
|
1601
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1605
1602
|
|
|
1606
1603
|
// Verify that all timers were stopped
|
|
1607
1604
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -1623,9 +1620,7 @@ describe('HashTreeParser', () => {
|
|
|
1623
1620
|
parser.handleMessage(sentinelMessage, 'sentinel message');
|
|
1624
1621
|
|
|
1625
1622
|
// Verify callback was called with MEETING_ENDED
|
|
1626
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1627
|
-
updatedObjects: undefined,
|
|
1628
|
-
});
|
|
1623
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1629
1624
|
|
|
1630
1625
|
// Verify that all timers were stopped
|
|
1631
1626
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -1721,7 +1716,7 @@ describe('HashTreeParser', () => {
|
|
|
1721
1716
|
);
|
|
1722
1717
|
|
|
1723
1718
|
// Verify that callback was called with synced objects
|
|
1724
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1719
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
1725
1720
|
updatedObjects: [
|
|
1726
1721
|
{
|
|
1727
1722
|
htMeta: {
|
|
@@ -1783,9 +1778,7 @@ describe('HashTreeParser', () => {
|
|
|
1783
1778
|
await clock.tickAsync(1000);
|
|
1784
1779
|
|
|
1785
1780
|
// Verify callback was called with MEETING_ENDED
|
|
1786
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1787
|
-
updatedObjects: undefined,
|
|
1788
|
-
});
|
|
1781
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1789
1782
|
|
|
1790
1783
|
// Verify all timers are stopped
|
|
1791
1784
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -1848,9 +1841,7 @@ describe('HashTreeParser', () => {
|
|
|
1848
1841
|
await clock.tickAsync(1000);
|
|
1849
1842
|
|
|
1850
1843
|
// Verify callback was called with MEETING_ENDED
|
|
1851
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
1852
|
-
updatedObjects: undefined,
|
|
1853
|
-
});
|
|
1844
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
1854
1845
|
|
|
1855
1846
|
// Verify all timers are stopped
|
|
1856
1847
|
Object.values(parser.dataSets).forEach((ds: any) => {
|
|
@@ -2088,7 +2079,7 @@ describe('HashTreeParser', () => {
|
|
|
2088
2079
|
assert.equal(parser.dataSets.attendees.hashTree.numLeaves, 8);
|
|
2089
2080
|
|
|
2090
2081
|
// Verify callback was called with the metadata update (appears twice - processed once for visible dataset changes, once in main loop)
|
|
2091
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2082
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2092
2083
|
updatedObjects: [
|
|
2093
2084
|
{
|
|
2094
2085
|
htMeta: {
|
|
@@ -2366,9 +2357,7 @@ describe('HashTreeParser', () => {
|
|
|
2366
2357
|
await clock.tickAsync(0);
|
|
2367
2358
|
|
|
2368
2359
|
// Verify callback was called with MEETING_ENDED
|
|
2369
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
2370
|
-
updatedObjects: undefined,
|
|
2371
|
-
});
|
|
2360
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
2372
2361
|
});
|
|
2373
2362
|
|
|
2374
2363
|
it('handles removal of visible data set', async () => {
|
|
@@ -2431,7 +2420,7 @@ describe('HashTreeParser', () => {
|
|
|
2431
2420
|
assert.isUndefined(parser.dataSets['atd-unmuted'].timer);
|
|
2432
2421
|
|
|
2433
2422
|
// Verify callback was called with the metadata update and the removed objects (metadata appears twice - processed once for dataset changes, once in main loop)
|
|
2434
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2423
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
2435
2424
|
updatedObjects: [
|
|
2436
2425
|
{
|
|
2437
2426
|
htMeta: {
|
|
@@ -3050,7 +3039,7 @@ describe('HashTreeParser', () => {
|
|
|
3050
3039
|
parser.handleMessage(updateMessage, 'update with newer version');
|
|
3051
3040
|
|
|
3052
3041
|
// Callback should be called with the update
|
|
3053
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3042
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3054
3043
|
updatedObjects: [
|
|
3055
3044
|
{
|
|
3056
3045
|
htMeta: {
|
|
@@ -3121,7 +3110,7 @@ describe('HashTreeParser', () => {
|
|
|
3121
3110
|
parser.handleMessage(removalMessage, 'removal of non-existent object');
|
|
3122
3111
|
|
|
3123
3112
|
// Callback should be called with the removal
|
|
3124
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3113
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3125
3114
|
updatedObjects: [
|
|
3126
3115
|
{
|
|
3127
3116
|
htMeta: {
|
|
@@ -3256,7 +3245,7 @@ describe('HashTreeParser', () => {
|
|
|
3256
3245
|
parser.handleMessage(mixedMessage, 'mixed updates');
|
|
3257
3246
|
|
|
3258
3247
|
// Callback should be called with only the valid updates (participant 1 v110 and participant 3 v10)
|
|
3259
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3248
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.OBJECTS_UPDATED,
|
|
3260
3249
|
updatedObjects: [
|
|
3261
3250
|
{
|
|
3262
3251
|
htMeta: {
|
|
@@ -3434,9 +3423,7 @@ describe('HashTreeParser', () => {
|
|
|
3434
3423
|
parser.handleMessage(sentinelMessage as any, 'sentinel message');
|
|
3435
3424
|
|
|
3436
3425
|
// Callback should be called with MEETING_ENDED
|
|
3437
|
-
assert.calledOnceWithExactly(callback, LocusInfoUpdateType.MEETING_ENDED
|
|
3438
|
-
updatedObjects: undefined,
|
|
3439
|
-
});
|
|
3426
|
+
assert.calledOnceWithExactly(callback, {updateType: LocusInfoUpdateType.MEETING_ENDED});
|
|
3440
3427
|
});
|
|
3441
3428
|
});
|
|
3442
3429
|
|
|
@@ -3795,4 +3782,44 @@ describe('HashTreeParser', () => {
|
|
|
3795
3782
|
assert.notCalled(callback);
|
|
3796
3783
|
});
|
|
3797
3784
|
});
|
|
3785
|
+
|
|
3786
|
+
describe('#cleanUp', () => {
|
|
3787
|
+
it('should stop the parser, clear all timers and clear all dataSets', () => {
|
|
3788
|
+
const parser = createHashTreeParser();
|
|
3789
|
+
|
|
3790
|
+
// Send a message to set up sync timers via runSyncAlgorithm
|
|
3791
|
+
const message = {
|
|
3792
|
+
dataSets: [
|
|
3793
|
+
{
|
|
3794
|
+
...createDataSet('main', 16, 1100),
|
|
3795
|
+
root: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1',
|
|
3796
|
+
},
|
|
3797
|
+
],
|
|
3798
|
+
visibleDataSetsUrl,
|
|
3799
|
+
locusUrl,
|
|
3800
|
+
heartbeatIntervalMs: 5000,
|
|
3801
|
+
locusStateElements: [
|
|
3802
|
+
{
|
|
3803
|
+
htMeta: {
|
|
3804
|
+
elementId: {type: 'locus' as const, id: 0, version: 201},
|
|
3805
|
+
dataSetNames: ['main'],
|
|
3806
|
+
},
|
|
3807
|
+
data: {someData: 'value'},
|
|
3808
|
+
},
|
|
3809
|
+
],
|
|
3810
|
+
};
|
|
3811
|
+
|
|
3812
|
+
parser.handleMessage(message, 'setup timers');
|
|
3813
|
+
|
|
3814
|
+
// Verify timers were set by handleMessage
|
|
3815
|
+
expect(parser.dataSets.main.timer).to.not.be.undefined;
|
|
3816
|
+
expect(parser.dataSets.main.heartbeatWatchdogTimer).to.not.be.undefined;
|
|
3817
|
+
|
|
3818
|
+
parser.cleanUp();
|
|
3819
|
+
|
|
3820
|
+
expect(parser.state).to.equal('stopped');
|
|
3821
|
+
expect(parser.visibleDataSets).to.deep.equal([]);
|
|
3822
|
+
expect(parser.dataSets).to.deep.equal({});
|
|
3823
|
+
});
|
|
3824
|
+
});
|
|
3798
3825
|
});
|