@splitsoftware/splitio-commons 1.16.1-rc.7 → 1.17.0-rc.0
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/CHANGES.txt +2 -1
- package/cjs/evaluator/matchers/index.js +1 -3
- package/cjs/evaluator/matchers/matcherTypes.js +0 -1
- package/cjs/evaluator/matchersTransform/index.js +1 -1
- package/cjs/logger/constants.js +4 -3
- package/cjs/logger/messages/info.js +2 -1
- package/cjs/readiness/readinessManager.js +10 -14
- package/cjs/readiness/sdkReadinessManager.js +6 -5
- package/cjs/sdkClient/sdkClientMethodCS.js +2 -2
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +2 -2
- package/cjs/sdkFactory/index.js +1 -1
- package/cjs/services/decorateHeaders.js +42 -0
- package/cjs/services/splitApi.js +0 -4
- package/cjs/services/splitHttpClient.js +5 -4
- package/cjs/storages/AbstractSplitsCacheAsync.js +2 -2
- package/cjs/storages/AbstractSplitsCacheSync.js +6 -5
- package/cjs/storages/KeyBuilder.js +0 -3
- package/cjs/storages/KeyBuilderCS.js +5 -17
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +4 -16
- package/cjs/storages/inLocalStorage/index.js +2 -6
- package/cjs/storages/inMemory/InMemoryStorageCS.js +0 -5
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +11 -20
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +10 -7
- package/cjs/storages/pluggable/inMemoryWrapper.js +1 -1
- package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +1 -5
- package/cjs/sync/polling/pollingManagerCS.js +33 -51
- package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +21 -20
- package/cjs/sync/streaming/SSEClient/index.js +0 -4
- package/cjs/sync/streaming/SSEHandler/index.js +0 -1
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +9 -23
- package/cjs/sync/streaming/constants.js +1 -2
- package/cjs/sync/streaming/parseUtils.js +8 -3
- package/cjs/sync/streaming/pushManager.js +68 -97
- package/cjs/sync/submitters/telemetrySubmitter.js +0 -4
- package/cjs/sync/syncManagerOnline.js +14 -24
- package/cjs/utils/constants/index.js +2 -4
- package/cjs/utils/settingsValidation/index.js +2 -7
- package/esm/evaluator/matchers/index.js +1 -3
- package/esm/evaluator/matchers/matcherTypes.js +0 -1
- package/esm/evaluator/matchersTransform/index.js +1 -1
- package/esm/logger/constants.js +1 -0
- package/esm/logger/messages/info.js +2 -1
- package/esm/readiness/readinessManager.js +10 -14
- package/esm/readiness/sdkReadinessManager.js +6 -5
- package/esm/sdkClient/sdkClientMethodCS.js +2 -2
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +2 -2
- package/esm/sdkFactory/index.js +1 -1
- package/esm/services/decorateHeaders.js +38 -0
- package/esm/services/splitApi.js +1 -5
- package/esm/services/splitHttpClient.js +5 -4
- package/esm/storages/AbstractSplitsCacheAsync.js +2 -2
- package/esm/storages/AbstractSplitsCacheSync.js +4 -3
- package/esm/storages/KeyBuilder.js +0 -3
- package/esm/storages/KeyBuilderCS.js +4 -15
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +5 -17
- package/esm/storages/inLocalStorage/index.js +3 -7
- package/esm/storages/inMemory/InMemoryStorageCS.js +0 -5
- package/esm/storages/inMemory/SplitsCacheInMemory.js +12 -21
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +10 -7
- package/esm/storages/pluggable/inMemoryWrapper.js +1 -1
- package/esm/sync/polling/fetchers/mySegmentsFetcher.js +1 -5
- package/esm/sync/polling/pollingManagerCS.js +34 -52
- package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +19 -18
- package/esm/sync/streaming/SSEClient/index.js +1 -5
- package/esm/sync/streaming/SSEHandler/index.js +1 -2
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +9 -23
- package/esm/sync/streaming/constants.js +0 -1
- package/esm/sync/streaming/parseUtils.js +8 -3
- package/esm/sync/streaming/pushManager.js +69 -97
- package/esm/sync/submitters/telemetrySubmitter.js +0 -4
- package/esm/sync/syncManagerOnline.js +15 -25
- package/esm/utils/constants/index.js +1 -3
- package/esm/utils/settingsValidation/index.js +2 -7
- package/package.json +1 -1
- package/src/dtos/types.ts +7 -17
- package/src/evaluator/matchers/index.ts +0 -2
- package/src/evaluator/matchers/matcherTypes.ts +0 -1
- package/src/evaluator/matchersTransform/index.ts +1 -1
- package/src/logger/constants.ts +1 -0
- package/src/logger/messages/info.ts +2 -1
- package/src/readiness/readinessManager.ts +9 -13
- package/src/readiness/sdkReadinessManager.ts +7 -7
- package/src/readiness/types.ts +2 -3
- package/src/sdkClient/sdkClientMethodCS.ts +2 -2
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +2 -2
- package/src/sdkFactory/index.ts +1 -1
- package/src/services/decorateHeaders.ts +40 -0
- package/src/services/splitApi.ts +1 -6
- package/src/services/splitHttpClient.ts +5 -4
- package/src/services/types.ts +0 -1
- package/src/storages/AbstractSplitsCacheAsync.ts +2 -2
- package/src/storages/AbstractSplitsCacheSync.ts +5 -4
- package/src/storages/KeyBuilder.ts +0 -3
- package/src/storages/KeyBuilderCS.ts +5 -25
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +3 -3
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +5 -20
- package/src/storages/inLocalStorage/index.ts +4 -8
- package/src/storages/inMemory/InMemoryStorageCS.ts +0 -5
- package/src/storages/inMemory/SplitsCacheInMemory.ts +10 -15
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +11 -7
- package/src/storages/pluggable/inMemoryWrapper.ts +1 -1
- package/src/storages/types.ts +5 -7
- package/src/sync/polling/fetchers/mySegmentsFetcher.ts +2 -6
- package/src/sync/polling/pollingManagerCS.ts +29 -61
- package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +10 -10
- package/src/sync/polling/types.ts +3 -4
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +20 -17
- package/src/sync/streaming/SSEClient/index.ts +7 -10
- package/src/sync/streaming/SSEHandler/index.ts +1 -2
- package/src/sync/streaming/SSEHandler/types.ts +2 -14
- package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +9 -25
- package/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +1 -1
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +1 -1
- package/src/sync/streaming/UpdateWorkers/types.ts +2 -2
- package/src/sync/streaming/constants.ts +0 -1
- package/src/sync/streaming/parseUtils.ts +10 -6
- package/src/sync/streaming/pushManager.ts +67 -101
- package/src/sync/streaming/types.ts +3 -5
- package/src/sync/submitters/telemetrySubmitter.ts +0 -4
- package/src/sync/submitters/types.ts +4 -11
- package/src/sync/syncManagerOnline.ts +11 -19
- package/src/types.ts +9 -28
- package/src/utils/constants/index.ts +1 -3
- package/src/utils/settingsValidation/index.ts +3 -8
- package/src/utils/settingsValidation/types.ts +1 -1
- package/types/dtos/types.d.ts +6 -14
- package/types/logger/constants.d.ts +1 -0
- package/types/readiness/readinessManager.d.ts +2 -2
- package/types/readiness/sdkReadinessManager.d.ts +3 -2
- package/types/readiness/types.d.ts +2 -3
- package/types/services/decorateHeaders.d.ts +2 -0
- package/types/services/types.d.ts +0 -1
- package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
- package/types/storages/AbstractSplitsCacheSync.d.ts +3 -3
- package/types/storages/KeyBuilder.d.ts +0 -1
- package/types/storages/KeyBuilderCS.d.ts +2 -7
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +2 -2
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +2 -3
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +6 -4
- package/types/storages/pluggable/inMemoryWrapper.d.ts +1 -1
- package/types/storages/types.d.ts +3 -4
- package/types/sync/polling/syncTasks/mySegmentsSyncTask.d.ts +3 -2
- package/types/sync/polling/types.d.ts +3 -10
- package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +4 -4
- package/types/sync/streaming/SSEClient/index.d.ts +0 -1
- package/types/sync/streaming/SSEHandler/types.d.ts +2 -13
- package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +2 -3
- package/types/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.d.ts +1 -2
- package/types/sync/streaming/UpdateWorkers/SplitsUpdateWorker.d.ts +2 -3
- package/types/sync/streaming/UpdateWorkers/types.d.ts +2 -2
- package/types/sync/streaming/constants.d.ts +0 -1
- package/types/sync/streaming/parseUtils.d.ts +4 -2
- package/types/sync/streaming/pushManager.d.ts +0 -2
- package/types/sync/streaming/types.d.ts +4 -5
- package/types/sync/submitters/types.d.ts +3 -10
- package/types/types.d.ts +11 -26
- package/types/utils/constants/index.d.ts +1 -3
- package/types/utils/settingsValidation/index.d.ts +0 -2
- package/types/utils/settingsValidation/types.d.ts +1 -1
- package/cjs/evaluator/matchers/large_segment.js +0 -16
- package/esm/evaluator/matchers/large_segment.js +0 -12
- package/src/evaluator/matchers/large_segment.ts +0 -18
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies, TelemetryUsageStatsPayload, UpdatesFromSSEEnum
|
|
1
|
+
import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../../sync/submitters/types';
|
|
2
2
|
import { DEDUPED, DROPPED, LOCALHOST_MODE, QUEUED } from '../../utils/constants';
|
|
3
3
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
4
4
|
import { ISegmentsCacheSync, ISplitsCacheSync, IStorageFactoryParams, ITelemetryCacheSync } from '../types';
|
|
@@ -25,7 +25,7 @@ export function shouldRecordTelemetry({ settings }: IStorageFactoryParams) {
|
|
|
25
25
|
|
|
26
26
|
export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
27
27
|
|
|
28
|
-
constructor(private splits?: ISplitsCacheSync, private segments?: ISegmentsCacheSync
|
|
28
|
+
constructor(private splits?: ISplitsCacheSync, private segments?: ISegmentsCacheSync) { }
|
|
29
29
|
|
|
30
30
|
// isEmpty flag
|
|
31
31
|
private e = true;
|
|
@@ -51,8 +51,6 @@ 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
|
-
lseC: this.largeSegments && this.largeSegments.getRegisteredSegments().length,
|
|
55
|
-
lskC: this.largeSegments && this.largeSegments.getKeysCount(),
|
|
56
54
|
sL: this.getSessionLength(),
|
|
57
55
|
eQ: this.getEventStats(QUEUED),
|
|
58
56
|
eD: this.getEventStats(DROPPED),
|
|
@@ -247,16 +245,22 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
247
245
|
this.e = false;
|
|
248
246
|
}
|
|
249
247
|
|
|
250
|
-
private updatesFromSSE
|
|
248
|
+
private updatesFromSSE = {
|
|
249
|
+
sp: 0,
|
|
250
|
+
ms: 0
|
|
251
|
+
};
|
|
251
252
|
|
|
252
253
|
popUpdatesFromSSE() {
|
|
253
254
|
const result = this.updatesFromSSE;
|
|
254
|
-
this.updatesFromSSE = {
|
|
255
|
+
this.updatesFromSSE = {
|
|
256
|
+
sp: 0,
|
|
257
|
+
ms: 0,
|
|
258
|
+
};
|
|
255
259
|
return result;
|
|
256
260
|
}
|
|
257
261
|
|
|
258
262
|
recordUpdatesFromSSE(type: UpdatesFromSSEEnum) {
|
|
259
|
-
this.updatesFromSSE[type]
|
|
263
|
+
this.updatesFromSSE[type]++;
|
|
260
264
|
this.e = false;
|
|
261
265
|
}
|
|
262
266
|
|
|
@@ -7,7 +7,7 @@ import { ISet, setToArray, _Set } from '../../utils/lang/sets';
|
|
|
7
7
|
* The `_cache` property is the object were items are stored.
|
|
8
8
|
* Intended for testing purposes.
|
|
9
9
|
*
|
|
10
|
-
* @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves
|
|
10
|
+
* @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves inmediatelly.
|
|
11
11
|
*/
|
|
12
12
|
export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWrapper & { _cache: Record<string, string | string[] | ISet<string>>, _setConnDelay(connDelay: number): void } {
|
|
13
13
|
|
package/src/storages/types.ts
CHANGED
|
@@ -204,8 +204,8 @@ export interface ISplitsCacheBase {
|
|
|
204
204
|
getSplitNames(): MaybeThenable<string[]>,
|
|
205
205
|
// should never reject or throw an exception. Instead return true by default, asssuming the TT might exist.
|
|
206
206
|
trafficTypeExists(trafficType: string): MaybeThenable<boolean>,
|
|
207
|
-
// only for Client-Side
|
|
208
|
-
|
|
207
|
+
// only for Client-Side
|
|
208
|
+
usesSegments(): MaybeThenable<boolean>,
|
|
209
209
|
clear(): MaybeThenable<boolean | void>,
|
|
210
210
|
// should never reject or throw an exception. Instead return false by default, to avoid emitting SDK_READY_FROM_CACHE.
|
|
211
211
|
checkCache(): MaybeThenable<boolean>,
|
|
@@ -223,7 +223,7 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
|
|
|
223
223
|
getAll(): ISplit[],
|
|
224
224
|
getSplitNames(): string[],
|
|
225
225
|
trafficTypeExists(trafficType: string): boolean,
|
|
226
|
-
|
|
226
|
+
usesSegments(): boolean,
|
|
227
227
|
clear(): void,
|
|
228
228
|
checkCache(): boolean,
|
|
229
229
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean,
|
|
@@ -240,7 +240,7 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
|
|
|
240
240
|
getAll(): Promise<ISplit[]>,
|
|
241
241
|
getSplitNames(): Promise<string[]>,
|
|
242
242
|
trafficTypeExists(trafficType: string): Promise<boolean>,
|
|
243
|
-
|
|
243
|
+
usesSegments(): Promise<boolean>,
|
|
244
244
|
clear(): Promise<boolean | void>,
|
|
245
245
|
checkCache(): Promise<boolean>,
|
|
246
246
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>,
|
|
@@ -477,9 +477,7 @@ export interface IStorageSync extends IStorageBase<
|
|
|
477
477
|
IEventsCacheSync,
|
|
478
478
|
ITelemetryCacheSync,
|
|
479
479
|
IUniqueKeysCacheSync
|
|
480
|
-
> {
|
|
481
|
-
largeSegments?: ISegmentsCacheSync,
|
|
482
|
-
}
|
|
480
|
+
> { }
|
|
483
481
|
|
|
484
482
|
export interface IStorageAsync extends IStorageBase<
|
|
485
483
|
ISplitsCacheAsync,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IFetchMySegments, IResponse } from '../../../services/types';
|
|
2
|
-
import {
|
|
2
|
+
import { IMySegmentsResponseItem } from '../../../dtos/types';
|
|
3
3
|
import { IMySegmentsFetcher } from './types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -21,11 +21,7 @@ export function mySegmentsFetcherFactory(fetchMySegments: IFetchMySegments): IMy
|
|
|
21
21
|
// Extract segment names
|
|
22
22
|
return mySegmentsPromise
|
|
23
23
|
.then(resp => resp.json())
|
|
24
|
-
.then(
|
|
25
|
-
return (json as IMySegmentsResponse).mySegments ?
|
|
26
|
-
(json as IMySegmentsResponse).mySegments.map((segment) => segment.name) :
|
|
27
|
-
(json as IMyLargeSegmentsResponse).myLargeSegments;
|
|
28
|
-
});
|
|
24
|
+
.then(json => json.mySegments.map((segment: IMySegmentsResponseItem) => segment.name));
|
|
29
25
|
};
|
|
30
26
|
|
|
31
27
|
}
|
|
@@ -6,9 +6,8 @@ import { mySegmentsSyncTaskFactory } from './syncTasks/mySegmentsSyncTask';
|
|
|
6
6
|
import { splitsSyncTaskFactory } from './syncTasks/splitsSyncTask';
|
|
7
7
|
import { getMatching } from '../../utils/key';
|
|
8
8
|
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants';
|
|
9
|
-
import { POLLING_START, POLLING_STOP } from '../../logger/constants';
|
|
9
|
+
import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants';
|
|
10
10
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
11
|
-
import { IN_LARGE_SEGMENT, IN_SEGMENT } from '../../utils/constants';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* Expose start / stop mechanism for polling data from services.
|
|
@@ -23,92 +22,62 @@ export function pollingManagerCSFactory(
|
|
|
23
22
|
|
|
24
23
|
const splitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings, true);
|
|
25
24
|
|
|
26
|
-
// Map of matching keys to their corresponding MySegmentsSyncTask
|
|
27
|
-
const mySegmentsSyncTasks: Record<string,
|
|
25
|
+
// Map of matching keys to their corresponding MySegmentsSyncTask.
|
|
26
|
+
const mySegmentsSyncTasks: Record<string, IMySegmentsSyncTask> = {};
|
|
28
27
|
|
|
29
28
|
const matchingKey = getMatching(settings.core.key);
|
|
30
|
-
const
|
|
29
|
+
const mySegmentsSyncTask = add(matchingKey, readiness, storage);
|
|
31
30
|
|
|
32
31
|
function startMySegmentsSyncTasks() {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
forOwn(mySegmentsSyncTasks, ({ msSyncTask, mlsSyncTask }) => {
|
|
37
|
-
if (splitsHaveSegments) msSyncTask.start();
|
|
38
|
-
else msSyncTask.stop(); // smart pausing
|
|
39
|
-
|
|
40
|
-
if (mlsSyncTask) {
|
|
41
|
-
if (splitsHaveLargeSegments) mlsSyncTask.start();
|
|
42
|
-
else mlsSyncTask.stop(); // smart pausing
|
|
43
|
-
}
|
|
32
|
+
forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
33
|
+
mySegmentsSyncTask.start();
|
|
44
34
|
});
|
|
45
35
|
}
|
|
46
36
|
|
|
47
37
|
function stopMySegmentsSyncTasks() {
|
|
48
|
-
forOwn(mySegmentsSyncTasks, (
|
|
49
|
-
|
|
50
|
-
mlsSyncTask && mlsSyncTask.stop();
|
|
38
|
+
forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
39
|
+
if (mySegmentsSyncTask.isRunning()) mySegmentsSyncTask.stop();
|
|
51
40
|
});
|
|
52
41
|
}
|
|
53
42
|
|
|
43
|
+
// smart pausing
|
|
54
44
|
readiness.splits.on(SDK_SPLITS_ARRIVED, () => {
|
|
55
|
-
if (splitsSyncTask.isRunning())
|
|
45
|
+
if (!splitsSyncTask.isRunning()) return; // noop if not doing polling
|
|
46
|
+
const splitsHaveSegments = storage.splits.usesSegments();
|
|
47
|
+
if (splitsHaveSegments !== mySegmentsSyncTask.isRunning()) {
|
|
48
|
+
log.info(POLLING_SMART_PAUSING, [splitsHaveSegments ? 'ON' : 'OFF']);
|
|
49
|
+
if (splitsHaveSegments) {
|
|
50
|
+
startMySegmentsSyncTasks();
|
|
51
|
+
} else {
|
|
52
|
+
stopMySegmentsSyncTasks();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
56
55
|
});
|
|
57
56
|
|
|
58
57
|
function add(matchingKey: string, readiness: IReadinessManager, storage: IStorageSync) {
|
|
59
|
-
const
|
|
60
|
-
splitApi.fetchMySegments,
|
|
61
|
-
storage.segments,
|
|
62
|
-
() => { if (storage.splits.usesMatcher(IN_SEGMENT)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED); },
|
|
63
|
-
settings,
|
|
64
|
-
matchingKey,
|
|
65
|
-
settings.scheduler.segmentsRefreshRate,
|
|
66
|
-
'mySegmentsUpdater'
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
let mlsSyncTask;
|
|
70
|
-
if (settings.sync.largeSegmentsEnabled) {
|
|
71
|
-
mlsSyncTask = mySegmentsSyncTaskFactory(
|
|
72
|
-
splitApi.fetchMyLargeSegments,
|
|
73
|
-
storage.largeSegments!,
|
|
74
|
-
() => { if (readiness.largeSegments && storage.splits.usesMatcher(IN_LARGE_SEGMENT)) readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED); },
|
|
75
|
-
settings,
|
|
76
|
-
matchingKey,
|
|
77
|
-
settings.scheduler.largeSegmentsRefreshRate,
|
|
78
|
-
'myLargeSegmentsUpdater'
|
|
79
|
-
);
|
|
80
|
-
}
|
|
58
|
+
const mySegmentsSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMySegments, storage, readiness, settings, matchingKey);
|
|
81
59
|
|
|
82
60
|
// smart ready
|
|
83
61
|
function smartReady() {
|
|
84
|
-
if (!readiness.isReady())
|
|
85
|
-
if (readiness.largeSegments && !storage.splits.usesMatcher(IN_LARGE_SEGMENT)) readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED);
|
|
86
|
-
if (!storage.splits.usesMatcher(IN_SEGMENT)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
87
|
-
}
|
|
62
|
+
if (!readiness.isReady() && !storage.splits.usesSegments()) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
88
63
|
}
|
|
64
|
+
if (!storage.splits.usesSegments()) setTimeout(smartReady, 0);
|
|
65
|
+
else readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
|
|
89
66
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
mySegmentsSyncTasks[matchingKey] = { msSyncTask: msSyncTask, mlsSyncTask: mlsSyncTask };
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
msSyncTask,
|
|
97
|
-
mlsSyncTask
|
|
98
|
-
};
|
|
67
|
+
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
68
|
+
return mySegmentsSyncTask;
|
|
99
69
|
}
|
|
100
70
|
|
|
101
71
|
return {
|
|
102
72
|
splitsSyncTask,
|
|
103
|
-
segmentsSyncTask:
|
|
104
|
-
largeSegmentsSyncTask: mlsSyncTask,
|
|
73
|
+
segmentsSyncTask: mySegmentsSyncTask,
|
|
105
74
|
|
|
106
75
|
// Start periodic fetching (polling)
|
|
107
76
|
start() {
|
|
108
77
|
log.info(POLLING_START);
|
|
109
78
|
|
|
110
79
|
splitsSyncTask.start();
|
|
111
|
-
startMySegmentsSyncTasks();
|
|
80
|
+
if (storage.splits.usesSegments()) startMySegmentsSyncTasks();
|
|
112
81
|
},
|
|
113
82
|
|
|
114
83
|
// Stop periodic fetching (polling)
|
|
@@ -125,9 +94,8 @@ export function pollingManagerCSFactory(
|
|
|
125
94
|
// fetch splits and segments
|
|
126
95
|
syncAll() {
|
|
127
96
|
const promises = [splitsSyncTask.execute()];
|
|
128
|
-
forOwn(mySegmentsSyncTasks, function (
|
|
129
|
-
promises.push(
|
|
130
|
-
mlsSyncTask && promises.push(mlsSyncTask.execute());
|
|
97
|
+
forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
98
|
+
promises.push(mySegmentsSyncTask.execute());
|
|
131
99
|
});
|
|
132
100
|
return Promise.all(promises);
|
|
133
101
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IStorageSync } from '../../../storages/types';
|
|
2
|
+
import { IReadinessManager } from '../../../readiness/types';
|
|
2
3
|
import { syncTaskFactory } from '../../syncTask';
|
|
3
4
|
import { IMySegmentsSyncTask } from '../types';
|
|
4
5
|
import { IFetchMySegments } from '../../../services/types';
|
|
@@ -11,25 +12,24 @@ import { mySegmentsUpdaterFactory } from '../updaters/mySegmentsUpdater';
|
|
|
11
12
|
*/
|
|
12
13
|
export function mySegmentsSyncTaskFactory(
|
|
13
14
|
fetchMySegments: IFetchMySegments,
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
storage: IStorageSync,
|
|
16
|
+
readiness: IReadinessManager,
|
|
16
17
|
settings: ISettings,
|
|
17
|
-
matchingKey: string
|
|
18
|
-
segmentsRefreshRate: number,
|
|
19
|
-
NAME: string
|
|
18
|
+
matchingKey: string
|
|
20
19
|
): IMySegmentsSyncTask {
|
|
21
20
|
return syncTaskFactory(
|
|
22
21
|
settings.log,
|
|
23
22
|
mySegmentsUpdaterFactory(
|
|
24
23
|
settings.log,
|
|
25
24
|
mySegmentsFetcherFactory(fetchMySegments),
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
storage.splits,
|
|
26
|
+
storage.segments,
|
|
27
|
+
readiness.segments,
|
|
28
28
|
settings.startup.requestTimeoutBeforeReady,
|
|
29
29
|
settings.startup.retriesOnFailureBeforeReady,
|
|
30
30
|
matchingKey
|
|
31
31
|
),
|
|
32
|
-
segmentsRefreshRate,
|
|
33
|
-
|
|
32
|
+
settings.scheduler.segmentsRefreshRate,
|
|
33
|
+
'mySegmentsUpdater',
|
|
34
34
|
);
|
|
35
35
|
}
|
|
@@ -12,7 +12,7 @@ export type MySegmentsData = string[] | {
|
|
|
12
12
|
name: string,
|
|
13
13
|
/* action: `true` for add, and `false` for delete */
|
|
14
14
|
add: boolean
|
|
15
|
-
}
|
|
15
|
+
}
|
|
16
16
|
|
|
17
17
|
export interface IMySegmentsSyncTask extends ISyncTask<[segmentsData?: MySegmentsData, noCache?: boolean], boolean> { }
|
|
18
18
|
|
|
@@ -20,14 +20,13 @@ export interface IPollingManager extends ITask {
|
|
|
20
20
|
syncAll(): Promise<any>
|
|
21
21
|
splitsSyncTask: ISplitsSyncTask
|
|
22
22
|
segmentsSyncTask: ISyncTask
|
|
23
|
-
largeSegmentsSyncTask?: ISyncTask
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
/**
|
|
27
26
|
* PollingManager for client-side with support for multiple clients
|
|
28
27
|
*/
|
|
29
28
|
export interface IPollingManagerCS extends IPollingManager {
|
|
30
|
-
add(matchingKey: string, readiness: IReadinessManager, storage: IStorageSync):
|
|
29
|
+
add(matchingKey: string, readiness: IReadinessManager, storage: IStorageSync): IMySegmentsSyncTask
|
|
31
30
|
remove(matchingKey: string): void;
|
|
32
|
-
get(matchingKey: string):
|
|
31
|
+
get(matchingKey: string): IMySegmentsSyncTask | undefined
|
|
33
32
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { IMySegmentsFetcher } from '../fetchers/types';
|
|
2
|
-
import { ISegmentsCacheSync } from '../../../storages/types';
|
|
2
|
+
import { ISegmentsCacheSync, ISplitsCacheSync } from '../../../storages/types';
|
|
3
|
+
import { ISegmentsEventEmitter } from '../../../readiness/types';
|
|
3
4
|
import { timeout } from '../../../utils/promise/timeout';
|
|
5
|
+
import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
|
|
4
6
|
import { ILogger } from '../../../logger/types';
|
|
5
7
|
import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
|
|
6
8
|
import { MySegmentsData } from '../types';
|
|
7
|
-
import { isObject } from '../../../utils/lang';
|
|
8
9
|
|
|
9
|
-
type IMySegmentsUpdater = (segmentList?:
|
|
10
|
+
type IMySegmentsUpdater = (segmentList?: string[], noCache?: boolean) => Promise<boolean>
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* factory of MySegments updater, a task that:
|
|
@@ -17,8 +18,9 @@ type IMySegmentsUpdater = (segmentList?: MySegmentsData, noCache?: boolean) => P
|
|
|
17
18
|
export function mySegmentsUpdaterFactory(
|
|
18
19
|
log: ILogger,
|
|
19
20
|
mySegmentsFetcher: IMySegmentsFetcher,
|
|
21
|
+
splitsCache: ISplitsCacheSync,
|
|
20
22
|
mySegmentsCache: ISegmentsCacheSync,
|
|
21
|
-
|
|
23
|
+
segmentsEventEmitter: ISegmentsEventEmitter,
|
|
22
24
|
requestTimeoutBeforeReady: number,
|
|
23
25
|
retriesOnFailureBeforeReady: number,
|
|
24
26
|
matchingKey: string
|
|
@@ -37,24 +39,25 @@ export function mySegmentsUpdaterFactory(
|
|
|
37
39
|
function updateSegments(segmentsData: MySegmentsData) {
|
|
38
40
|
|
|
39
41
|
let shouldNotifyUpdate;
|
|
40
|
-
if (
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
if (mySegmentsCache.isInSegment(name) !== add) {
|
|
44
|
-
shouldNotifyUpdate = true;
|
|
45
|
-
if (add) mySegmentsCache.addToSegment(name);
|
|
46
|
-
else mySegmentsCache.removeFromSegment(name);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
42
|
+
if (Array.isArray(segmentsData)) {
|
|
43
|
+
// Update the list of segment names available
|
|
44
|
+
shouldNotifyUpdate = mySegmentsCache.resetSegments(segmentsData);
|
|
49
45
|
} else {
|
|
50
|
-
//
|
|
51
|
-
|
|
46
|
+
// Add/Delete the segment
|
|
47
|
+
const { name, add } = segmentsData;
|
|
48
|
+
if (mySegmentsCache.isInSegment(name) !== add) {
|
|
49
|
+
shouldNotifyUpdate = true;
|
|
50
|
+
if (add) mySegmentsCache.addToSegment(name);
|
|
51
|
+
else mySegmentsCache.removeFromSegment(name);
|
|
52
|
+
} else {
|
|
53
|
+
shouldNotifyUpdate = false;
|
|
54
|
+
}
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
// Notify update if required
|
|
55
|
-
if (shouldNotifyUpdate || readyOnAlreadyExistentState) {
|
|
58
|
+
if (splitsCache.usesSegments() && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
|
|
56
59
|
readyOnAlreadyExistentState = false;
|
|
57
|
-
|
|
60
|
+
segmentsEventEmitter.emit(SDK_SEGMENTS_ARRIVED);
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IPlatform } from '../../../sdkFactory/types';
|
|
2
2
|
import { IEventSourceConstructor } from '../../../services/types';
|
|
3
3
|
import { ISettings } from '../../../types';
|
|
4
|
-
import {
|
|
4
|
+
import { isString } from '../../../utils/lang';
|
|
5
5
|
import { objectAssign } from '../../../utils/lang/objectAssign';
|
|
6
6
|
import { IAuthTokenPushEnabled } from '../AuthClient/types';
|
|
7
7
|
import { ISSEClient, ISseEventHandler } from './types';
|
|
@@ -42,7 +42,6 @@ export class SSEClient implements ISSEClient {
|
|
|
42
42
|
useHeaders?: boolean;
|
|
43
43
|
headers: Record<string, string>;
|
|
44
44
|
options?: object;
|
|
45
|
-
lse?: boolean;
|
|
46
45
|
|
|
47
46
|
/**
|
|
48
47
|
* SSEClient constructor.
|
|
@@ -62,7 +61,6 @@ export class SSEClient implements ISSEClient {
|
|
|
62
61
|
this.useHeaders = useHeaders;
|
|
63
62
|
this.headers = buildSSEHeaders(settings);
|
|
64
63
|
this.options = getOptions && getOptions(settings);
|
|
65
|
-
this.lse = settings.sync.largeSegmentsEnabled;
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
setEventHandler(handler: ISseEventHandler) {
|
|
@@ -78,13 +76,12 @@ export class SSEClient implements ISSEClient {
|
|
|
78
76
|
open(authToken: IAuthTokenPushEnabled) {
|
|
79
77
|
this.close(); // it closes connection if previously opened
|
|
80
78
|
|
|
81
|
-
const channelsQueryParam = Object.keys(authToken.channels).map(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
79
|
+
const channelsQueryParam = Object.keys(authToken.channels).map(
|
|
80
|
+
function (channel) {
|
|
81
|
+
const params = CONTROL_CHANNEL_REGEX.test(channel) ? '[?occupancy=metrics.publishers]' : '';
|
|
82
|
+
return encodeURIComponent(params + channel);
|
|
83
|
+
}
|
|
84
|
+
).join(',');
|
|
88
85
|
const url = `${this.streamingUrl}?channels=${channelsQueryParam}&accessToken=${authToken.token}&v=${ABLY_API_VERSION}&heartbeats=true`; // same results using `&heartbeats=false`
|
|
89
86
|
|
|
90
87
|
this.connection = new this.eventSource!(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { errorParser, messageParser } from './NotificationParser';
|
|
2
2
|
import { notificationKeeperFactory } from './NotificationKeeper';
|
|
3
|
-
import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE
|
|
3
|
+
import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE } from '../constants';
|
|
4
4
|
import { IPushEventEmitter } from '../types';
|
|
5
5
|
import { ISseEventHandler } from '../SSEClient/types';
|
|
6
6
|
import { INotificationError, INotificationMessage } from './types';
|
|
@@ -83,7 +83,6 @@ export function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventEmitter,
|
|
|
83
83
|
case SPLIT_UPDATE:
|
|
84
84
|
case SEGMENT_UPDATE:
|
|
85
85
|
case MY_SEGMENTS_UPDATE_V2:
|
|
86
|
-
case MY_LARGE_SEGMENTS_UPDATE:
|
|
87
86
|
case SPLIT_KILL:
|
|
88
87
|
pushEmitter.emit(parsedData.type, parsedData);
|
|
89
88
|
break;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ControlType } from '../constants';
|
|
2
|
-
import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, SEGMENT_UPDATE, SPLIT_UPDATE, SPLIT_KILL, CONTROL, OCCUPANCY
|
|
2
|
+
import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, SEGMENT_UPDATE, SPLIT_UPDATE, SPLIT_KILL, CONTROL, OCCUPANCY } from '../types';
|
|
3
3
|
|
|
4
4
|
export interface IMySegmentsUpdateData {
|
|
5
5
|
type: MY_SEGMENTS_UPDATE,
|
|
@@ -35,18 +35,6 @@ export interface IMySegmentsUpdateV2Data {
|
|
|
35
35
|
u: UpdateStrategy,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
export interface IMyLargeSegmentsUpdateData {
|
|
39
|
-
type: MY_LARGE_SEGMENTS_UPDATE,
|
|
40
|
-
changeNumber: number,
|
|
41
|
-
largeSegments: string[],
|
|
42
|
-
c: Compression,
|
|
43
|
-
d: string,
|
|
44
|
-
u: UpdateStrategy,
|
|
45
|
-
i?: number, // time interval in millis
|
|
46
|
-
h?: number, // hash function. 0 for murmur3_32, 1 for murmur3_64
|
|
47
|
-
s?: number, // seed for hash function
|
|
48
|
-
}
|
|
49
|
-
|
|
50
38
|
export interface ISegmentUpdateData {
|
|
51
39
|
type: SEGMENT_UPDATE,
|
|
52
40
|
changeNumber: number,
|
|
@@ -80,6 +68,6 @@ export interface IOccupancyData {
|
|
|
80
68
|
}
|
|
81
69
|
}
|
|
82
70
|
|
|
83
|
-
export type INotificationData = IMySegmentsUpdateData | IMySegmentsUpdateV2Data |
|
|
71
|
+
export type INotificationData = IMySegmentsUpdateData | IMySegmentsUpdateV2Data | ISegmentUpdateData | ISplitUpdateData | ISplitKillData | IControlData | IOccupancyData
|
|
84
72
|
export type INotificationMessage = { parsedData: INotificationData, channel: string, timestamp: number, data: string }
|
|
85
73
|
export type INotificationError = Event & { parsedData?: any, message?: string }
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { IMySegmentsSyncTask, MySegmentsData } from '../../polling/types';
|
|
2
2
|
import { Backoff } from '../../../utils/Backoff';
|
|
3
3
|
import { IUpdateWorker } from './types';
|
|
4
|
+
import { MY_SEGMENT } from '../../../utils/constants';
|
|
4
5
|
import { ITelemetryTracker } from '../../../trackers/types';
|
|
5
|
-
import { UpdatesFromSSEEnum } from '../../submitters/types';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* MySegmentsUpdateWorker factory
|
|
9
9
|
*/
|
|
10
|
-
export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask, telemetryTracker: ITelemetryTracker
|
|
10
|
+
export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask, telemetryTracker: ITelemetryTracker): IUpdateWorker {
|
|
11
11
|
|
|
12
12
|
let maxChangeNumber = 0; // keeps the maximum changeNumber among queued events
|
|
13
13
|
let currentChangeNumber = -1;
|
|
14
14
|
let handleNewEvent = false;
|
|
15
15
|
let isHandlingEvent: boolean;
|
|
16
16
|
let _segmentsData: MySegmentsData | undefined; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
|
|
17
|
-
let _delay: undefined | number;
|
|
18
|
-
let _delayTimeoutID: any;
|
|
19
17
|
const backoff = new Backoff(__handleMySegmentsUpdateCall);
|
|
20
18
|
|
|
21
19
|
function __handleMySegmentsUpdateCall() {
|
|
@@ -25,19 +23,10 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask,
|
|
|
25
23
|
const currentMaxChangeNumber = maxChangeNumber;
|
|
26
24
|
|
|
27
25
|
// fetch mySegments revalidating data if cached
|
|
28
|
-
|
|
29
|
-
new Promise(res => {
|
|
30
|
-
_delayTimeoutID = setTimeout(() => {
|
|
31
|
-
_delay = undefined;
|
|
32
|
-
mySegmentsSyncTask.execute(_segmentsData, true).then(res);
|
|
33
|
-
}, _delay);
|
|
34
|
-
}) :
|
|
35
|
-
mySegmentsSyncTask.execute(_segmentsData, true);
|
|
36
|
-
|
|
37
|
-
syncTask.then((result) => {
|
|
26
|
+
mySegmentsSyncTask.execute(_segmentsData, true).then((result) => {
|
|
38
27
|
if (!isHandlingEvent) return; // halt if `stop` has been called
|
|
39
28
|
if (result !== false) {// Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
|
|
40
|
-
if (_segmentsData) telemetryTracker.trackUpdatesFromSSE(
|
|
29
|
+
if (_segmentsData) telemetryTracker.trackUpdatesFromSSE(MY_SEGMENT);
|
|
41
30
|
currentChangeNumber = Math.max(currentChangeNumber, currentMaxChangeNumber); // use `currentMaxChangeNumber`, in case that `maxChangeNumber` was updated during fetch.
|
|
42
31
|
}
|
|
43
32
|
if (handleNewEvent) {
|
|
@@ -53,28 +42,23 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask,
|
|
|
53
42
|
|
|
54
43
|
return {
|
|
55
44
|
/**
|
|
56
|
-
* Invoked by NotificationProcessor on
|
|
45
|
+
* Invoked by NotificationProcessor on MY_SEGMENTS_UPDATE event
|
|
57
46
|
*
|
|
58
|
-
* @param changeNumber change number of the notification
|
|
59
|
-
* @param
|
|
60
|
-
* @param delay optional time to wait for BoundedFetchRequest or BoundedFetchRequest updates
|
|
47
|
+
* @param {number} changeNumber change number of the MY_SEGMENTS_UPDATE notification
|
|
48
|
+
* @param {SegmentsData | undefined} segmentsData might be undefined
|
|
61
49
|
*/
|
|
62
|
-
put(changeNumber: number, segmentsData?: MySegmentsData
|
|
63
|
-
|
|
64
|
-
if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber || _delay) return;
|
|
50
|
+
put(changeNumber: number, segmentsData?: MySegmentsData) {
|
|
51
|
+
if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
|
|
65
52
|
|
|
66
53
|
maxChangeNumber = changeNumber;
|
|
67
54
|
handleNewEvent = true;
|
|
68
55
|
_segmentsData = segmentsData;
|
|
69
|
-
_delay = delay;
|
|
70
56
|
|
|
71
57
|
if (backoff.timeoutID || !isHandlingEvent) __handleMySegmentsUpdateCall();
|
|
72
58
|
backoff.reset();
|
|
73
59
|
},
|
|
74
60
|
|
|
75
61
|
stop() {
|
|
76
|
-
clearTimeout(_delayTimeoutID);
|
|
77
|
-
_delay = undefined;
|
|
78
62
|
isHandlingEvent = false;
|
|
79
63
|
backoff.reset();
|
|
80
64
|
}
|
|
@@ -9,7 +9,7 @@ import { IUpdateWorker } from './types';
|
|
|
9
9
|
/**
|
|
10
10
|
* SegmentsUpdateWorker factory
|
|
11
11
|
*/
|
|
12
|
-
export function SegmentsUpdateWorker(log: ILogger, segmentsSyncTask: ISegmentsSyncTask, segmentsCache: ISegmentsCacheSync): IUpdateWorker
|
|
12
|
+
export function SegmentsUpdateWorker(log: ILogger, segmentsSyncTask: ISegmentsSyncTask, segmentsCache: ISegmentsCacheSync): IUpdateWorker {
|
|
13
13
|
|
|
14
14
|
// Handles retries with CDN bypass per segment name
|
|
15
15
|
function SegmentUpdateWorker(segment: string) {
|
|
@@ -14,7 +14,7 @@ import { IUpdateWorker } from './types';
|
|
|
14
14
|
/**
|
|
15
15
|
* SplitsUpdateWorker factory
|
|
16
16
|
*/
|
|
17
|
-
export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker
|
|
17
|
+
export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker & { killSplit(event: ISplitKillData): void } {
|
|
18
18
|
|
|
19
19
|
let maxChangeNumber = 0;
|
|
20
20
|
let handleNewEvent = false;
|
|
@@ -30,7 +30,6 @@ export const MY_SEGMENTS_UPDATE_V2 = 'MY_SEGMENTS_UPDATE_V2';
|
|
|
30
30
|
export const SEGMENT_UPDATE = 'SEGMENT_UPDATE';
|
|
31
31
|
export const SPLIT_KILL = 'SPLIT_KILL';
|
|
32
32
|
export const SPLIT_UPDATE = 'SPLIT_UPDATE';
|
|
33
|
-
export const MY_LARGE_SEGMENTS_UPDATE = 'MY_LARGE_SEGMENTS_UPDATE';
|
|
34
33
|
|
|
35
34
|
// Control-type push notifications, handled by NotificationKeeper
|
|
36
35
|
export const CONTROL = 'CONTROL';
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { algorithms } from '../../utils/decompress';
|
|
2
2
|
import { decodeFromBase64 } from '../../utils/base64';
|
|
3
3
|
import { Compression, KeyList } from './SSEHandler/types';
|
|
4
|
-
import { ISplit } from '../../dtos/types';
|
|
5
4
|
|
|
6
5
|
const GZIP = 1;
|
|
7
6
|
const ZLIB = 2;
|
|
@@ -43,7 +42,7 @@ function decompress(data: string, compression: Compression) {
|
|
|
43
42
|
* @returns {{a?: string[], r?: string[] }}
|
|
44
43
|
* @throws if data string cannot be decoded, decompressed or parsed
|
|
45
44
|
*/
|
|
46
|
-
export function parseKeyList(data: string, compression: Compression, avoidPrecisionLoss = true): KeyList {
|
|
45
|
+
export function parseKeyList(data: string, compression: Compression, avoidPrecisionLoss: boolean = true): KeyList {
|
|
47
46
|
const binKeyList = decompress(data, compression);
|
|
48
47
|
let strKeyList = Uint8ArrayToString(binKeyList);
|
|
49
48
|
// replace numbers to strings, to avoid losing precision
|
|
@@ -81,9 +80,14 @@ export function isInBitmap(bitmap: Uint8Array, hash64hex: string) {
|
|
|
81
80
|
|
|
82
81
|
/**
|
|
83
82
|
* Parse feature flags notifications for instant feature flag updates
|
|
83
|
+
*
|
|
84
|
+
* @param {ISplitUpdateData} data
|
|
85
|
+
* @returns {KeyList}
|
|
84
86
|
*/
|
|
85
|
-
export function parseFFUpdatePayload(compression: Compression, data: string):
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
export function parseFFUpdatePayload(compression: Compression, data: string): KeyList | undefined {
|
|
88
|
+
const avoidPrecisionLoss = false;
|
|
89
|
+
if (compression > 0)
|
|
90
|
+
return parseKeyList(data, compression, avoidPrecisionLoss);
|
|
91
|
+
else
|
|
92
|
+
return JSON.parse(decodeFromBase64(data));
|
|
89
93
|
}
|