@webex/plugin-meetings 3.0.0-beta.186 → 3.0.0-beta.187

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.
@@ -1,15 +1,25 @@
1
- import SimpleQueue from '../common/queue';
1
+ /// <reference types="node" />
2
+ import SortedQueue from '../common/queue';
3
+ type LocusDeltaDto = {
4
+ baseSequence: {
5
+ rangeStart: number;
6
+ rangeEnd: number;
7
+ entries: number[];
8
+ };
9
+ sequence: {
10
+ rangeStart: number;
11
+ rangeEnd: number;
12
+ entries: number[];
13
+ };
14
+ syncUrl: string;
15
+ };
2
16
  /**
3
17
  * Locus Delta Parser
4
18
  * @private
5
19
  * https://sqbu-github.cisco.com/WebExSquared/cloud-apps/wiki/Locus-Delta-Events
6
20
  */
7
21
  export default class Parser {
8
- static status: {
9
- IDLE: string;
10
- PAUSED: string;
11
- WORKING: string;
12
- };
22
+ status: 'IDLE' | 'PAUSED' | 'WORKING' | 'BLOCKED';
13
23
  static loci: {
14
24
  EQ: string;
15
25
  GT: string;
@@ -17,14 +27,23 @@ export default class Parser {
17
27
  DESYNC: string;
18
28
  USE_INCOMING: string;
19
29
  USE_CURRENT: string;
30
+ WAIT: string;
20
31
  ERROR: string;
21
32
  };
22
- queue: SimpleQueue;
33
+ queue: SortedQueue<LocusDeltaDto>;
23
34
  workingCopy: any;
35
+ syncTimer: null | number | NodeJS.Timeout;
24
36
  /**
25
37
  * @constructs Parser
26
38
  */
27
39
  constructor();
40
+ /**
41
+ * Returns a debug string representing a locus delta - useful for logging
42
+ *
43
+ * @param {LocusDeltaDto} locus Locus delta
44
+ * @returns {string}
45
+ */
46
+ static locus2string(locus: LocusDeltaDto): string;
28
47
  /**
29
48
  * Checks if two sequences overlap in time,
30
49
  * the sequence with the higher minimum value is greater.
@@ -206,6 +225,29 @@ export default class Parser {
206
225
  * @returns {undefined}
207
226
  */
208
227
  pause(): void;
228
+ /**
229
+ * Triggers a sync with Locus
230
+ *
231
+ * @param {string} reason used just for logging
232
+ * @returns {undefined}
233
+ */
234
+ private triggerSync;
235
+ /**
236
+ * Starts a timer with a random delay. When that timer expires we will do a sync.
237
+ *
238
+ * The main purpose of this timer is to handle a case when we get some out-of-order deltas,
239
+ * so we start waiting to receive the missing delta. If that delta never arrives, this timer
240
+ * will trigger a sync with Locus.
241
+ *
242
+ * @returns {undefined}
243
+ */
244
+ private startSyncTimer;
245
+ /**
246
+ * Stops the timer for triggering a sync
247
+ *
248
+ * @returns {undefined}
249
+ */
250
+ private stopSyncTimer;
209
251
  /**
210
252
  * Processes next locus delta in the queue,
211
253
  * continues until the queue is empty
@@ -226,3 +268,4 @@ export default class Parser {
226
268
  */
227
269
  static getDebugMessage(debugCode: string, comparison: string): any;
228
270
  }
271
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-beta.186",
3
+ "version": "3.0.0-beta.187",
4
4
  "description": "",
5
5
  "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
6
6
  "contributors": [
@@ -32,12 +32,12 @@
32
32
  "build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
33
33
  },
34
34
  "devDependencies": {
35
- "@webex/plugin-meetings": "3.0.0-beta.186",
36
- "@webex/test-helper-chai": "3.0.0-beta.186",
37
- "@webex/test-helper-mocha": "3.0.0-beta.186",
38
- "@webex/test-helper-mock-webex": "3.0.0-beta.186",
39
- "@webex/test-helper-retry": "3.0.0-beta.186",
40
- "@webex/test-helper-test-users": "3.0.0-beta.186",
35
+ "@webex/plugin-meetings": "3.0.0-beta.187",
36
+ "@webex/test-helper-chai": "3.0.0-beta.187",
37
+ "@webex/test-helper-mocha": "3.0.0-beta.187",
38
+ "@webex/test-helper-mock-webex": "3.0.0-beta.187",
39
+ "@webex/test-helper-retry": "3.0.0-beta.187",
40
+ "@webex/test-helper-test-users": "3.0.0-beta.187",
41
41
  "chai": "^4.3.4",
42
42
  "chai-as-promised": "^7.1.1",
43
43
  "jsdom-global": "3.0.2",
@@ -46,19 +46,19 @@
46
46
  "typescript": "^4.7.4"
47
47
  },
48
48
  "dependencies": {
49
- "@webex/common": "3.0.0-beta.186",
49
+ "@webex/common": "3.0.0-beta.187",
50
50
  "@webex/internal-media-core": "1.39.1",
51
- "@webex/internal-plugin-conversation": "3.0.0-beta.186",
52
- "@webex/internal-plugin-device": "3.0.0-beta.186",
53
- "@webex/internal-plugin-llm": "3.0.0-beta.186",
54
- "@webex/internal-plugin-mercury": "3.0.0-beta.186",
55
- "@webex/internal-plugin-metrics": "3.0.0-beta.186",
56
- "@webex/internal-plugin-support": "3.0.0-beta.186",
57
- "@webex/internal-plugin-user": "3.0.0-beta.186",
58
- "@webex/media-helpers": "3.0.0-beta.186",
59
- "@webex/plugin-people": "3.0.0-beta.186",
60
- "@webex/plugin-rooms": "3.0.0-beta.186",
61
- "@webex/webex-core": "3.0.0-beta.186",
51
+ "@webex/internal-plugin-conversation": "3.0.0-beta.187",
52
+ "@webex/internal-plugin-device": "3.0.0-beta.187",
53
+ "@webex/internal-plugin-llm": "3.0.0-beta.187",
54
+ "@webex/internal-plugin-mercury": "3.0.0-beta.187",
55
+ "@webex/internal-plugin-metrics": "3.0.0-beta.187",
56
+ "@webex/internal-plugin-support": "3.0.0-beta.187",
57
+ "@webex/internal-plugin-user": "3.0.0-beta.187",
58
+ "@webex/media-helpers": "3.0.0-beta.187",
59
+ "@webex/plugin-people": "3.0.0-beta.187",
60
+ "@webex/plugin-rooms": "3.0.0-beta.187",
61
+ "@webex/webex-core": "3.0.0-beta.187",
62
62
  "ampersand-collection": "^2.0.2",
63
63
  "bowser": "^2.11.0",
64
64
  "btoa": "^1.2.1",
@@ -1,13 +1,18 @@
1
1
  /**
2
- * Simple queue
2
+ * Simple queue in which the elements are always sorted
3
3
  */
4
- export default class SimpleQueue {
5
- queue: any[];
4
+ export default class SortedQueue<ItemType> {
5
+ queue: ItemType[];
6
+ // returns -1 if left < right, 0 if left === right, +1 if left > right
7
+ compareFunc: (left: ItemType, right: ItemType) => number;
8
+
6
9
  /**
7
- * @constructs SimpleQueue
10
+ * @constructs SortedQueue
11
+ * @param {Function} compareFunc comparison function used for sorting the elements of the queue
8
12
  */
9
- constructor() {
13
+ constructor(compareFunc: (left: ItemType, right: ItemType) => number) {
10
14
  this.queue = [];
15
+ this.compareFunc = compareFunc;
11
16
  }
12
17
 
13
18
  /**
@@ -23,8 +28,17 @@ export default class SimpleQueue {
23
28
  * @param {object} item
24
29
  * @returns {undefined}
25
30
  */
26
- enqueue(item: object) {
27
- this.queue.push(item);
31
+ enqueue(item: ItemType) {
32
+ // Find the index of the first item in the queue that's greater or equal to the new item.
33
+ // That's where we want to insert the new item.
34
+ const idx = this.queue.findIndex((existingItem) => {
35
+ return this.compareFunc(existingItem, item) >= 0;
36
+ });
37
+ if (idx >= 0) {
38
+ this.queue.splice(idx, 0, item);
39
+ } else {
40
+ this.queue.push(item);
41
+ }
28
42
  }
29
43
 
30
44
  /**
@@ -32,7 +46,7 @@ export default class SimpleQueue {
32
46
  * Returns null if the queue is empty.
33
47
  * @returns {(object|null)} Queue item or null.
34
48
  */
35
- dequeue() {
49
+ dequeue(): ItemType {
36
50
  if (this.queue.length === 0) {
37
51
  return null;
38
52
  }
@@ -108,23 +108,26 @@ export default class LocusInfo extends EventsScope {
108
108
  );
109
109
 
110
110
  // return value ignored on purpose
111
- meeting.meetingRequest.getLocusDTO({url}).then((res) => {
112
- if (isDelta) {
113
- if (!isEmpty(res.body)) {
114
- meeting.locusInfo.onDeltaLocus(res.body);
111
+ meeting.meetingRequest
112
+ .getLocusDTO({url})
113
+ .then((res) => {
114
+ if (isDelta) {
115
+ if (!isEmpty(res.body)) {
116
+ meeting.locusInfo.handleLocusDelta(res.body, meeting);
117
+ } else {
118
+ LoggerProxy.logger.info(
119
+ 'Locus-info:index#doLocusSync --> received empty body from syncUrl, so we already have latest Locus DTO'
120
+ );
121
+ }
115
122
  } else {
116
- LoggerProxy.logger.info(
117
- 'Locus-info:index#doLocusSync --> received empty body from syncUrl, so we already have latest Locus DTO'
118
- );
123
+ meeting.locusInfo.onFullLocus(res.body);
119
124
  }
120
- } else {
121
- meeting.locusInfo.onFullLocus(res.body);
122
- }
123
-
124
- // Notify parser to resume processing delta events.
125
- // Any deltas in the queue that have now been superseded by this sync will simply be ignored
126
- this.locusParser.resume();
127
- });
125
+ })
126
+ .finally(() => {
127
+ // Notify parser to resume processing delta events.
128
+ // Any deltas in the queue that have now been superseded by this sync will simply be ignored
129
+ this.locusParser.resume();
130
+ });
128
131
  }
129
132
 
130
133
  /**
@@ -135,13 +138,14 @@ export default class LocusInfo extends EventsScope {
135
138
  * @returns {undefined}
136
139
  */
137
140
  applyLocusDeltaData(action: string, locus: any, meeting: any) {
138
- const {DESYNC, USE_CURRENT, USE_INCOMING} = LocusDeltaParser.loci;
141
+ const {DESYNC, USE_CURRENT, USE_INCOMING, WAIT} = LocusDeltaParser.loci;
139
142
 
140
143
  switch (action) {
141
144
  case USE_INCOMING:
142
145
  meeting.locusInfo.onDeltaLocus(locus);
143
146
  break;
144
147
  case USE_CURRENT:
148
+ case WAIT:
145
149
  // do nothing
146
150
  break;
147
151
  case DESYNC:
@@ -314,6 +318,7 @@ export default class LocusInfo extends EventsScope {
314
318
 
315
319
  return;
316
320
  }
321
+
317
322
  this.updateParticipantDeltas(locus.participants);
318
323
  this.scheduledMeeting = locus.meeting || null;
319
324
  this.participants = locus.participants;
@@ -1,8 +1,26 @@
1
1
  import {difference} from 'lodash';
2
2
 
3
- import SimpleQueue from '../common/queue';
3
+ import SortedQueue from '../common/queue';
4
4
  import LoggerProxy from '../common/logs/logger-proxy';
5
5
 
6
+ const MAX_OOO_DELTA_COUNT = 5; // when we receive an out-of-order delta and the queue builds up to MAX_OOO_DELTA_COUNT, we do a sync with Locus
7
+ const OOO_DELTA_WAIT_TIME = 10000; // [ms] minimum wait time before we do a sync if we get out-of-order deltas
8
+ const OOO_DELTA_WAIT_TIME_RANDOM_DELAY = 5000; // [ms] max random delay added to OOO_DELTA_WAIT_TIME
9
+
10
+ type LocusDeltaDto = {
11
+ baseSequence: {
12
+ rangeStart: number;
13
+ rangeEnd: number;
14
+ entries: number[];
15
+ };
16
+ sequence: {
17
+ rangeStart: number;
18
+ rangeEnd: number;
19
+ entries: number[];
20
+ };
21
+ syncUrl: string;
22
+ };
23
+
6
24
  /**
7
25
  * Locus Delta Parser
8
26
  * @private
@@ -10,11 +28,11 @@ import LoggerProxy from '../common/logs/logger-proxy';
10
28
  */
11
29
  export default class Parser {
12
30
  // processing status
13
- static status = {
14
- IDLE: 'IDLE',
15
- PAUSED: 'PAUSED',
16
- WORKING: 'WORKING',
17
- };
31
+ status:
32
+ | 'IDLE' // not doing anything
33
+ | 'PAUSED' // paused, because we are doing a sync
34
+ | 'WORKING' // processing a delta event
35
+ | 'BLOCKED'; // received an out-of-order delta, so waiting for the missing one
18
36
 
19
37
  // loci comparison states
20
38
  static loci = {
@@ -24,21 +42,59 @@ export default class Parser {
24
42
  DESYNC: 'DESYNC',
25
43
  USE_INCOMING: 'USE_INCOMING',
26
44
  USE_CURRENT: 'USE_CURRENT',
45
+ WAIT: 'WAIT',
27
46
  ERROR: 'ERROR',
28
47
  };
29
48
 
30
- queue: SimpleQueue;
49
+ queue: SortedQueue<LocusDeltaDto>;
31
50
  workingCopy: any;
51
+ syncTimer: null | number | NodeJS.Timeout;
32
52
 
33
53
  /**
34
54
  * @constructs Parser
35
55
  */
36
56
  constructor() {
37
- this.queue = new SimpleQueue();
38
- // @ts-ignore - This is declared as static class member and again being initialized here from same
39
- this.status = Parser.status.IDLE;
57
+ const deltaCompareFunc = (left: LocusDeltaDto, right: LocusDeltaDto) => {
58
+ const {LT, GT} = Parser.loci;
59
+ const {extractComparisonState: extract} = Parser;
60
+
61
+ if (Parser.isSequenceEmpty(left)) {
62
+ return -1;
63
+ }
64
+ if (Parser.isSequenceEmpty(right)) {
65
+ return 1;
66
+ }
67
+ const result = extract(Parser.compareSequence(left.baseSequence, right.baseSequence));
68
+
69
+ if (result === LT) {
70
+ return -1;
71
+ }
72
+ if (result === GT) {
73
+ return 1;
74
+ }
75
+
76
+ return 0;
77
+ };
78
+
79
+ this.queue = new SortedQueue<LocusDeltaDto>(deltaCompareFunc);
80
+ this.status = 'IDLE';
40
81
  this.onDeltaAction = null;
41
82
  this.workingCopy = null;
83
+ this.syncTimer = null;
84
+ }
85
+
86
+ /**
87
+ * Returns a debug string representing a locus delta - useful for logging
88
+ *
89
+ * @param {LocusDeltaDto} locus Locus delta
90
+ * @returns {string}
91
+ */
92
+ static locus2string(locus: LocusDeltaDto) {
93
+ if (!locus.sequence?.entries) {
94
+ return 'invalid';
95
+ }
96
+
97
+ return locus.sequence.entries.length ? `seq=${locus.sequence.entries.at(-1)}` : 'empty';
42
98
  }
43
99
 
44
100
  /**
@@ -208,7 +264,7 @@ export default class Parser {
208
264
  * @returns {string} loci comparison state
209
265
  */
210
266
  private static compareDelta(current, incoming) {
211
- const {LT, GT, EQ, DESYNC, USE_INCOMING} = Parser.loci;
267
+ const {LT, GT, EQ, DESYNC, USE_INCOMING, WAIT} = Parser.loci;
212
268
 
213
269
  const {extractComparisonState: extract} = Parser;
214
270
  const {packComparisonResult: pack} = Parser;
@@ -228,6 +284,17 @@ export default class Parser {
228
284
  comparison = USE_INCOMING;
229
285
  break;
230
286
 
287
+ case LT:
288
+ if (extract(Parser.compareSequence(incoming.baseSequence, incoming.sequence)) === EQ) {
289
+ // special case where Locus sends a delta with baseSequence === sequence to trigger a sync,
290
+ // because the delta event is too large to be sent over mercury connection
291
+ comparison = DESYNC;
292
+ } else {
293
+ // the incoming locus has baseSequence from the future, so it is out-of-order,
294
+ // we are missing 1 or more locus that should be in front of it, we need to wait for it
295
+ comparison = WAIT;
296
+ }
297
+ break;
231
298
  default:
232
299
  comparison = DESYNC;
233
300
  }
@@ -436,17 +503,10 @@ export default class Parser {
436
503
  */
437
504
  isValidLocus(newLoci) {
438
505
  let isValid = false;
439
- const {IDLE} = Parser.status;
440
506
  const {isLoci} = Parser;
441
- // @ts-ignore
442
- const setStatus = (status) => {
443
- // @ts-ignore
444
- this.status = status;
445
- };
446
507
 
447
508
  // one or both objects are not locus delta events
448
509
  if (!isLoci(this.workingCopy) || !isLoci(newLoci)) {
449
- setStatus(IDLE);
450
510
  LoggerProxy.logger.info(
451
511
  'Locus-info:parser#processDeltaEvent --> Ignoring non-locus object. workingCopy:',
452
512
  this.workingCopy,
@@ -498,19 +558,25 @@ export default class Parser {
498
558
  * @returns {undefined}
499
559
  */
500
560
  nextEvent() {
501
- // @ts-ignore
502
- if (this.status === Parser.status.PAUSED) {
561
+ if (this.status === 'PAUSED') {
503
562
  LoggerProxy.logger.info('Locus-info:parser#nextEvent --> Locus parser paused.');
504
563
 
505
564
  return;
506
565
  }
507
566
 
567
+ if (this.status === 'BLOCKED') {
568
+ LoggerProxy.logger.info(
569
+ 'Locus-info:parser#nextEvent --> Locus parser blocked by out-of-order delta.'
570
+ );
571
+
572
+ return;
573
+ }
574
+
508
575
  // continue processing until queue is empty
509
576
  if (this.queue.size() > 0) {
510
577
  this.processDeltaEvent();
511
578
  } else {
512
- // @ts-ignore
513
- this.status = Parser.status.IDLE;
579
+ this.status = 'IDLE';
514
580
  }
515
581
  }
516
582
 
@@ -532,15 +598,20 @@ export default class Parser {
532
598
  onDeltaEvent(loci) {
533
599
  // enqueue the new loci
534
600
  this.queue.enqueue(loci);
535
- // start processing events in the queue if idle
536
- // and a function handler is defined
537
- // @ts-ignore
538
- if (this.status === Parser.status.IDLE && this.onDeltaAction) {
539
- // Update status, ensure we only process one event at a time.
540
- // @ts-ignore
541
- this.status = Parser.status.WORKING;
542
601
 
543
- this.processDeltaEvent();
602
+ if (this.onDeltaAction) {
603
+ if (this.status === 'BLOCKED') {
604
+ if (this.queue.size() > MAX_OOO_DELTA_COUNT) {
605
+ this.triggerSync('queue too big, blocked on out-of-order delta');
606
+ } else {
607
+ this.processDeltaEvent();
608
+ }
609
+ } else if (this.status === 'IDLE') {
610
+ // Update status, ensure we only process one event at a time.
611
+ this.status = 'WORKING';
612
+
613
+ this.processDeltaEvent();
614
+ }
544
615
  }
545
616
  }
546
617
 
@@ -559,11 +630,55 @@ export default class Parser {
559
630
  * @returns {undefined}
560
631
  */
561
632
  pause() {
562
- // @ts-ignore
563
- this.status = Parser.status.PAUSED;
633
+ this.status = 'PAUSED';
564
634
  LoggerProxy.logger.info('Locus-info:parser#pause --> Locus parser paused.');
565
635
  }
566
636
 
637
+ /**
638
+ * Triggers a sync with Locus
639
+ *
640
+ * @param {string} reason used just for logging
641
+ * @returns {undefined}
642
+ */
643
+ private triggerSync(reason: string) {
644
+ LoggerProxy.logger.info(`Locus-info:parser#triggerSync --> doing sync, reason: ${reason}`);
645
+ this.stopSyncTimer();
646
+ this.pause();
647
+ this.onDeltaAction(Parser.loci.DESYNC, this.workingCopy);
648
+ }
649
+
650
+ /**
651
+ * Starts a timer with a random delay. When that timer expires we will do a sync.
652
+ *
653
+ * The main purpose of this timer is to handle a case when we get some out-of-order deltas,
654
+ * so we start waiting to receive the missing delta. If that delta never arrives, this timer
655
+ * will trigger a sync with Locus.
656
+ *
657
+ * @returns {undefined}
658
+ */
659
+ private startSyncTimer() {
660
+ if (this.syncTimer === null) {
661
+ const timeout = OOO_DELTA_WAIT_TIME + Math.random() * OOO_DELTA_WAIT_TIME_RANDOM_DELAY;
662
+
663
+ this.syncTimer = setTimeout(() => {
664
+ this.syncTimer = null;
665
+ this.triggerSync('timer expired, blocked on out-of-order delta');
666
+ }, timeout);
667
+ }
668
+ }
669
+
670
+ /**
671
+ * Stops the timer for triggering a sync
672
+ *
673
+ * @returns {undefined}
674
+ */
675
+ private stopSyncTimer() {
676
+ if (this.syncTimer !== null) {
677
+ clearTimeout(this.syncTimer);
678
+ this.syncTimer = null;
679
+ }
680
+ }
681
+
567
682
  /**
568
683
  * Processes next locus delta in the queue,
569
684
  * continues until the queue is empty
@@ -571,11 +686,13 @@ export default class Parser {
571
686
  * @returns {undefined}
572
687
  */
573
688
  processDeltaEvent() {
574
- const {DESYNC, USE_INCOMING} = Parser.loci;
689
+ const {DESYNC, USE_INCOMING, WAIT} = Parser.loci;
575
690
  const {extractComparisonState: extract} = Parser;
576
691
  const newLoci = this.queue.dequeue();
577
692
 
578
693
  if (!this.isValidLocus(newLoci)) {
694
+ this.nextEvent();
695
+
579
696
  return;
580
697
  }
581
698
 
@@ -586,6 +703,8 @@ export default class Parser {
586
703
  // for full debugging.
587
704
  LoggerProxy.logger.debug(`Locus-info:parser#processDeltaEvent --> Locus Debug: ${result}`);
588
705
 
706
+ let needToWait = false;
707
+
589
708
  if (lociComparison === DESYNC) {
590
709
  // wait for desync response
591
710
  this.pause();
@@ -594,15 +713,39 @@ export default class Parser {
594
713
  // Note: The working copy of parser gets updated in .onFullLocus()
595
714
  // and here when USE_INCOMING locus.
596
715
  this.workingCopy = newLoci;
716
+ } else if (lociComparison === WAIT) {
717
+ // we've taken newLoci from the front of the queue, so put it back there as we have to wait
718
+ // for the one that should be in front of it, before we can process it
719
+ this.queue.enqueue(newLoci);
720
+ needToWait = true;
721
+ }
722
+
723
+ if (needToWait) {
724
+ this.status = 'BLOCKED';
725
+ this.startSyncTimer();
726
+ } else {
727
+ this.stopSyncTimer();
728
+
729
+ if (this.status === 'BLOCKED') {
730
+ // we are not blocked anymore
731
+ this.status = 'WORKING';
732
+
733
+ LoggerProxy.logger.info(
734
+ `Locus-info:parser#processDeltaEvent --> received delta that we were waiting for ${Parser.locus2string(
735
+ newLoci
736
+ )}, not blocked anymore`
737
+ );
738
+ }
597
739
  }
598
740
 
599
741
  if (this.onDeltaAction) {
600
742
  LoggerProxy.logger.info(
601
- `Locus-info:parser#processDeltaEvent --> Locus Delta Action: ${lociComparison}`
743
+ `Locus-info:parser#processDeltaEvent --> Locus Delta ${Parser.locus2string(
744
+ newLoci
745
+ )}, Action: ${lociComparison}`
602
746
  );
603
747
 
604
- // eslint-disable-next-line no-useless-call
605
- this.onDeltaAction.call(this, lociComparison, newLoci);
748
+ this.onDeltaAction(lociComparison, newLoci);
606
749
  }
607
750
 
608
751
  this.nextEvent();
@@ -614,8 +757,7 @@ export default class Parser {
614
757
  */
615
758
  resume() {
616
759
  LoggerProxy.logger.info('Locus-info:parser#resume --> Locus parser resumed.');
617
- // @ts-ignore
618
- this.status = Parser.status.WORKING;
760
+ this.status = 'WORKING';
619
761
  this.nextEvent();
620
762
  }
621
763
 
@@ -1,5 +1,5 @@
1
1
  import {assert} from '@webex/test-helper-chai';
2
- import SimpleQueue from '@webex/plugin-meetings/src/common/queue';
2
+ import SortedQueue from '@webex/plugin-meetings/src/common/queue';
3
3
 
4
4
  describe('common/queue', () => {
5
5
  let fifo = null;
@@ -11,7 +11,15 @@ describe('common/queue', () => {
11
11
  };
12
12
 
13
13
  beforeEach(() => {
14
- fifo = new SimpleQueue();
14
+ fifo = new SortedQueue((left, right) => {
15
+ if (left.text > right.text) {
16
+ return 1;
17
+ }
18
+ if (left.text < right.text) {
19
+ return -1;
20
+ }
21
+ return 0;
22
+ });
15
23
  });
16
24
 
17
25
  afterEach(() => {
@@ -66,4 +74,25 @@ describe('common/queue', () => {
66
74
  it('Returns null if the queue is empty.', () => {
67
75
  assert.equal(fifo.dequeue(), null);
68
76
  });
77
+
78
+ it('Implement lifo', () => {
79
+ const lifo = new SortedQueue((left, right) => {
80
+ if (left.text < right.text) {
81
+ return 1;
82
+ }
83
+ if (left.text > right.text) {
84
+ return -1;
85
+ }
86
+ return 0;
87
+ });
88
+
89
+ const item1 = {text: 'fake item1'};
90
+ const item2 = {text: 'fake item2'};
91
+
92
+ lifo.enqueue(item1);
93
+ lifo.enqueue(item2);
94
+
95
+ assert.equal(lifo.dequeue(), item2);
96
+ assert.equal(lifo.dequeue(), item1);
97
+ });
69
98
  });