@splitsoftware/splitio-commons 1.17.1-rc.4 → 1.17.1-rc.5
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 +28 -29
- package/LICENSE +1 -1
- package/README.md +4 -3
- package/cjs/consent/sdkUserConsent.js +4 -2
- package/cjs/evaluator/matchers/index.js +1 -3
- package/cjs/evaluator/matchers/matcherTypes.js +0 -1
- package/cjs/evaluator/matchers/segment.js +0 -6
- package/cjs/evaluator/matchersTransform/index.js +1 -4
- package/cjs/evaluator/matchersTransform/segment.js +1 -3
- package/cjs/logger/constants.js +2 -2
- package/cjs/logger/messages/info.js +1 -1
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/readiness/readinessManager.js +8 -18
- package/cjs/readiness/sdkReadinessManager.js +6 -5
- package/cjs/sdkClient/sdkClient.js +5 -5
- package/cjs/sdkClient/sdkClientMethod.js +1 -3
- package/cjs/sdkClient/sdkClientMethodCS.js +15 -9
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +15 -9
- package/cjs/sdkFactory/index.js +10 -32
- package/cjs/services/decorateHeaders.js +6 -1
- package/cjs/services/splitApi.js +5 -5
- package/cjs/services/splitHttpClient.js +5 -2
- package/cjs/storages/AbstractSegmentsCacheSync.js +33 -0
- package/cjs/storages/AbstractSplitsCacheSync.js +1 -2
- package/cjs/storages/KeyBuilderCS.js +5 -23
- package/cjs/storages/dataLoader.js +1 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +56 -33
- package/cjs/storages/inLocalStorage/index.js +2 -6
- package/cjs/storages/inMemory/InMemoryStorageCS.js +1 -6
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +44 -13
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +28 -14
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +9 -8
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +10 -7
- package/cjs/storages/inRedis/SegmentsCacheInRedis.js +21 -15
- package/cjs/storages/inRedis/index.js +11 -5
- package/cjs/storages/pluggable/SegmentsCachePluggable.js +34 -13
- package/cjs/storages/pluggable/inMemoryWrapper.js +1 -1
- package/cjs/sync/offline/syncManagerOffline.js +11 -18
- package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +8 -5
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/cjs/sync/polling/pollingManagerCS.js +1 -1
- package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +21 -15
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +28 -12
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +1 -1
- package/cjs/sync/streaming/AuthClient/index.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +5 -3
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +48 -107
- package/cjs/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +3 -3
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/parseUtils.js +9 -14
- package/cjs/sync/streaming/pushManager.js +67 -69
- package/cjs/sync/syncManagerOnline.js +21 -20
- package/cjs/sync/syncTask.js +2 -2
- package/cjs/trackers/eventTracker.js +10 -12
- package/cjs/trackers/impressionsTracker.js +14 -16
- package/cjs/trackers/uniqueKeysTracker.js +3 -5
- package/cjs/utils/constants/index.js +4 -5
- package/cjs/utils/settingsValidation/index.js +1 -2
- package/esm/consent/sdkUserConsent.js +4 -2
- package/esm/evaluator/matchers/index.js +1 -3
- package/esm/evaluator/matchers/matcherTypes.js +0 -1
- package/esm/evaluator/matchers/segment.js +0 -6
- package/esm/evaluator/matchersTransform/index.js +1 -4
- package/esm/evaluator/matchersTransform/segment.js +1 -3
- package/esm/logger/constants.js +1 -1
- package/esm/logger/messages/info.js +1 -1
- package/esm/logger/messages/warn.js +1 -1
- package/esm/readiness/readinessManager.js +8 -18
- package/esm/readiness/sdkReadinessManager.js +6 -5
- package/esm/sdkClient/sdkClient.js +5 -5
- package/esm/sdkClient/sdkClientMethod.js +1 -3
- package/esm/sdkClient/sdkClientMethodCS.js +13 -7
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +13 -7
- package/esm/sdkFactory/index.js +10 -32
- package/esm/services/decorateHeaders.js +4 -0
- package/esm/services/splitApi.js +6 -6
- package/esm/services/splitHttpClient.js +6 -3
- package/esm/storages/AbstractSegmentsCacheSync.js +30 -0
- package/esm/storages/AbstractSplitsCacheSync.js +2 -3
- package/esm/storages/KeyBuilderCS.js +4 -21
- package/esm/storages/dataLoader.js +1 -1
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +56 -33
- package/esm/storages/inLocalStorage/index.js +3 -7
- package/esm/storages/inMemory/InMemoryStorageCS.js +1 -6
- package/esm/storages/inMemory/MySegmentsCacheInMemory.js +44 -13
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +28 -14
- package/esm/storages/inMemory/SplitsCacheInMemory.js +9 -8
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +10 -7
- package/esm/storages/inRedis/SegmentsCacheInRedis.js +21 -15
- package/esm/storages/inRedis/index.js +11 -5
- package/esm/storages/pluggable/SegmentsCachePluggable.js +34 -13
- package/esm/storages/pluggable/inMemoryWrapper.js +1 -1
- package/esm/sync/offline/syncManagerOffline.js +11 -18
- package/esm/sync/polling/fetchers/mySegmentsFetcher.js +8 -5
- package/esm/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/esm/sync/polling/pollingManagerCS.js +1 -1
- package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +21 -15
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +28 -12
- package/esm/sync/polling/updaters/splitChangesUpdater.js +1 -1
- package/esm/sync/streaming/AuthClient/index.js +1 -1
- package/esm/sync/streaming/SSEHandler/index.js +6 -4
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +49 -108
- package/esm/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +3 -3
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/parseUtils.js +8 -12
- package/esm/sync/streaming/pushManager.js +70 -72
- package/esm/sync/syncManagerOnline.js +21 -20
- package/esm/sync/syncTask.js +2 -2
- package/esm/trackers/eventTracker.js +10 -12
- package/esm/trackers/impressionsTracker.js +14 -16
- package/esm/trackers/uniqueKeysTracker.js +3 -5
- package/esm/utils/constants/index.js +2 -3
- package/esm/utils/settingsValidation/index.js +1 -2
- package/package.json +1 -1
- package/src/consent/sdkUserConsent.ts +3 -2
- package/src/dtos/types.ts +7 -21
- package/src/evaluator/matchers/index.ts +0 -2
- package/src/evaluator/matchers/matcherTypes.ts +0 -1
- package/src/evaluator/matchers/segment.ts +0 -7
- package/src/evaluator/matchersTransform/index.ts +1 -4
- package/src/evaluator/matchersTransform/segment.ts +3 -5
- package/src/logger/constants.ts +1 -1
- package/src/logger/messages/info.ts +1 -1
- package/src/logger/messages/warn.ts +1 -1
- package/src/readiness/readinessManager.ts +8 -19
- package/src/readiness/sdkReadinessManager.ts +7 -7
- package/src/readiness/types.ts +2 -5
- package/src/sdkClient/sdkClient.ts +5 -5
- package/src/sdkClient/sdkClientMethod.ts +1 -4
- package/src/sdkClient/sdkClientMethodCS.ts +15 -7
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +15 -7
- package/src/sdkFactory/index.ts +12 -35
- package/src/sdkFactory/types.ts +1 -4
- package/src/services/decorateHeaders.ts +5 -0
- package/src/services/splitApi.ts +7 -7
- package/src/services/splitHttpClient.ts +7 -4
- package/src/services/types.ts +2 -2
- package/src/storages/AbstractSegmentsCacheSync.ts +68 -0
- package/src/storages/AbstractSplitsCacheSync.ts +3 -4
- package/src/storages/KeyBuilderCS.ts +5 -34
- package/src/storages/dataLoader.ts +1 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +63 -33
- package/src/storages/inLocalStorage/index.ts +4 -8
- package/src/storages/inMemory/InMemoryStorageCS.ts +1 -6
- package/src/storages/inMemory/MySegmentsCacheInMemory.ts +47 -13
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +27 -13
- package/src/storages/inMemory/SplitsCacheInMemory.ts +9 -7
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +11 -7
- package/src/storages/inRedis/SegmentsCacheInRedis.ts +24 -15
- package/src/storages/inRedis/index.ts +12 -6
- package/src/storages/pluggable/SegmentsCachePluggable.ts +37 -13
- package/src/storages/pluggable/inMemoryWrapper.ts +1 -1
- package/src/storages/types.ts +17 -15
- package/src/sync/offline/syncManagerOffline.ts +13 -21
- package/src/sync/polling/fetchers/mySegmentsFetcher.ts +10 -8
- package/src/sync/polling/fetchers/segmentChangesFetcher.ts +1 -1
- package/src/sync/polling/fetchers/types.ts +2 -3
- package/src/sync/polling/pollingManagerCS.ts +4 -4
- package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +5 -4
- package/src/sync/polling/types.ts +6 -7
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +22 -19
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +29 -13
- package/src/sync/polling/updaters/splitChangesUpdater.ts +1 -1
- package/src/sync/streaming/AuthClient/index.ts +1 -1
- package/src/sync/streaming/SSEClient/index.ts +6 -4
- package/src/sync/streaming/SSEHandler/index.ts +8 -5
- package/src/sync/streaming/SSEHandler/types.ts +15 -15
- package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +49 -116
- package/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +4 -4
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +1 -1
- package/src/sync/streaming/UpdateWorkers/types.ts +2 -2
- package/src/sync/streaming/constants.ts +2 -2
- package/src/sync/streaming/parseUtils.ts +11 -19
- package/src/sync/streaming/pushManager.ts +72 -73
- package/src/sync/streaming/types.ts +10 -10
- package/src/sync/submitters/types.ts +5 -8
- package/src/sync/syncManagerOnline.ts +17 -17
- package/src/sync/syncTask.ts +2 -2
- package/src/sync/types.ts +1 -1
- package/src/trackers/eventTracker.ts +8 -11
- package/src/trackers/impressionsTracker.ts +10 -13
- package/src/trackers/types.ts +0 -1
- package/src/trackers/uniqueKeysTracker.ts +4 -6
- package/src/types.ts +1 -7
- package/src/utils/constants/index.ts +2 -3
- package/src/utils/settingsValidation/index.ts +2 -3
- package/src/utils/settingsValidation/types.ts +1 -1
- package/types/dtos/types.d.ts +7 -18
- package/types/evaluator/matchersTransform/segment.d.ts +2 -2
- package/types/logger/constants.d.ts +1 -1
- package/types/readiness/readinessManager.d.ts +2 -2
- package/types/readiness/sdkReadinessManager.d.ts +3 -2
- package/types/readiness/types.d.ts +2 -5
- package/types/sdkClient/sdkClientMethod.d.ts +1 -1
- package/types/sdkFactory/types.d.ts +1 -3
- package/types/services/decorateHeaders.d.ts +1 -0
- package/types/services/splitApi.d.ts +1 -1
- package/types/services/splitHttpClient.d.ts +1 -1
- package/types/services/types.d.ts +2 -2
- package/types/storages/AbstractSegmentsCacheSync.d.ts +11 -9
- package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
- package/types/storages/KeyBuilderCS.d.ts +2 -9
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +18 -8
- package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +13 -7
- package/types/storages/inMemory/SegmentsCacheInMemory.d.ts +8 -6
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +2 -1
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +6 -4
- package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +4 -7
- package/types/storages/inRedis/index.d.ts +1 -1
- package/types/storages/pluggable/SegmentsCachePluggable.d.ts +17 -5
- package/types/storages/pluggable/inMemoryWrapper.d.ts +1 -1
- package/types/storages/types.d.ts +15 -11
- package/types/sync/polling/fetchers/mySegmentsFetcher.d.ts +2 -2
- package/types/sync/polling/fetchers/types.d.ts +2 -2
- package/types/sync/polling/syncTasks/mySegmentsSyncTask.d.ts +2 -2
- package/types/sync/polling/types.d.ts +4 -7
- package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +3 -4
- package/types/sync/streaming/SSEHandler/types.d.ts +14 -16
- package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +2 -4
- 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 +2 -2
- package/types/sync/streaming/parseUtils.d.ts +5 -4
- package/types/sync/streaming/types.d.ts +8 -8
- package/types/sync/submitters/types.d.ts +4 -7
- package/types/sync/types.d.ts +1 -1
- package/types/trackers/eventTracker.d.ts +1 -1
- package/types/trackers/impressionsTracker.d.ts +1 -1
- package/types/trackers/types.d.ts +0 -1
- package/types/types.d.ts +1 -7
- package/types/utils/constants/index.d.ts +2 -3
- package/types/utils/settingsValidation/types.d.ts +1 -1
- package/cjs/evaluator/matchers/large_segment.js +0 -16
- package/cjs/sdkClient/identity.js +0 -7
- package/cjs/storages/AbstractMySegmentsCacheSync.js +0 -60
- package/esm/evaluator/matchers/large_segment.js +0 -12
- package/esm/sdkClient/identity.js +0 -3
- package/esm/storages/AbstractMySegmentsCacheSync.js +0 -57
- package/src/evaluator/matchers/large_segment.ts +0 -18
- package/src/sdkClient/identity.ts +0 -5
- package/src/storages/AbstractMySegmentsCacheSync.ts +0 -94
- package/types/evaluator/matchers/large_segment.d.ts +0 -5
- package/types/evaluator/matchers/sember_inlist.d.ts +0 -3
- package/types/evaluator/matchersTransform/set.d.ts +0 -5
- package/types/evaluator/matchersTransform/string.d.ts +0 -7
- package/types/sdkClient/identity.d.ts +0 -2
- package/types/storages/AbstractMySegmentsCacheSync.d.ts +0 -39
- package/types/storages/AbstractSplitsCache.d.ts +0 -46
- package/types/sync/streaming/mySegmentsV2utils.d.ts +0 -27
- package/types/sync/streaming/pushManagerCS_Spec1_3.d.ts +0 -9
- package/types/sync/streaming/pushManager_Spec1_3.d.ts +0 -9
- package/types/trackers/impressionObserver/utils.d.ts +0 -5
- package/types/utils/inputValidation/sdkKey.d.ts +0 -7
- package/types/utils/inputValidation/splitExistance.d.ts +0 -7
- package/types/utils/inputValidation/trafficTypeExistance.d.ts +0 -9
- package/types/utils/redis/RedisMock.d.ts +0 -4
- package/types/utils/settingsValidation/logger/globalLogLevel.d.ts +0 -8
- /package/types/utils/{semVer.d.ts → Semver.d.ts} +0 -0
|
@@ -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,
|
|
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';
|
|
@@ -74,18 +74,21 @@ export function SSEHandlerFactory(log: ILogger, pushEmitter: IPushEventEmitter,
|
|
|
74
74
|
const { parsedData, data, channel, timestamp } = messageWithParsedData;
|
|
75
75
|
log.debug(STREAMING_NEW_MESSAGE, [data]);
|
|
76
76
|
|
|
77
|
-
// we only handle update events if streaming is up
|
|
78
|
-
if (!notificationKeeper.isStreamingUp() && [OCCUPANCY, CONTROL].indexOf(parsedData.type) === -1)
|
|
77
|
+
// we only handle update events if streaming is up.
|
|
78
|
+
if (!notificationKeeper.isStreamingUp() && [OCCUPANCY, CONTROL].indexOf(parsedData.type) === -1)
|
|
79
|
+
return;
|
|
79
80
|
|
|
80
81
|
switch (parsedData.type) {
|
|
81
82
|
/* update events */
|
|
82
83
|
case SPLIT_UPDATE:
|
|
83
84
|
case SEGMENT_UPDATE:
|
|
84
|
-
case
|
|
85
|
-
case MEMBERSHIPS_LS_UPDATE:
|
|
85
|
+
case MY_SEGMENTS_UPDATE_V2:
|
|
86
86
|
case SPLIT_KILL:
|
|
87
87
|
pushEmitter.emit(parsedData.type, parsedData);
|
|
88
88
|
break;
|
|
89
|
+
case MY_SEGMENTS_UPDATE:
|
|
90
|
+
pushEmitter.emit(parsedData.type, parsedData, channel);
|
|
91
|
+
break;
|
|
89
92
|
|
|
90
93
|
/* occupancy & control events, handled by NotificationManagerKeeper */
|
|
91
94
|
case OCCUPANCY:
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { ControlType } from '../constants';
|
|
2
|
-
import { 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
|
+
|
|
4
|
+
export interface IMySegmentsUpdateData {
|
|
5
|
+
type: MY_SEGMENTS_UPDATE,
|
|
6
|
+
changeNumber: number,
|
|
7
|
+
includesPayload: boolean,
|
|
8
|
+
segmentList?: string[]
|
|
9
|
+
}
|
|
3
10
|
|
|
4
11
|
export enum Compression {
|
|
5
12
|
None = 0,
|
|
@@ -19,22 +26,15 @@ export interface KeyList {
|
|
|
19
26
|
r?: string[], // decimal hash64 of user keys
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
interface
|
|
23
|
-
type:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
c
|
|
27
|
-
d
|
|
29
|
+
export interface IMySegmentsUpdateV2Data {
|
|
30
|
+
type: MY_SEGMENTS_UPDATE_V2,
|
|
31
|
+
changeNumber: number,
|
|
32
|
+
segmentName: string,
|
|
33
|
+
c: Compression,
|
|
34
|
+
d: string,
|
|
28
35
|
u: UpdateStrategy,
|
|
29
|
-
i?: number, // time interval in millis
|
|
30
|
-
h?: number, // hash function
|
|
31
|
-
s?: number, // seed for hash function
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
export interface IMembershipMSUpdateData extends IMembershipUpdateData<MEMBERSHIPS_MS_UPDATE> { }
|
|
35
|
-
|
|
36
|
-
export interface IMembershipLSUpdateData extends IMembershipUpdateData<MEMBERSHIPS_LS_UPDATE> { }
|
|
37
|
-
|
|
38
38
|
export interface ISegmentUpdateData {
|
|
39
39
|
type: SEGMENT_UPDATE,
|
|
40
40
|
changeNumber: number,
|
|
@@ -68,6 +68,6 @@ export interface IOccupancyData {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
export type INotificationData =
|
|
71
|
+
export type INotificationData = IMySegmentsUpdateData | IMySegmentsUpdateV2Data | 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 }
|
|
@@ -1,133 +1,66 @@
|
|
|
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 { MEMBERSHIPS } from '../../../utils/constants';
|
|
6
|
-
import { ISegmentsCacheSync, IStorageSync } from '../../../storages/types';
|
|
7
|
-
import { ILogger } from '../../../logger/types';
|
|
8
|
-
import { FETCH_BACKOFF_MAX_RETRIES } from './constants';
|
|
9
|
-
import { MEMBERSHIPS_LS_UPDATE, MEMBERSHIPS_MS_UPDATE } from '../constants';
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
8
|
* MySegmentsUpdateWorker factory
|
|
13
9
|
*/
|
|
14
|
-
export function MySegmentsUpdateWorker(
|
|
15
|
-
|
|
16
|
-
let
|
|
17
|
-
let
|
|
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
|
-
syncTask.then((result) => {
|
|
46
|
-
if (!isHandlingEvent) return; // halt if `stop` has been called
|
|
47
|
-
if (result !== false) { // Unlike `Splits|SegmentsUpdateWorker`, `mySegmentsCache.getChangeNumber` can be -1, since `/memberships` change number is optional
|
|
48
|
-
const storageChangeNumber = mySegmentsCache.getChangeNumber();
|
|
49
|
-
currentChangeNumber = storageChangeNumber > -1 ?
|
|
50
|
-
storageChangeNumber :
|
|
51
|
-
Math.max(currentChangeNumber, currentMaxChangeNumber); // use `currentMaxChangeNumber`, in case that `maxChangeNumber` was updated during fetch.
|
|
52
|
-
}
|
|
53
|
-
if (handleNewEvent) {
|
|
54
|
-
__handleMySegmentsUpdateCall();
|
|
55
|
-
} else {
|
|
56
|
-
if (_segmentsData) telemetryTracker.trackUpdatesFromSSE(MEMBERSHIPS);
|
|
57
|
-
|
|
58
|
-
const attempts = backoff.attempts + 1;
|
|
59
|
-
|
|
60
|
-
if (maxChangeNumber <= currentChangeNumber) {
|
|
61
|
-
log.debug(`Refresh completed${cdnBypass ? ' bypassing the CDN' : ''} in ${attempts} attempts.`);
|
|
62
|
-
isHandlingEvent = false;
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (attempts < FETCH_BACKOFF_MAX_RETRIES) {
|
|
67
|
-
backoff.scheduleCall();
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (cdnBypass) {
|
|
72
|
-
log.debug(`No changes fetched after ${attempts} attempts with CDN bypassed.`);
|
|
73
|
-
isHandlingEvent = false;
|
|
74
|
-
} else {
|
|
75
|
-
backoff.reset();
|
|
76
|
-
cdnBypass = true;
|
|
77
|
-
__handleMySegmentsUpdateCall();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
} else {
|
|
82
|
-
isHandlingEvent = false;
|
|
83
|
-
}
|
|
10
|
+
export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask, telemetryTracker: ITelemetryTracker): IUpdateWorker {
|
|
11
|
+
|
|
12
|
+
let maxChangeNumber = 0; // keeps the maximum changeNumber among queued events
|
|
13
|
+
let currentChangeNumber = -1;
|
|
14
|
+
let handleNewEvent = false;
|
|
15
|
+
let isHandlingEvent: boolean;
|
|
16
|
+
let _segmentsData: MySegmentsData | undefined; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
|
|
17
|
+
const backoff = new Backoff(__handleMySegmentsUpdateCall);
|
|
18
|
+
|
|
19
|
+
function __handleMySegmentsUpdateCall() {
|
|
20
|
+
isHandlingEvent = true;
|
|
21
|
+
if (maxChangeNumber > currentChangeNumber) {
|
|
22
|
+
handleNewEvent = false;
|
|
23
|
+
const currentMaxChangeNumber = maxChangeNumber;
|
|
24
|
+
|
|
25
|
+
// fetch mySegments revalidating data if cached
|
|
26
|
+
mySegmentsSyncTask.execute(_segmentsData, true).then((result) => {
|
|
27
|
+
if (!isHandlingEvent) return; // halt if `stop` has been called
|
|
28
|
+
if (result !== false) {// Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
|
|
29
|
+
if (_segmentsData) telemetryTracker.trackUpdatesFromSSE(MY_SEGMENT);
|
|
30
|
+
currentChangeNumber = Math.max(currentChangeNumber, currentMaxChangeNumber); // use `currentMaxChangeNumber`, in case that `maxChangeNumber` was updated during fetch.
|
|
31
|
+
}
|
|
32
|
+
if (handleNewEvent) {
|
|
33
|
+
__handleMySegmentsUpdateCall();
|
|
34
|
+
} else {
|
|
35
|
+
backoff.scheduleCall();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
isHandlingEvent = false;
|
|
84
40
|
}
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
/**
|
|
88
|
-
* Invoked by NotificationProcessor on MY_(LARGE)_SEGMENTS_UPDATE notifications
|
|
89
|
-
*
|
|
90
|
-
* @param changeNumber change number of the notification
|
|
91
|
-
* @param segmentsData data for KeyList or SegmentRemoval instant updates
|
|
92
|
-
* @param delay optional time to wait for BoundedFetchRequest or BoundedFetchRequest updates
|
|
93
|
-
*/
|
|
94
|
-
put(mySegmentsData: Pick<MySegmentsData, 'type' | 'cn'>, payload?: Pick<MySegmentsData, 'added' | 'removed'>, delay?: number) {
|
|
95
|
-
const { type, cn } = mySegmentsData;
|
|
96
|
-
// Discard event if it is outdated or there is a pending fetch request (_delay is set), but update target change number
|
|
97
|
-
if (cn <= Math.max(currentChangeNumber, mySegmentsCache.getChangeNumber()) || cn <= maxChangeNumber) return;
|
|
98
|
-
maxChangeNumber = cn;
|
|
99
|
-
if (_delay) return;
|
|
100
|
-
|
|
101
|
-
handleNewEvent = true;
|
|
102
|
-
cdnBypass = false;
|
|
103
|
-
_segmentsData = payload && { type, cn, added: payload.added, removed: payload.removed };
|
|
104
|
-
_delay = delay;
|
|
105
|
-
|
|
106
|
-
if (backoff.timeoutID || !isHandlingEvent) __handleMySegmentsUpdateCall();
|
|
107
|
-
backoff.reset();
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
stop() {
|
|
111
|
-
clearTimeout(_delayTimeoutID);
|
|
112
|
-
_delay = undefined;
|
|
113
|
-
isHandlingEvent = false;
|
|
114
|
-
backoff.reset();
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
41
|
}
|
|
118
42
|
|
|
119
|
-
const updateWorkers = {
|
|
120
|
-
[MEMBERSHIPS_MS_UPDATE]: createUpdateWorker(storage.segments),
|
|
121
|
-
[MEMBERSHIPS_LS_UPDATE]: createUpdateWorker(storage.largeSegments!),
|
|
122
|
-
};
|
|
123
|
-
|
|
124
43
|
return {
|
|
125
|
-
|
|
126
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Invoked by NotificationProcessor on MY_SEGMENTS_UPDATE event
|
|
46
|
+
*
|
|
47
|
+
* @param {number} changeNumber change number of the MY_SEGMENTS_UPDATE notification
|
|
48
|
+
* @param {SegmentsData | undefined} segmentsData might be undefined
|
|
49
|
+
*/
|
|
50
|
+
put(changeNumber: number, segmentsData?: MySegmentsData) {
|
|
51
|
+
if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
|
|
52
|
+
|
|
53
|
+
maxChangeNumber = changeNumber;
|
|
54
|
+
handleNewEvent = true;
|
|
55
|
+
_segmentsData = segmentsData;
|
|
56
|
+
|
|
57
|
+
if (backoff.timeoutID || !isHandlingEvent) __handleMySegmentsUpdateCall();
|
|
58
|
+
backoff.reset();
|
|
127
59
|
},
|
|
60
|
+
|
|
128
61
|
stop() {
|
|
129
|
-
|
|
130
|
-
|
|
62
|
+
isHandlingEvent = false;
|
|
63
|
+
backoff.reset();
|
|
131
64
|
}
|
|
132
65
|
};
|
|
133
66
|
}
|
|
@@ -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) {
|
|
@@ -21,7 +21,7 @@ export function SegmentsUpdateWorker(log: ILogger, segmentsSyncTask: ISegmentsSy
|
|
|
21
21
|
|
|
22
22
|
function __handleSegmentUpdateCall() {
|
|
23
23
|
isHandlingEvent = true;
|
|
24
|
-
if (maxChangeNumber > segmentsCache.getChangeNumber(segment)) {
|
|
24
|
+
if (maxChangeNumber > (segmentsCache.getChangeNumber(segment) || -1)) {
|
|
25
25
|
handleNewEvent = false;
|
|
26
26
|
|
|
27
27
|
// fetch segments revalidating data if cached
|
|
@@ -32,7 +32,7 @@ export function SegmentsUpdateWorker(log: ILogger, segmentsSyncTask: ISegmentsSy
|
|
|
32
32
|
} else {
|
|
33
33
|
const attempts = backoff.attempts + 1;
|
|
34
34
|
|
|
35
|
-
if (maxChangeNumber <= segmentsCache.getChangeNumber(segment)) {
|
|
35
|
+
if (maxChangeNumber <= (segmentsCache.getChangeNumber(segment) || -1)) {
|
|
36
36
|
log.debug(`Refresh completed${cdnBypass ? ' bypassing the CDN' : ''} in ${attempts} attempts.`);
|
|
37
37
|
isHandlingEvent = false;
|
|
38
38
|
return;
|
|
@@ -60,7 +60,7 @@ export function SegmentsUpdateWorker(log: ILogger, segmentsSyncTask: ISegmentsSy
|
|
|
60
60
|
|
|
61
61
|
return {
|
|
62
62
|
put(changeNumber: number) {
|
|
63
|
-
const currentChangeNumber = segmentsCache.getChangeNumber(segment);
|
|
63
|
+
const currentChangeNumber = segmentsCache.getChangeNumber(segment) || -1;
|
|
64
64
|
|
|
65
65
|
if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
|
|
66
66
|
|
|
@@ -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;
|
|
@@ -25,8 +25,8 @@ export const PUSH_SUBSYSTEM_UP = 'PUSH_SUBSYSTEM_UP';
|
|
|
25
25
|
export const PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN';
|
|
26
26
|
|
|
27
27
|
// Update-type push notifications, handled by NotificationProcessor
|
|
28
|
-
export const
|
|
29
|
-
export const
|
|
28
|
+
export const MY_SEGMENTS_UPDATE = 'MY_SEGMENTS_UPDATE';
|
|
29
|
+
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';
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { algorithms } from '../../utils/decompress';
|
|
2
2
|
import { decodeFromBase64 } from '../../utils/base64';
|
|
3
|
-
import {
|
|
4
|
-
import { Compression, IMembershipMSUpdateData, KeyList } from './SSEHandler/types';
|
|
5
|
-
import { ISplit } from '../../dtos/types';
|
|
3
|
+
import { Compression, KeyList } from './SSEHandler/types';
|
|
6
4
|
|
|
7
5
|
const GZIP = 1;
|
|
8
6
|
const ZLIB = 2;
|
|
@@ -44,7 +42,7 @@ function decompress(data: string, compression: Compression) {
|
|
|
44
42
|
* @returns {{a?: string[], r?: string[] }}
|
|
45
43
|
* @throws if data string cannot be decoded, decompressed or parsed
|
|
46
44
|
*/
|
|
47
|
-
export function parseKeyList(data: string, compression: Compression, avoidPrecisionLoss = true): KeyList {
|
|
45
|
+
export function parseKeyList(data: string, compression: Compression, avoidPrecisionLoss: boolean = true): KeyList {
|
|
48
46
|
const binKeyList = decompress(data, compression);
|
|
49
47
|
let strKeyList = Uint8ArrayToString(binKeyList);
|
|
50
48
|
// replace numbers to strings, to avoid losing precision
|
|
@@ -82,20 +80,14 @@ export function isInBitmap(bitmap: Uint8Array, hash64hex: string) {
|
|
|
82
80
|
|
|
83
81
|
/**
|
|
84
82
|
* Parse feature flags notifications for instant feature flag updates
|
|
83
|
+
*
|
|
84
|
+
* @param {ISplitUpdateData} data
|
|
85
|
+
* @returns {KeyList}
|
|
85
86
|
*/
|
|
86
|
-
export function parseFFUpdatePayload(compression: Compression, data: string):
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const DEFAULT_MAX_INTERVAL = 60000;
|
|
93
|
-
|
|
94
|
-
export function getDelay(parsedData: Pick<IMembershipMSUpdateData, 'i' | 'h' | 's'>, matchingKey: string) {
|
|
95
|
-
if (parsedData.h === 0) return 0;
|
|
96
|
-
|
|
97
|
-
const interval = parsedData.i || DEFAULT_MAX_INTERVAL;
|
|
98
|
-
const seed = parsedData.s || 0;
|
|
99
|
-
|
|
100
|
-
return hash(matchingKey, seed) % interval;
|
|
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));
|
|
101
93
|
}
|
|
@@ -11,15 +11,16 @@ import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
|
11
11
|
import { forOwn } from '../../utils/lang';
|
|
12
12
|
import { SSEClient } from './SSEClient';
|
|
13
13
|
import { getMatching } from '../../utils/key';
|
|
14
|
-
import {
|
|
15
|
-
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT,
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
14
|
+
import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
|
|
15
|
+
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, STREAMING_PARSING_SPLIT_UPDATE } from '../../logger/constants';
|
|
16
|
+
import { KeyList, UpdateStrategy } from './SSEHandler/types';
|
|
17
|
+
import { isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
|
|
18
18
|
import { ISet, _Set } from '../../utils/lang/sets';
|
|
19
19
|
import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
|
|
20
20
|
import { IAuthTokenPushEnabled } from './AuthClient/types';
|
|
21
21
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
22
22
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
23
|
+
import { IUpdateWorker } from './UpdateWorkers/types';
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* PushManager factory:
|
|
@@ -59,11 +60,11 @@ export function pushManagerFactory(
|
|
|
59
60
|
// For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
|
|
60
61
|
const splitsUpdateWorker = SplitsUpdateWorker(log, storage.splits, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
|
|
61
62
|
|
|
62
|
-
// [Only for client-side] map of hashes to user keys, to dispatch
|
|
63
|
+
// [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker
|
|
63
64
|
const userKeyHashes: Record<string, string> = {};
|
|
64
65
|
// [Only for client-side] map of user keys to their corresponding hash64 and MySegmentsUpdateWorkers.
|
|
65
|
-
// Hash64 is used to process
|
|
66
|
-
const clients: Record<string, { hash64: Hash64, worker:
|
|
66
|
+
// Hash64 is used to process MY_SEGMENTS_UPDATE_V2 events and dispatch actions to the corresponding MySegmentsUpdateWorker.
|
|
67
|
+
const clients: Record<string, { hash64: Hash64, worker: IUpdateWorker }> = {};
|
|
67
68
|
|
|
68
69
|
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
69
70
|
let connectForNewClient = false;
|
|
@@ -235,75 +236,76 @@ export function pushManagerFactory(
|
|
|
235
236
|
splitsUpdateWorker.put(parsedData);
|
|
236
237
|
});
|
|
237
238
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
forOwn(clients, ({ hash64, worker }, matchingKey) => {
|
|
250
|
-
if (isInBitmap(bitmap, hash64.hex)) {
|
|
251
|
-
worker.put(parsedData, undefined, getDelay(parsedData, matchingKey));
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
return;
|
|
239
|
+
if (userKey) {
|
|
240
|
+
pushEmitter.on(MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
|
|
241
|
+
const userKeyHash = channel.split('_')[2];
|
|
242
|
+
const userKey = userKeyHashes[userKeyHash];
|
|
243
|
+
if (userKey && clients[userKey]) { // check existence since it can be undefined if client has been destroyed
|
|
244
|
+
clients[userKey].worker.put(
|
|
245
|
+
parsedData.changeNumber,
|
|
246
|
+
parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
|
|
255
247
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
248
|
+
});
|
|
249
|
+
pushEmitter.on(MY_SEGMENTS_UPDATE_V2, function handleMySegmentsUpdate(parsedData) {
|
|
250
|
+
switch (parsedData.u) {
|
|
251
|
+
case UpdateStrategy.BoundedFetchRequest: {
|
|
252
|
+
let bitmap: Uint8Array;
|
|
253
|
+
try {
|
|
254
|
+
bitmap = parseBitmap(parsedData.d, parsedData.c);
|
|
255
|
+
} catch (e) {
|
|
256
|
+
log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['BoundedFetchRequest', e]);
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
266
259
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
260
|
+
forOwn(clients, ({ hash64, worker }) => {
|
|
261
|
+
if (isInBitmap(bitmap, hash64.hex)) {
|
|
262
|
+
worker.put(parsedData.changeNumber); // fetch mySegments
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
return;
|
|
270
266
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
267
|
+
case UpdateStrategy.KeyList: {
|
|
268
|
+
let keyList: KeyList, added: ISet<string>, removed: ISet<string>;
|
|
269
|
+
try {
|
|
270
|
+
keyList = parseKeyList(parsedData.d, parsedData.c);
|
|
271
|
+
added = new _Set(keyList.a);
|
|
272
|
+
removed = new _Set(keyList.r);
|
|
273
|
+
} catch (e) {
|
|
274
|
+
log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['KeyList', e]);
|
|
275
|
+
break;
|
|
279
276
|
}
|
|
280
|
-
});
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
case UpdateStrategy.SegmentRemoval:
|
|
284
|
-
if (!parsedData.n || !parsedData.n.length) {
|
|
285
|
-
log.warn(STREAMING_PARSING_MEMBERSHIPS_UPDATE, ['SegmentRemoval', 'No segment name was provided']);
|
|
286
|
-
break;
|
|
287
|
-
}
|
|
288
277
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
278
|
+
forOwn(clients, ({ hash64, worker }) => {
|
|
279
|
+
const add = added.has(hash64.dec) ? true : removed.has(hash64.dec) ? false : undefined;
|
|
280
|
+
if (add !== undefined) {
|
|
281
|
+
worker.put(parsedData.changeNumber, {
|
|
282
|
+
name: parsedData.segmentName,
|
|
283
|
+
add
|
|
284
|
+
});
|
|
285
|
+
}
|
|
293
286
|
});
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
case UpdateStrategy.SegmentRemoval:
|
|
290
|
+
if (!parsedData.segmentName) {
|
|
291
|
+
log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['SegmentRemoval', 'No segment name was provided']);
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
297
294
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
295
|
+
forOwn(clients, ({ worker }) =>
|
|
296
|
+
worker.put(parsedData.changeNumber, {
|
|
297
|
+
name: parsedData.segmentName,
|
|
298
|
+
add: false
|
|
299
|
+
})
|
|
300
|
+
);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
303
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
304
|
+
// `UpdateStrategy.UnboundedFetchRequest` and fallbacks of other cases
|
|
305
|
+
forOwn(clients, ({ worker }) => {
|
|
306
|
+
worker.put(parsedData.changeNumber);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
307
309
|
} else {
|
|
308
310
|
pushEmitter.on(SEGMENT_UPDATE, segmentsUpdateWorker!.put);
|
|
309
311
|
}
|
|
@@ -326,7 +328,7 @@ export function pushManagerFactory(
|
|
|
326
328
|
if (disabled || disconnected === false) return;
|
|
327
329
|
disconnected = false;
|
|
328
330
|
|
|
329
|
-
if (userKey) this.add(userKey, pollingManager.segmentsSyncTask); // client-side
|
|
331
|
+
if (userKey) this.add(userKey, pollingManager.segmentsSyncTask as IMySegmentsSyncTask); // client-side
|
|
330
332
|
else setTimeout(connectPush); // server-side runs in next cycle as in client-side, for consistency with client-side
|
|
331
333
|
},
|
|
332
334
|
|
|
@@ -341,10 +343,7 @@ export function pushManagerFactory(
|
|
|
341
343
|
|
|
342
344
|
if (!userKeyHashes[hash]) {
|
|
343
345
|
userKeyHashes[hash] = userKey;
|
|
344
|
-
clients[userKey] = {
|
|
345
|
-
hash64: hash64(userKey),
|
|
346
|
-
worker: MySegmentsUpdateWorker(log, storage, mySegmentsSyncTask, telemetryTracker)
|
|
347
|
-
};
|
|
346
|
+
clients[userKey] = { hash64: hash64(userKey), worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) };
|
|
348
347
|
connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
|
|
349
348
|
|
|
350
349
|
// Reconnects in case of a new client.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IMySegmentsUpdateData, IMySegmentsUpdateV2Data, ISegmentUpdateData, ISplitUpdateData, ISplitKillData } from './SSEHandler/types';
|
|
2
2
|
import { ITask } from '../types';
|
|
3
3
|
import { IMySegmentsSyncTask } from '../polling/types';
|
|
4
4
|
import { IEventEmitter } from '../../types';
|
|
@@ -11,8 +11,8 @@ export type PUSH_NONRETRYABLE_ERROR = 'PUSH_NONRETRYABLE_ERROR'
|
|
|
11
11
|
export type PUSH_RETRYABLE_ERROR = 'PUSH_RETRYABLE_ERROR'
|
|
12
12
|
|
|
13
13
|
// Update-type push notifications, handled by NotificationProcessor
|
|
14
|
-
export type
|
|
15
|
-
export type
|
|
14
|
+
export type MY_SEGMENTS_UPDATE = 'MY_SEGMENTS_UPDATE';
|
|
15
|
+
export type MY_SEGMENTS_UPDATE_V2 = 'MY_SEGMENTS_UPDATE_V2';
|
|
16
16
|
export type SEGMENT_UPDATE = 'SEGMENT_UPDATE';
|
|
17
17
|
export type SPLIT_KILL = 'SPLIT_KILL';
|
|
18
18
|
export type SPLIT_UPDATE = 'SPLIT_UPDATE';
|
|
@@ -21,23 +21,23 @@ export type SPLIT_UPDATE = 'SPLIT_UPDATE';
|
|
|
21
21
|
export type CONTROL = 'CONTROL';
|
|
22
22
|
export type OCCUPANCY = 'OCCUPANCY';
|
|
23
23
|
|
|
24
|
-
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NONRETRYABLE_ERROR | PUSH_RETRYABLE_ERROR |
|
|
24
|
+
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NONRETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MY_SEGMENTS_UPDATE | MY_SEGMENTS_UPDATE_V2 | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | ControlType.STREAMING_RESET
|
|
25
25
|
|
|
26
26
|
type IParsedData<T extends IPushEvent> =
|
|
27
|
-
T extends
|
|
28
|
-
T extends
|
|
27
|
+
T extends MY_SEGMENTS_UPDATE ? IMySegmentsUpdateData :
|
|
28
|
+
T extends MY_SEGMENTS_UPDATE_V2 ? IMySegmentsUpdateV2Data :
|
|
29
29
|
T extends SEGMENT_UPDATE ? ISegmentUpdateData :
|
|
30
30
|
T extends SPLIT_UPDATE ? ISplitUpdateData :
|
|
31
|
-
T extends SPLIT_KILL ? ISplitKillData :
|
|
31
|
+
T extends SPLIT_KILL ? ISplitKillData : undefined;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* EventEmitter used as Feedback Loop between the SyncManager and PushManager,
|
|
35
35
|
* where the latter pushes messages and the former consumes it
|
|
36
36
|
*/
|
|
37
37
|
export interface IPushEventEmitter extends IEventEmitter {
|
|
38
|
-
once<T extends IPushEvent>(event: T, listener: (parsedData: IParsedData<T
|
|
39
|
-
on<T extends IPushEvent>(event: T, listener: (parsedData: IParsedData<T
|
|
40
|
-
emit<T extends IPushEvent>(event: T, parsedData?: IParsedData<T
|
|
38
|
+
once<T extends IPushEvent>(event: T, listener: (parsedData: IParsedData<T>, channel: T extends MY_SEGMENTS_UPDATE ? string : undefined) => void): this;
|
|
39
|
+
on<T extends IPushEvent>(event: T, listener: (parsedData: IParsedData<T>, channel: T extends MY_SEGMENTS_UPDATE ? string : undefined) => void): this;
|
|
40
|
+
emit<T extends IPushEvent>(event: T, parsedData?: IParsedData<T>, channel?: T extends MY_SEGMENTS_UPDATE ? string : undefined): boolean;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|