@splitsoftware/splitio-commons 1.17.1-rc.3 → 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 -28
- 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 +11 -12
- 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 +17 -15
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +17 -15
- package/cjs/sdkFactory/index.js +11 -38
- 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 +12 -41
- package/cjs/storages/AbstractSplitsCacheAsync.js +7 -0
- package/cjs/storages/AbstractSplitsCacheSync.js +8 -2
- package/cjs/storages/KeyBuilderCS.js +5 -23
- package/cjs/storages/dataLoader.js +33 -65
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +52 -29
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +9 -1
- package/cjs/storages/inLocalStorage/index.js +3 -12
- package/cjs/storages/inMemory/InMemoryStorageCS.js +3 -20
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +40 -9
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +8 -8
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +10 -7
- package/cjs/storages/inRedis/RedisAdapter.js +1 -1
- package/cjs/storages/inRedis/SegmentsCacheInRedis.js +2 -2
- package/cjs/storages/inRedis/index.js +11 -5
- package/cjs/storages/pluggable/SegmentsCachePluggable.js +2 -2
- package/cjs/storages/pluggable/inMemoryWrapper.js +1 -1
- package/cjs/storages/pluggable/index.js +32 -37
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +7 -2
- 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/pollingManagerSS.js +3 -3
- 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 +2 -2
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +11 -2
- 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/syncTask.js +2 -2
- package/cjs/trackers/eventTracker.js +9 -11
- package/cjs/trackers/impressionsTracker.js +13 -15
- package/cjs/trackers/uniqueKeysTracker.js +3 -5
- package/cjs/utils/constants/index.js +4 -5
- package/cjs/utils/settingsValidation/index.js +1 -2
- package/cjs/utils/settingsValidation/storage/storageCS.js +12 -1
- 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 +11 -12
- 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 +15 -13
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +15 -13
- package/esm/sdkFactory/index.js +12 -39
- 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 +12 -41
- package/esm/storages/AbstractSplitsCacheAsync.js +7 -0
- package/esm/storages/AbstractSplitsCacheSync.js +9 -3
- package/esm/storages/KeyBuilderCS.js +4 -21
- package/esm/storages/dataLoader.js +31 -62
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +52 -29
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +9 -1
- package/esm/storages/inLocalStorage/index.js +5 -14
- package/esm/storages/inMemory/InMemoryStorageCS.js +3 -20
- package/esm/storages/inMemory/MySegmentsCacheInMemory.js +40 -9
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/SplitsCacheInMemory.js +8 -8
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +10 -7
- package/esm/storages/inRedis/RedisAdapter.js +1 -1
- package/esm/storages/inRedis/SegmentsCacheInRedis.js +2 -2
- package/esm/storages/inRedis/index.js +11 -5
- package/esm/storages/pluggable/SegmentsCachePluggable.js +2 -2
- package/esm/storages/pluggable/inMemoryWrapper.js +1 -1
- package/esm/storages/pluggable/index.js +32 -37
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +8 -3
- 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/pollingManagerSS.js +3 -3
- 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 +2 -2
- package/esm/sync/polling/updaters/splitChangesUpdater.js +12 -3
- 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/syncTask.js +2 -2
- package/esm/trackers/eventTracker.js +9 -11
- package/esm/trackers/impressionsTracker.js +13 -15
- package/esm/trackers/uniqueKeysTracker.js +3 -5
- package/esm/utils/constants/index.js +2 -3
- package/esm/utils/settingsValidation/index.js +1 -2
- package/esm/utils/settingsValidation/storage/storageCS.js +10 -0
- 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 +12 -16
- package/src/readiness/sdkReadinessManager.ts +7 -7
- package/src/readiness/types.ts +2 -3
- package/src/sdkClient/sdkClient.ts +5 -5
- package/src/sdkClient/sdkClientMethod.ts +1 -4
- package/src/sdkClient/sdkClientMethodCS.ts +14 -11
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +14 -11
- package/src/sdkFactory/index.ts +13 -42
- package/src/sdkFactory/types.ts +1 -5
- 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 +12 -53
- package/src/storages/AbstractSplitsCacheAsync.ts +8 -0
- package/src/storages/AbstractSplitsCacheSync.ts +11 -4
- package/src/storages/KeyBuilderCS.ts +5 -34
- package/src/storages/dataLoader.ts +33 -63
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +59 -29
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +10 -1
- package/src/storages/inLocalStorage/index.ts +6 -16
- package/src/storages/inMemory/InMemoryStorageCS.ts +3 -23
- package/src/storages/inMemory/MySegmentsCacheInMemory.ts +44 -10
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +1 -1
- package/src/storages/inMemory/SplitsCacheInMemory.ts +8 -7
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +11 -7
- package/src/storages/inRedis/RedisAdapter.ts +1 -1
- package/src/storages/inRedis/SegmentsCacheInRedis.ts +2 -2
- package/src/storages/inRedis/index.ts +12 -6
- package/src/storages/pluggable/SegmentsCachePluggable.ts +2 -2
- package/src/storages/pluggable/inMemoryWrapper.ts +1 -1
- package/src/storages/pluggable/index.ts +33 -38
- package/src/storages/types.ts +15 -15
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +7 -3
- 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/pollingManagerSS.ts +2 -3
- 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 +2 -2
- package/src/sync/polling/updaters/splitChangesUpdater.ts +12 -4
- 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/syncTask.ts +2 -2
- package/src/trackers/eventTracker.ts +7 -10
- package/src/trackers/impressionsTracker.ts +9 -12
- package/src/trackers/types.ts +0 -1
- package/src/trackers/uniqueKeysTracker.ts +4 -6
- package/src/types.ts +9 -16
- package/src/utils/constants/index.ts +2 -3
- package/src/utils/settingsValidation/index.ts +2 -3
- package/src/utils/settingsValidation/storage/storageCS.ts +13 -0
- 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 -3
- package/types/sdkClient/sdkClientMethod.d.ts +1 -1
- package/types/sdkFactory/types.d.ts +1 -4
- 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/AbstractSplitsCacheAsync.d.ts +5 -0
- package/types/storages/AbstractSplitsCacheSync.d.ts +6 -1
- package/types/storages/KeyBuilderCS.d.ts +2 -9
- package/types/storages/dataLoader.d.ts +6 -17
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +14 -4
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +6 -0
- package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +9 -3
- package/types/storages/inMemory/SegmentsCacheInMemory.d.ts +1 -1
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -1
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +6 -4
- package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +1 -1
- package/types/storages/inRedis/index.d.ts +1 -1
- package/types/storages/pluggable/SegmentsCachePluggable.d.ts +1 -1
- package/types/storages/pluggable/inMemoryWrapper.d.ts +1 -1
- package/types/storages/types.d.ts +11 -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/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 +9 -15
- package/types/utils/constants/index.d.ts +2 -3
- package/types/utils/settingsValidation/storage/storageCS.d.ts +5 -0
- 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/esm/evaluator/matchers/large_segment.js +0 -12
- package/esm/sdkClient/identity.js +0 -3
- package/src/evaluator/matchers/large_segment.ts +0 -18
- package/src/sdkClient/identity.ts +0 -5
- 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,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
|
/**
|
|
@@ -103,7 +103,7 @@ export type DROPPED = 1;
|
|
|
103
103
|
export type DEDUPED = 2;
|
|
104
104
|
export type ImpressionDataType = QUEUED | DROPPED | DEDUPED
|
|
105
105
|
export type EventDataType = QUEUED | DROPPED;
|
|
106
|
-
export type UpdatesFromSSEEnum = SPLITS |
|
|
106
|
+
export type UpdatesFromSSEEnum = SPLITS | MY_SEGMENT;
|
|
107
107
|
|
|
108
108
|
export type SPLITS = 'sp';
|
|
109
109
|
export type IMPRESSIONS = 'im';
|
|
@@ -112,8 +112,8 @@ export type EVENTS = 'ev';
|
|
|
112
112
|
export type TELEMETRY = 'te';
|
|
113
113
|
export type TOKEN = 'to';
|
|
114
114
|
export type SEGMENT = 'se';
|
|
115
|
-
export type
|
|
116
|
-
export type OperationType = SPLITS | IMPRESSIONS | IMPRESSIONS_COUNT | EVENTS | TELEMETRY | TOKEN | SEGMENT |
|
|
115
|
+
export type MY_SEGMENT = 'ms';
|
|
116
|
+
export type OperationType = SPLITS | IMPRESSIONS | IMPRESSIONS_COUNT | EVENTS | TELEMETRY | TOKEN | SEGMENT | MY_SEGMENT;
|
|
117
117
|
|
|
118
118
|
export type LastSync = Partial<Record<OperationType, number | undefined>>
|
|
119
119
|
export type HttpErrors = Partial<Record<OperationType, { [statusCode: string]: number }>>
|
|
@@ -158,9 +158,8 @@ export type TelemetryUsageStats = {
|
|
|
158
158
|
|
|
159
159
|
// amount of instant updates that we are doing by avoiding fetching to Split servers
|
|
160
160
|
export type UpdatesFromSSE = {
|
|
161
|
-
sp
|
|
161
|
+
sp: number, // splits
|
|
162
162
|
ms?: number, // my segments
|
|
163
|
-
mls?: number // my large segments
|
|
164
163
|
}
|
|
165
164
|
|
|
166
165
|
// 'metrics/usage' JSON request body
|
|
@@ -176,14 +175,12 @@ export type TelemetryUsageStatsPayload = TelemetryUsageStats & {
|
|
|
176
175
|
spC?: number, // splitCount
|
|
177
176
|
seC?: number, // segmentCount
|
|
178
177
|
skC?: number, // segmentKeyCount
|
|
179
|
-
lsC?: number, // largeSegmentCount
|
|
180
|
-
lskC?: number, // largeSegmentKeyCount
|
|
181
178
|
sL?: number, // sessionLengthMs
|
|
182
179
|
eQ: number, // eventsQueued
|
|
183
180
|
eD: number, // eventsDropped
|
|
184
181
|
sE: Array<StreamingEvent>, // streamingEvents
|
|
185
182
|
t?: Array<string>, // tags
|
|
186
|
-
ufs?: UpdatesFromSSE, //
|
|
183
|
+
ufs?: UpdatesFromSSE, //UpdatesFromSSE
|
|
187
184
|
}
|
|
188
185
|
|
|
189
186
|
/**
|
package/src/sync/syncTask.ts
CHANGED
|
@@ -68,8 +68,8 @@ export function syncTaskFactory<Input extends any[], Output = any>(log: ILogger,
|
|
|
68
68
|
},
|
|
69
69
|
|
|
70
70
|
stop() {
|
|
71
|
-
running
|
|
72
|
-
|
|
71
|
+
if (running) {
|
|
72
|
+
running = false;
|
|
73
73
|
log.debug(SYNC_TASK_STOP, [taskName]);
|
|
74
74
|
clearTimeout(timeoutID);
|
|
75
75
|
timeoutID = undefined;
|
|
@@ -16,7 +16,6 @@ import { isConsumerMode } from '../utils/settingsValidation/mode';
|
|
|
16
16
|
export function eventTrackerFactory(
|
|
17
17
|
settings: ISettings,
|
|
18
18
|
eventsCache: IEventsCacheBase,
|
|
19
|
-
whenInit: (cb: () => void) => void,
|
|
20
19
|
integrationsManager?: IEventsHandler,
|
|
21
20
|
telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync
|
|
22
21
|
): IEventTracker {
|
|
@@ -33,15 +32,13 @@ export function eventTrackerFactory(
|
|
|
33
32
|
log.info(EVENTS_TRACKER_SUCCESS, [msg]);
|
|
34
33
|
if (integrationsManager) {
|
|
35
34
|
// Wrap in a timeout because we don't want it to be blocking.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
});
|
|
35
|
+
setTimeout(function () {
|
|
36
|
+
// copy of event, to avoid unexpected behaviour if modified by integrations
|
|
37
|
+
const eventDataCopy = objectAssign({}, eventData);
|
|
38
|
+
if (properties) eventDataCopy.properties = objectAssign({}, properties);
|
|
39
|
+
// integrationsManager does not throw errors (they are internally handled by each integration module)
|
|
40
|
+
integrationsManager.handleEvent(eventDataCopy);
|
|
41
|
+
}, 0);
|
|
45
42
|
}
|
|
46
43
|
} else {
|
|
47
44
|
log.error(ERROR_EVENTS_TRACKER, [msg]);
|