-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathAbstractMySegmentsCacheSync.ts
More file actions
100 lines (78 loc) · 3.12 KB
/
AbstractMySegmentsCacheSync.ts
File metadata and controls
100 lines (78 loc) · 3.12 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
96
97
98
99
100
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
/**
* 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.
registerSegments(): boolean { return false; }
update() { return false; }
/**
* For server-side synchronizer: get the list of segments to fetch changes.
* Also used for the `seC` (segment count) telemetry stat.
*/
abstract getRegisteredSegments(): string[]
/**
* 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 {
let isDiff = false;
const { added, removed } = segmentsData as MySegmentsData;
if (added && removed) {
added.forEach(segment => {
isDiff = this.addSegment(segment) || isDiff;
});
removed.forEach(segment => {
isDiff = this.removeSegment(segment) || isDiff;
});
} else {
const names = ((segmentsData as IMySegmentsResponse).k || []).map(s => s.n).sort();
const storedSegmentKeys = this.getRegisteredSegments().sort();
// Extreme fast => everything is empty
if (!names.length && !storedSegmentKeys.length) {
isDiff = false;
} else {
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) {
isDiff = false;
} else {
// 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]);
}
isDiff = true;
}
}
}
this.setChangeNumber(segmentsData.cn);
return isDiff;
}
}