-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathAbstractMySegmentsCacheSync.ts
More file actions
95 lines (72 loc) · 2.9 KB
/
AbstractMySegmentsCacheSync.ts
File metadata and controls
95 lines (72 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { IMySegmentsResponse } from '../dtos/types';
import { MySegmentsData } from '../sync/polling/types';
import { ISegmentsCacheSync } from './types';
/**
* This class provides a skeletal implementation of the ISegmentsCacheSync interface
* to minimize the effort required to implement this interface.
*/
export abstract class AbstractMySegmentsCacheSync implements ISegmentsCacheSync {
protected abstract addSegment(name: string): boolean
protected abstract removeSegment(name: string): boolean
protected abstract setChangeNumber(changeNumber?: number): boolean | void
protected abstract getSegments(): string[]
/**
* For server-side synchronizer: check if `key` is in `name` segment.
* For client-side synchronizer: check if `name` segment is in the cache. `key` is undefined.
*/
abstract isInSegment(name: string, key?: string): boolean
/**
* clear the cache.
*/
clear() {
this.resetSegments({});
}
// No-op. Not used in client-side.
update() { return false; }
/**
* Used for the `seC` (segment count) telemetry stat.
*/
getSegmentsCount() {
return this.getSegments().length;
}
/**
* Only used for the `skC`(segment keys count) telemetry stat: 1 for client-side, and total count of keys in server-side.
*/
// @TODO for client-side it should be the number of clients, but it requires a refactor of MySegments caches to simplify the code.
abstract getKeysCount(): number
abstract getChangeNumber(): number
/**
* For server-side synchronizer: the method is not used.
* For client-side synchronizer: it resets or updates the cache.
*/
resetSegments(segmentsData: MySegmentsData | IMySegmentsResponse): boolean {
this.setChangeNumber(segmentsData.cn);
const { added, removed } = segmentsData as MySegmentsData;
if (added && removed) {
let isDiff = false;
added.forEach(segment => {
isDiff = this.addSegment(segment) || isDiff;
});
removed.forEach(segment => {
isDiff = this.removeSegment(segment) || isDiff;
});
return isDiff;
}
const names = ((segmentsData as IMySegmentsResponse).k || []).map(s => s.n).sort();
const storedSegmentKeys = this.getSegments().sort();
// Extreme fast => everything is empty
if (!names.length && !storedSegmentKeys.length) return false;
let index = 0;
while (index < names.length && index < storedSegmentKeys.length && names[index] === storedSegmentKeys[index]) index++;
// Quick path => no changes
if (index === names.length && index === storedSegmentKeys.length) return false;
// Slowest path => add and/or remove segments
for (let removeIndex = index; removeIndex < storedSegmentKeys.length; removeIndex++) {
this.removeSegment(storedSegmentKeys[removeIndex]);
}
for (let addIndex = index; addIndex < names.length; addIndex++) {
this.addSegment(names[addIndex]);
}
return true;
}
}