@splitsoftware/splitio-commons 1.16.1-rc.10 → 1.16.1-rc.12
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/cjs/logger/constants.js +2 -2
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/services/splitApi.js +3 -3
- package/cjs/storages/AbstractSegmentsCacheSync.js +41 -7
- package/cjs/storages/dataLoader.js +1 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +19 -63
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +5 -40
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +1 -1
- package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +2 -2
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +12 -21
- package/cjs/sync/streaming/AuthClient/index.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +5 -7
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +106 -63
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/pushManager.js +25 -31
- package/cjs/utils/constants/index.js +3 -4
- package/esm/logger/constants.js +1 -1
- package/esm/logger/messages/warn.js +1 -1
- package/esm/services/splitApi.js +4 -4
- package/esm/storages/AbstractSegmentsCacheSync.js +41 -7
- package/esm/storages/dataLoader.js +1 -1
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +19 -63
- package/esm/storages/inMemory/MySegmentsCacheInMemory.js +5 -40
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +1 -1
- package/esm/sync/polling/fetchers/mySegmentsFetcher.js +2 -2
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +12 -21
- package/esm/sync/streaming/AuthClient/index.js +1 -1
- package/esm/sync/streaming/SSEHandler/index.js +6 -8
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +106 -63
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/pushManager.js +28 -34
- package/esm/utils/constants/index.js +1 -2
- package/package.json +1 -1
- package/src/dtos/types.ts +9 -12
- package/src/logger/constants.ts +1 -1
- package/src/logger/messages/warn.ts +1 -1
- package/src/services/splitApi.ts +4 -4
- package/src/services/types.ts +1 -1
- package/src/storages/AbstractSegmentsCacheSync.ts +52 -7
- package/src/storages/AbstractSplitsCacheSync.ts +1 -1
- package/src/storages/dataLoader.ts +1 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +15 -69
- package/src/storages/inMemory/MySegmentsCacheInMemory.ts +6 -46
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +1 -1
- package/src/storages/types.ts +6 -5
- package/src/sync/polling/fetchers/mySegmentsFetcher.ts +2 -1
- package/src/sync/polling/fetchers/types.ts +1 -0
- package/src/sync/polling/types.ts +9 -10
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +15 -19
- package/src/sync/streaming/AuthClient/index.ts +1 -1
- package/src/sync/streaming/SSEHandler/index.ts +9 -11
- package/src/sync/streaming/SSEHandler/types.ts +6 -6
- package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +114 -65
- package/src/sync/streaming/constants.ts +2 -2
- package/src/sync/streaming/parseUtils.ts +2 -2
- package/src/sync/streaming/pushManager.ts +30 -39
- package/src/sync/streaming/types.ts +6 -6
- package/src/sync/submitters/types.ts +4 -5
- package/src/utils/constants/index.ts +1 -2
- package/types/dtos/types.d.ts +8 -12
- package/types/logger/constants.d.ts +1 -1
- package/types/services/types.d.ts +1 -1
- package/types/storages/AbstractSegmentsCacheSync.d.ts +8 -6
- package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +1 -12
- package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +1 -9
- package/types/storages/types.d.ts +6 -5
- package/types/sync/polling/fetchers/types.d.ts +1 -1
- package/types/sync/polling/types.d.ts +9 -7
- package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +1 -1
- package/types/sync/streaming/SSEHandler/types.d.ts +6 -6
- package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +3 -2
- package/types/sync/streaming/constants.d.ts +2 -2
- package/types/sync/streaming/parseUtils.d.ts +2 -2
- package/types/sync/streaming/types.d.ts +5 -5
- package/types/sync/submitters/types.d.ts +4 -5
- package/types/utils/constants/index.d.ts +1 -2
|
@@ -16,22 +16,11 @@ export class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
|
|
|
16
16
|
// There is not need to flush segments cache like splits cache, since resetSegments receives the up-to-date list of active segments
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
* Removes list of segments from localStorage
|
|
21
|
-
* @NOTE this method is not being used at the moment.
|
|
22
|
-
*/
|
|
23
|
-
clear() {
|
|
24
|
-
this.log.info(LOG_PREFIX + 'Flushing MySegments data from localStorage');
|
|
25
|
-
|
|
26
|
-
// We cannot simply call `localStorage.clear()` since that implies removing user items from the storage
|
|
27
|
-
// We could optimize next sentence, since it implies iterating over all localStorage items
|
|
28
|
-
this.resetSegments([]);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
19
|
addToSegment(name: string): boolean {
|
|
32
20
|
const segmentKey = this.keys.buildSegmentNameKey(name);
|
|
33
21
|
|
|
34
22
|
try {
|
|
23
|
+
if (localStorage.getItem(segmentKey) === DEFINED) return false;
|
|
35
24
|
localStorage.setItem(segmentKey, DEFINED);
|
|
36
25
|
return true;
|
|
37
26
|
} catch (e) {
|
|
@@ -44,6 +33,7 @@ export class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
|
|
|
44
33
|
const segmentKey = this.keys.buildSegmentNameKey(name);
|
|
45
34
|
|
|
46
35
|
try {
|
|
36
|
+
if (localStorage.getItem(segmentKey) !== DEFINED) return false;
|
|
47
37
|
localStorage.removeItem(segmentKey);
|
|
48
38
|
return true;
|
|
49
39
|
} catch (e) {
|
|
@@ -56,41 +46,22 @@ export class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
|
|
|
56
46
|
return localStorage.getItem(this.keys.buildSegmentNameKey(name)) === DEFINED;
|
|
57
47
|
}
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
* Reset (update) the cached list of segments with the given list, removing and adding segments if necessary.
|
|
61
|
-
*
|
|
62
|
-
* @param {string[]} names list of segment names
|
|
63
|
-
* @returns boolean indicating if the cache was updated (i.e., given list was different from the cached one)
|
|
64
|
-
*/
|
|
65
|
-
resetSegments(names: string[], changeNumber?: number): boolean {
|
|
66
|
-
try {
|
|
67
|
-
if (changeNumber) {
|
|
68
|
-
localStorage.setItem(this.keys.buildTillKey(), changeNumber + '');
|
|
69
|
-
} else {
|
|
70
|
-
localStorage.removeItem(this.keys.buildTillKey());
|
|
71
|
-
}
|
|
72
|
-
} catch (e) {
|
|
73
|
-
this.log.error(e);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
let isDiff = false;
|
|
77
|
-
let index;
|
|
78
|
-
|
|
49
|
+
getRegisteredSegments(): string[] {
|
|
79
50
|
// Scan current values from localStorage
|
|
80
|
-
|
|
51
|
+
return Object.keys(localStorage).reduce((accum, key) => {
|
|
81
52
|
let segmentName = this.keys.extractSegmentName(key);
|
|
82
53
|
|
|
83
54
|
if (segmentName) {
|
|
84
55
|
accum.push(segmentName);
|
|
85
56
|
} else {
|
|
86
|
-
// @TODO @BREAKING: This is only to clean up "old" keys. Remove this whole else code block
|
|
57
|
+
// @TODO @BREAKING: This is only to clean up "old" keys. Remove this whole else code block
|
|
87
58
|
segmentName = this.keys.extractOldSegmentKey(key);
|
|
88
59
|
|
|
89
60
|
if (segmentName) { // this was an old segment key, let's clean up.
|
|
90
61
|
const newSegmentKey = this.keys.buildSegmentNameKey(segmentName);
|
|
91
62
|
try {
|
|
92
63
|
// If the new format key is not there, create it.
|
|
93
|
-
if (!localStorage.getItem(newSegmentKey)
|
|
64
|
+
if (!localStorage.getItem(newSegmentKey)) {
|
|
94
65
|
localStorage.setItem(newSegmentKey, DEFINED);
|
|
95
66
|
// we are migrating a segment, let's track it.
|
|
96
67
|
accum.push(segmentName);
|
|
@@ -104,46 +75,21 @@ export class MySegmentsCacheInLocal extends AbstractSegmentsCacheSync {
|
|
|
104
75
|
|
|
105
76
|
return accum;
|
|
106
77
|
}, [] as string[]);
|
|
107
|
-
|
|
108
|
-
// Extreme fast => everything is empty
|
|
109
|
-
if (names.length === 0 && storedSegmentNames.length === names.length)
|
|
110
|
-
return isDiff;
|
|
111
|
-
|
|
112
|
-
// Quick path
|
|
113
|
-
if (storedSegmentNames.length !== names.length) {
|
|
114
|
-
isDiff = true;
|
|
115
|
-
|
|
116
|
-
storedSegmentNames.forEach(name => this.removeFromSegment(name));
|
|
117
|
-
names.forEach(name => this.addToSegment(name));
|
|
118
|
-
} else {
|
|
119
|
-
// Slowest path => we need to find at least 1 difference because
|
|
120
|
-
for (index = 0; index < names.length && storedSegmentNames.indexOf(names[index]) !== -1; index++) {
|
|
121
|
-
// TODO: why empty statement?
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (index < names.length) {
|
|
125
|
-
isDiff = true;
|
|
126
|
-
|
|
127
|
-
storedSegmentNames.forEach(name => this.removeFromSegment(name));
|
|
128
|
-
names.forEach(name => this.addToSegment(name));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return isDiff;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
getRegisteredSegments(): string[] {
|
|
136
|
-
return Object.keys(localStorage).reduce<string[]>((accum, key) => {
|
|
137
|
-
const segmentName = this.keys.extractSegmentName(key);
|
|
138
|
-
if (segmentName) accum.push(segmentName);
|
|
139
|
-
return accum;
|
|
140
|
-
}, []);
|
|
141
78
|
}
|
|
142
79
|
|
|
143
80
|
getKeysCount() {
|
|
144
81
|
return 1;
|
|
145
82
|
}
|
|
146
83
|
|
|
84
|
+
setChangeNumber(name?: string, changeNumber?: number) {
|
|
85
|
+
try {
|
|
86
|
+
if (changeNumber) localStorage.setItem(this.keys.buildTillKey(), changeNumber + '');
|
|
87
|
+
else localStorage.removeItem(this.keys.buildTillKey());
|
|
88
|
+
} catch (e) {
|
|
89
|
+
this.log.error(e);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
147
93
|
getChangeNumber() {
|
|
148
94
|
const n = -1;
|
|
149
95
|
let value: string | number | null = localStorage.getItem(this.keys.buildTillKey());
|
|
@@ -9,17 +9,17 @@ export class MySegmentsCacheInMemory extends AbstractSegmentsCacheSync {
|
|
|
9
9
|
private segmentCache: Record<string, boolean> = {};
|
|
10
10
|
private cn?: number;
|
|
11
11
|
|
|
12
|
-
clear() {
|
|
13
|
-
this.segmentCache = {};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
addToSegment(name: string): boolean {
|
|
13
|
+
if (this.segmentCache[name]) return false;
|
|
14
|
+
|
|
17
15
|
this.segmentCache[name] = true;
|
|
18
16
|
|
|
19
17
|
return true;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
removeFromSegment(name: string): boolean {
|
|
21
|
+
if (!this.segmentCache[name]) return false;
|
|
22
|
+
|
|
23
23
|
delete this.segmentCache[name];
|
|
24
24
|
|
|
25
25
|
return true;
|
|
@@ -29,49 +29,9 @@ export class MySegmentsCacheInMemory extends AbstractSegmentsCacheSync {
|
|
|
29
29
|
return this.segmentCache[name] === true;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* Reset (update) the cached list of segments with the given list, removing and adding segments if necessary.
|
|
34
|
-
* @NOTE based on the way we use segments in the browser, this way is the best option
|
|
35
|
-
*
|
|
36
|
-
* @param {string[]} names list of segment names
|
|
37
|
-
* @returns boolean indicating if the cache was updated (i.e., given list was different from the cached one)
|
|
38
|
-
*/
|
|
39
|
-
resetSegments(names: string[], changeNumber?: number): boolean {
|
|
40
|
-
this.cn = changeNumber;
|
|
41
|
-
let isDiff = false;
|
|
42
|
-
let index;
|
|
43
|
-
|
|
44
|
-
const storedSegmentKeys = Object.keys(this.segmentCache);
|
|
45
32
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return isDiff;
|
|
49
|
-
|
|
50
|
-
// Quick path
|
|
51
|
-
if (storedSegmentKeys.length !== names.length) {
|
|
52
|
-
isDiff = true;
|
|
53
|
-
|
|
54
|
-
this.segmentCache = {};
|
|
55
|
-
names.forEach(s => {
|
|
56
|
-
this.addToSegment(s);
|
|
57
|
-
});
|
|
58
|
-
} else {
|
|
59
|
-
// Slowest path => we need to find at least 1 difference because
|
|
60
|
-
for (index = 0; index < names.length && this.isInSegment(names[index]); index++) {
|
|
61
|
-
// TODO: why empty statement?
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (index < names.length) {
|
|
65
|
-
isDiff = true;
|
|
66
|
-
|
|
67
|
-
this.segmentCache = {};
|
|
68
|
-
names.forEach(s => {
|
|
69
|
-
this.addToSegment(s);
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return isDiff;
|
|
33
|
+
setChangeNumber(name?: string, changeNumber?: number) {
|
|
34
|
+
this.cn = changeNumber;
|
|
75
35
|
}
|
|
76
36
|
|
|
77
37
|
getChangeNumber() {
|
|
@@ -51,7 +51,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
51
51
|
spC: this.splits && this.splits.getSplitNames().length,
|
|
52
52
|
seC: this.segments && this.segments.getRegisteredSegments().length,
|
|
53
53
|
skC: this.segments && this.segments.getKeysCount(),
|
|
54
|
-
|
|
54
|
+
lsC: this.largeSegments && this.largeSegments.getRegisteredSegments().length,
|
|
55
55
|
lskC: this.largeSegments && this.largeSegments.getKeysCount(),
|
|
56
56
|
sL: this.getSessionLength(),
|
|
57
57
|
eQ: this.getEventStats(QUEUED),
|
package/src/storages/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { MaybeThenable, ISplit } from '../dtos/types';
|
|
1
|
+
import { MaybeThenable, ISplit, IMySegmentsResponse } from '../dtos/types';
|
|
2
|
+
import { MySegmentsData } from '../sync/polling/types';
|
|
2
3
|
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, MultiMethodExceptions, MultiMethodLatencies, MultiConfigs, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
3
4
|
import { SplitIO, ImpressionDTO, ISettings } from '../types';
|
|
4
5
|
import { ISet } from '../utils/lang/sets';
|
|
@@ -218,7 +219,7 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
|
|
|
218
219
|
removeSplits(names: string[]): boolean[],
|
|
219
220
|
getSplit(name: string): ISplit | null,
|
|
220
221
|
getSplits(names: string[]): Record<string, ISplit | null>,
|
|
221
|
-
setChangeNumber(changeNumber: number): boolean,
|
|
222
|
+
setChangeNumber(changeNumber: number): boolean | void,
|
|
222
223
|
getChangeNumber(): number,
|
|
223
224
|
getAll(): ISplit[],
|
|
224
225
|
getSplitNames(): string[],
|
|
@@ -268,9 +269,9 @@ export interface ISegmentsCacheSync extends ISegmentsCacheBase {
|
|
|
268
269
|
registerSegments(names: string[]): boolean
|
|
269
270
|
getRegisteredSegments(): string[]
|
|
270
271
|
getKeysCount(): number // only used for telemetry
|
|
271
|
-
setChangeNumber(name: string, changeNumber: number): boolean
|
|
272
|
-
getChangeNumber(name
|
|
273
|
-
resetSegments(
|
|
272
|
+
setChangeNumber(name: string, changeNumber: number): boolean | void
|
|
273
|
+
getChangeNumber(name?: string): number
|
|
274
|
+
resetSegments(segmentsData: MySegmentsData | IMySegmentsResponse): boolean // only for Sync Client-Side
|
|
274
275
|
clear(): void
|
|
275
276
|
}
|
|
276
277
|
|
|
@@ -11,11 +11,12 @@ export function mySegmentsFetcherFactory(fetchMemberships: IFetchMemberships): I
|
|
|
11
11
|
return function mySegmentsFetcher(
|
|
12
12
|
userMatchingKey: string,
|
|
13
13
|
noCache?: boolean,
|
|
14
|
+
till?: number,
|
|
14
15
|
// Optional decorator for `fetchMemberships` promise, such as timeout or time tracker
|
|
15
16
|
decorator?: (promise: Promise<IResponse>) => Promise<IResponse>
|
|
16
17
|
): Promise<IMembershipsResponse> {
|
|
17
18
|
|
|
18
|
-
let mySegmentsPromise = fetchMemberships(userMatchingKey, noCache);
|
|
19
|
+
let mySegmentsPromise = fetchMemberships(userMatchingKey, noCache, till);
|
|
19
20
|
if (decorator) mySegmentsPromise = decorator(mySegmentsPromise);
|
|
20
21
|
|
|
21
22
|
return mySegmentsPromise.then(resp => resp.json());
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ISplit } from '../../dtos/types';
|
|
2
2
|
import { IReadinessManager } from '../../readiness/types';
|
|
3
3
|
import { IStorageSync } from '../../storages/types';
|
|
4
|
+
import { MEMBERSHIPS_LS_UPDATE, MEMBERSHIPS_MS_UPDATE } from '../streaming/types';
|
|
4
5
|
import { ITask, ISyncTask } from '../types';
|
|
5
6
|
|
|
6
7
|
export interface ISplitsSyncTask extends ISyncTask<[noCache?: boolean, till?: number, splitUpdateNotification?: { payload: ISplit, changeNumber: number }], boolean> { }
|
|
7
8
|
|
|
8
9
|
export interface ISegmentsSyncTask extends ISyncTask<[fetchOnlyNew?: boolean, segmentName?: string, noCache?: boolean, till?: number], boolean> { }
|
|
9
10
|
|
|
10
|
-
export type MySegmentsData =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
add: boolean
|
|
17
|
-
}[]
|
|
11
|
+
export type MySegmentsData = {
|
|
12
|
+
type: MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE
|
|
13
|
+
cn: number
|
|
14
|
+
added: string[]
|
|
15
|
+
removed: string[]
|
|
16
|
+
}
|
|
18
17
|
|
|
19
|
-
export interface IMySegmentsSyncTask extends ISyncTask<[segmentsData?: MySegmentsData, noCache?: boolean], boolean> { }
|
|
18
|
+
export interface IMySegmentsSyncTask extends ISyncTask<[segmentsData?: MySegmentsData, noCache?: boolean, till?: number], boolean> { }
|
|
20
19
|
|
|
21
20
|
export interface IPollingManager extends ITask {
|
|
22
21
|
syncAll(): Promise<any>
|
|
@@ -6,8 +6,10 @@ import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
|
|
|
6
6
|
import { ILogger } from '../../../logger/types';
|
|
7
7
|
import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
|
|
8
8
|
import { MySegmentsData } from '../types';
|
|
9
|
+
import { IMembershipsResponse } from '../../../dtos/types';
|
|
10
|
+
import { MEMBERSHIPS_LS_UPDATE } from '../../streaming/constants';
|
|
9
11
|
|
|
10
|
-
type IMySegmentsUpdater = (
|
|
12
|
+
type IMySegmentsUpdater = (segmentsData?: MySegmentsData, noCache?: boolean, till?: number) => Promise<boolean>
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* factory of MySegments updater, a task that:
|
|
@@ -36,23 +38,16 @@ export function mySegmentsUpdaterFactory(
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
// @TODO if allowing pluggable storages, handle async execution
|
|
39
|
-
function updateSegments(segmentsData: MySegmentsData) {
|
|
41
|
+
function updateSegments(segmentsData: IMembershipsResponse | MySegmentsData) {
|
|
40
42
|
|
|
41
43
|
let shouldNotifyUpdate;
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (cache!.isInSegment(name) !== add) {
|
|
47
|
-
shouldNotifyUpdate = true;
|
|
48
|
-
if (add) cache!.addToSegment(name);
|
|
49
|
-
else cache!.removeFromSegment(name);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
44
|
+
if ((segmentsData as MySegmentsData).type !== undefined) {
|
|
45
|
+
shouldNotifyUpdate = (segmentsData as MySegmentsData).type === MEMBERSHIPS_LS_UPDATE ?
|
|
46
|
+
largeSegments!.resetSegments(segmentsData as MySegmentsData) :
|
|
47
|
+
segments.resetSegments(segmentsData as MySegmentsData);
|
|
52
48
|
} else {
|
|
53
|
-
|
|
54
|
-
shouldNotifyUpdate =
|
|
55
|
-
shouldNotifyUpdate = largeSegments!.resetSegments((segmentsData.ls?.k || []).map((segment) => segment.n), segmentsData.ls?.cn) || shouldNotifyUpdate;
|
|
49
|
+
shouldNotifyUpdate = segments.resetSegments((segmentsData as IMembershipsResponse).ms || {});
|
|
50
|
+
shouldNotifyUpdate = largeSegments!.resetSegments((segmentsData as IMembershipsResponse).ls || {}) || shouldNotifyUpdate;
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
// Notify update if required
|
|
@@ -62,12 +57,12 @@ export function mySegmentsUpdaterFactory(
|
|
|
62
57
|
}
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
function _mySegmentsUpdater(retry: number, segmentsData?: MySegmentsData, noCache?: boolean): Promise<boolean> {
|
|
60
|
+
function _mySegmentsUpdater(retry: number, segmentsData?: MySegmentsData, noCache?: boolean, till?: number): Promise<boolean> {
|
|
66
61
|
const updaterPromise: Promise<boolean> = segmentsData ?
|
|
67
62
|
// If segmentsData is provided, there is no need to fetch mySegments
|
|
68
63
|
new Promise((res) => { updateSegments(segmentsData); res(true); }) :
|
|
69
64
|
// If not provided, fetch mySegments
|
|
70
|
-
mySegmentsFetcher(matchingKey, noCache, _promiseDecorator).then(segments => {
|
|
65
|
+
mySegmentsFetcher(matchingKey, noCache, till, _promiseDecorator).then(segments => {
|
|
71
66
|
// Only when we have downloaded segments completely, we should not keep retrying anymore
|
|
72
67
|
startingUp = false;
|
|
73
68
|
|
|
@@ -97,9 +92,10 @@ export function mySegmentsUpdaterFactory(
|
|
|
97
92
|
* (2) an object with a segment name and action (true: add, or false: delete) to update the storage,
|
|
98
93
|
* (3) or `undefined`, for which the updater will fetch mySegments in order to sync the storage.
|
|
99
94
|
* @param {boolean | undefined} noCache true to revalidate data to fetch
|
|
95
|
+
* @param {boolean | undefined} till query param to bypass CDN requests
|
|
100
96
|
*/
|
|
101
|
-
return function mySegmentsUpdater(segmentsData?: MySegmentsData, noCache?: boolean) {
|
|
102
|
-
return _mySegmentsUpdater(0, segmentsData, noCache);
|
|
97
|
+
return function mySegmentsUpdater(segmentsData?: MySegmentsData, noCache?: boolean, till?: number) {
|
|
98
|
+
return _mySegmentsUpdater(0, segmentsData, noCache, till);
|
|
103
99
|
};
|
|
104
100
|
|
|
105
101
|
}
|
|
@@ -14,7 +14,7 @@ export function authenticateFactory(fetchAuth: IFetchAuth): IAuthenticate {
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Run authentication requests to Auth Server, and returns a promise that resolves with the decoded JTW token.
|
|
17
|
-
* @param {string[] | undefined} userKeys set of user Keys to track
|
|
17
|
+
* @param {string[] | undefined} userKeys set of user Keys to track membership updates. It is undefined for server-side API.
|
|
18
18
|
*/
|
|
19
19
|
return function authenticate(userKeys?: string[]): Promise<IAuthToken> {
|
|
20
20
|
return fetchAuth(userKeys)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { errorParser, messageParser } from './NotificationParser';
|
|
2
2
|
import { notificationKeeperFactory } from './NotificationKeeper';
|
|
3
|
-
import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL,
|
|
3
|
+
import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE } from '../constants';
|
|
4
4
|
import { IPushEventEmitter } from '../types';
|
|
5
5
|
import { ISseEventHandler } from '../SSEClient/types';
|
|
6
|
-
import {
|
|
6
|
+
import { INotificationError, INotificationMessage } from './types';
|
|
7
7
|
import { ILogger } from '../../../logger/types';
|
|
8
8
|
import { STREAMING_PARSING_ERROR_FAILS, ERROR_STREAMING_SSE, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_NEW_MESSAGE } from '../../../logger/constants';
|
|
9
9
|
import { ABLY_ERROR, NON_REQUESTED, SSE_CONNECTION_ERROR } from '../../../utils/constants';
|
|
@@ -75,26 +75,24 @@ export function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventEmitter,
|
|
|
75
75
|
log.debug(STREAMING_NEW_MESSAGE, [data]);
|
|
76
76
|
|
|
77
77
|
// we only handle update events if streaming is up
|
|
78
|
-
|
|
79
|
-
const type = parsedData.type || parsedData.t;
|
|
80
|
-
if (!notificationKeeper.isStreamingUp() && [OCCUPANCY, CONTROL].indexOf(type) === -1) return;
|
|
78
|
+
if (!notificationKeeper.isStreamingUp() && [OCCUPANCY, CONTROL].indexOf(parsedData.type) === -1) return;
|
|
81
79
|
|
|
82
|
-
switch (type) {
|
|
80
|
+
switch (parsedData.type) {
|
|
83
81
|
/* update events */
|
|
84
82
|
case SPLIT_UPDATE:
|
|
85
83
|
case SEGMENT_UPDATE:
|
|
86
|
-
case
|
|
87
|
-
case
|
|
84
|
+
case MEMBERSHIPS_MS_UPDATE:
|
|
85
|
+
case MEMBERSHIPS_LS_UPDATE:
|
|
88
86
|
case SPLIT_KILL:
|
|
89
|
-
pushEmitter.emit(type, parsedData);
|
|
87
|
+
pushEmitter.emit(parsedData.type, parsedData);
|
|
90
88
|
break;
|
|
91
89
|
|
|
92
90
|
/* occupancy & control events, handled by NotificationManagerKeeper */
|
|
93
91
|
case OCCUPANCY:
|
|
94
|
-
notificationKeeper.handleOccupancyEvent(
|
|
92
|
+
notificationKeeper.handleOccupancyEvent(parsedData.metrics.publishers, channel, timestamp);
|
|
95
93
|
break;
|
|
96
94
|
case CONTROL:
|
|
97
|
-
notificationKeeper.handleControlEvent(
|
|
95
|
+
notificationKeeper.handleControlEvent(parsedData.controlType, channel, timestamp);
|
|
98
96
|
break;
|
|
99
97
|
|
|
100
98
|
default:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ControlType } from '../constants';
|
|
2
|
-
import { SEGMENT_UPDATE, SPLIT_UPDATE, SPLIT_KILL, CONTROL, OCCUPANCY,
|
|
2
|
+
import { SEGMENT_UPDATE, SPLIT_UPDATE, SPLIT_KILL, CONTROL, OCCUPANCY, MEMBERSHIPS_LS_UPDATE, MEMBERSHIPS_MS_UPDATE } from '../types';
|
|
3
3
|
|
|
4
4
|
export enum Compression {
|
|
5
5
|
None = 0,
|
|
@@ -19,8 +19,8 @@ export interface KeyList {
|
|
|
19
19
|
r?: string[], // decimal hash64 of user keys
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
interface
|
|
23
|
-
|
|
22
|
+
interface IMembershipUpdateData<T extends string> {
|
|
23
|
+
type: T,
|
|
24
24
|
cn: number,
|
|
25
25
|
n?: string[],
|
|
26
26
|
c?: Compression,
|
|
@@ -31,9 +31,9 @@ interface IMySegmentsUpdateData<T extends string> {
|
|
|
31
31
|
s?: number, // seed for hash function
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export interface
|
|
34
|
+
export interface IMembershipMSUpdateData extends IMembershipUpdateData<MEMBERSHIPS_MS_UPDATE> { }
|
|
35
35
|
|
|
36
|
-
export interface
|
|
36
|
+
export interface IMembershipLSUpdateData extends IMembershipUpdateData<MEMBERSHIPS_LS_UPDATE> { }
|
|
37
37
|
|
|
38
38
|
export interface ISegmentUpdateData {
|
|
39
39
|
type: SEGMENT_UPDATE,
|
|
@@ -68,6 +68,6 @@ export interface IOccupancyData {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
export type INotificationData =
|
|
71
|
+
export type INotificationData = IMembershipMSUpdateData | IMembershipLSUpdateData | ISegmentUpdateData | ISplitUpdateData | ISplitKillData | IControlData | IOccupancyData
|
|
72
72
|
export type INotificationMessage = { parsedData: INotificationData, channel: string, timestamp: number, data: string }
|
|
73
73
|
export type INotificationError = Event & { parsedData?: any, message?: string }
|