@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
|
@@ -3,7 +3,7 @@ import { ImpressionCountsCacheInMemory } from '../inMemory/ImpressionCountsCache
|
|
|
3
3
|
import { EventsCacheInMemory } from '../inMemory/EventsCacheInMemory';
|
|
4
4
|
import { IStorageFactoryParams, IStorageSync, IStorageSyncFactory } from '../types';
|
|
5
5
|
import { validatePrefix } from '../KeyBuilder';
|
|
6
|
-
import { KeyBuilderCS
|
|
6
|
+
import { KeyBuilderCS } from '../KeyBuilderCS';
|
|
7
7
|
import { isLocalStorageAvailable } from '../../utils/env/isLocalStorageAvailable';
|
|
8
8
|
import { SplitsCacheInLocal } from './SplitsCacheInLocal';
|
|
9
9
|
import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
|
|
@@ -12,7 +12,7 @@ import { SplitsCacheInMemory } from '../inMemory/SplitsCacheInMemory';
|
|
|
12
12
|
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
|
|
13
13
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
14
14
|
import { LOG_PREFIX } from './constants';
|
|
15
|
-
import { DEBUG,
|
|
15
|
+
import { DEBUG, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
16
16
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
17
17
|
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
18
18
|
import { getMatching } from '../../utils/key';
|
|
@@ -36,35 +36,26 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
36
36
|
return InMemoryStorageCSFactory(params);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const {
|
|
39
|
+
const { settings, settings: { log, scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params;
|
|
40
40
|
const matchingKey = getMatching(settings.core.key);
|
|
41
|
-
const keys = new KeyBuilderCS(prefix, matchingKey);
|
|
41
|
+
const keys = new KeyBuilderCS(prefix, matchingKey as string);
|
|
42
42
|
const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
|
|
43
43
|
|
|
44
44
|
const splits = new SplitsCacheInLocal(settings, keys, expirationTimestamp);
|
|
45
45
|
const segments = new MySegmentsCacheInLocal(log, keys);
|
|
46
|
-
const largeSegments = new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey));
|
|
47
46
|
|
|
48
47
|
return {
|
|
49
48
|
splits,
|
|
50
49
|
segments,
|
|
51
|
-
largeSegments,
|
|
52
50
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
53
51
|
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
54
52
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
55
53
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
56
54
|
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
57
55
|
|
|
58
|
-
init() {
|
|
59
|
-
if (settings.mode === LOCALHOST_MODE || splits.getChangeNumber() > -1) {
|
|
60
|
-
Promise.resolve().then(onReadyFromCacheCb);
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
|
|
64
56
|
destroy() {
|
|
65
57
|
this.splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
66
58
|
this.segments = new MySegmentsCacheInMemory();
|
|
67
|
-
this.largeSegments = new MySegmentsCacheInMemory();
|
|
68
59
|
this.impressions.clear();
|
|
69
60
|
this.impressionCounts && this.impressionCounts.clear();
|
|
70
61
|
this.events.clear();
|
|
@@ -73,11 +64,11 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
73
64
|
|
|
74
65
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are customer per key).
|
|
75
66
|
shared(matchingKey: string) {
|
|
67
|
+
const childKeysBuilder = new KeyBuilderCS(prefix, matchingKey);
|
|
76
68
|
|
|
77
69
|
return {
|
|
78
70
|
splits: this.splits,
|
|
79
|
-
segments: new MySegmentsCacheInLocal(log,
|
|
80
|
-
largeSegments: new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey)),
|
|
71
|
+
segments: new MySegmentsCacheInLocal(log, childKeysBuilder),
|
|
81
72
|
impressions: this.impressions,
|
|
82
73
|
impressionCounts: this.impressionCounts,
|
|
83
74
|
events: this.events,
|
|
@@ -86,7 +77,6 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
86
77
|
destroy() {
|
|
87
78
|
this.splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
88
79
|
this.segments = new MySegmentsCacheInMemory();
|
|
89
|
-
this.largeSegments = new MySegmentsCacheInMemory();
|
|
90
80
|
}
|
|
91
81
|
};
|
|
92
82
|
},
|
|
@@ -7,8 +7,6 @@ import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
|
7
7
|
import { DEBUG, LOCALHOST_MODE, NONE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
9
|
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
10
|
-
import { getMatching } from '../../utils/key';
|
|
11
|
-
import { loadData } from '../dataLoader';
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
12
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
@@ -16,16 +14,14 @@ import { loadData } from '../dataLoader';
|
|
|
16
14
|
* @param params parameters required by EventsCacheSync
|
|
17
15
|
*/
|
|
18
16
|
export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorageSync {
|
|
19
|
-
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation }
|
|
17
|
+
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params;
|
|
20
18
|
|
|
21
19
|
const splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
22
20
|
const segments = new MySegmentsCacheInMemory();
|
|
23
|
-
const largeSegments = new MySegmentsCacheInMemory();
|
|
24
21
|
|
|
25
22
|
const storage = {
|
|
26
23
|
splits,
|
|
27
24
|
segments,
|
|
28
|
-
largeSegments,
|
|
29
25
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
30
26
|
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
31
27
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
@@ -36,7 +32,6 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
36
32
|
destroy() {
|
|
37
33
|
this.splits.clear();
|
|
38
34
|
this.segments.clear();
|
|
39
|
-
this.largeSegments.clear();
|
|
40
35
|
this.impressions.clear();
|
|
41
36
|
this.impressionCounts && this.impressionCounts.clear();
|
|
42
37
|
this.events.clear();
|
|
@@ -44,18 +39,10 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
44
39
|
},
|
|
45
40
|
|
|
46
41
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key)
|
|
47
|
-
shared(
|
|
48
|
-
const segments = new MySegmentsCacheInMemory();
|
|
49
|
-
const largeSegments = new MySegmentsCacheInMemory();
|
|
50
|
-
|
|
51
|
-
if (preloadedData) {
|
|
52
|
-
loadData(preloadedData, { segments, largeSegments }, matchingKey);
|
|
53
|
-
}
|
|
54
|
-
|
|
42
|
+
shared() {
|
|
55
43
|
return {
|
|
56
44
|
splits: this.splits,
|
|
57
|
-
segments,
|
|
58
|
-
largeSegments,
|
|
45
|
+
segments: new MySegmentsCacheInMemory(),
|
|
59
46
|
impressions: this.impressions,
|
|
60
47
|
impressionCounts: this.impressionCounts,
|
|
61
48
|
events: this.events,
|
|
@@ -65,7 +52,6 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
65
52
|
destroy() {
|
|
66
53
|
this.splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
67
54
|
this.segments.clear();
|
|
68
|
-
this.largeSegments.clear();
|
|
69
55
|
}
|
|
70
56
|
};
|
|
71
57
|
},
|
|
@@ -81,12 +67,6 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
81
67
|
if (storage.uniqueKeys) storage.uniqueKeys.track = noopTrack;
|
|
82
68
|
}
|
|
83
69
|
|
|
84
|
-
|
|
85
|
-
if (preloadedData) {
|
|
86
|
-
loadData(preloadedData, storage, getMatching(params.settings.core.key));
|
|
87
|
-
if (splits.getChangeNumber() > -1) onReadyFromCacheCb();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
70
|
return storage;
|
|
91
71
|
}
|
|
92
72
|
|
|
@@ -7,19 +7,18 @@ import { AbstractSegmentsCacheSync } from '../AbstractSegmentsCacheSync';
|
|
|
7
7
|
export class MySegmentsCacheInMemory extends AbstractSegmentsCacheSync {
|
|
8
8
|
|
|
9
9
|
private segmentCache: Record<string, boolean> = {};
|
|
10
|
-
private cn?: number;
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
clear() {
|
|
12
|
+
this.segmentCache = {};
|
|
13
|
+
}
|
|
14
14
|
|
|
15
|
+
addToSegment(name: string): boolean {
|
|
15
16
|
this.segmentCache[name] = true;
|
|
16
17
|
|
|
17
18
|
return true;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
removeFromSegment(name: string): boolean {
|
|
21
|
-
if (!this.segmentCache[name]) return false;
|
|
22
|
-
|
|
23
22
|
delete this.segmentCache[name];
|
|
24
23
|
|
|
25
24
|
return true;
|
|
@@ -29,13 +28,48 @@ export class MySegmentsCacheInMemory extends AbstractSegmentsCacheSync {
|
|
|
29
28
|
return this.segmentCache[name] === true;
|
|
30
29
|
}
|
|
31
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Reset (update) the cached list of segments with the given list, removing and adding segments if necessary.
|
|
33
|
+
* @NOTE based on the way we use segments in the browser, this way is the best option
|
|
34
|
+
*
|
|
35
|
+
* @param {string[]} names list of segment names
|
|
36
|
+
* @returns boolean indicating if the cache was updated (i.e., given list was different from the cached one)
|
|
37
|
+
*/
|
|
38
|
+
resetSegments(names: string[]): boolean {
|
|
39
|
+
let isDiff = false;
|
|
40
|
+
let index;
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
const storedSegmentKeys = Object.keys(this.segmentCache);
|
|
43
|
+
|
|
44
|
+
// Extreme fast => everything is empty
|
|
45
|
+
if (names.length === 0 && storedSegmentKeys.length === names.length)
|
|
46
|
+
return isDiff;
|
|
47
|
+
|
|
48
|
+
// Quick path
|
|
49
|
+
if (storedSegmentKeys.length !== names.length) {
|
|
50
|
+
isDiff = true;
|
|
51
|
+
|
|
52
|
+
this.segmentCache = {};
|
|
53
|
+
names.forEach(s => {
|
|
54
|
+
this.addToSegment(s);
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
// Slowest path => we need to find at least 1 difference because
|
|
58
|
+
for (index = 0; index < names.length && this.isInSegment(names[index]); index++) {
|
|
59
|
+
// TODO: why empty statement?
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (index < names.length) {
|
|
63
|
+
isDiff = true;
|
|
64
|
+
|
|
65
|
+
this.segmentCache = {};
|
|
66
|
+
names.forEach(s => {
|
|
67
|
+
this.addToSegment(s);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
36
71
|
|
|
37
|
-
|
|
38
|
-
return this.cn || -1;
|
|
72
|
+
return isDiff;
|
|
39
73
|
}
|
|
40
74
|
|
|
41
75
|
getRegisteredSegments() {
|
|
@@ -83,7 +83,7 @@ export class SegmentsCacheInMemory extends AbstractSegmentsCacheSync {
|
|
|
83
83
|
getChangeNumber(name: string) {
|
|
84
84
|
const value = this.segmentChangeNumber[name];
|
|
85
85
|
|
|
86
|
-
return isIntegerNumber(value) ? value :
|
|
86
|
+
return isIntegerNumber(value) ? value : undefined;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
}
|
|
@@ -13,7 +13,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
13
13
|
private splitsCache: Record<string, ISplit> = {};
|
|
14
14
|
private ttCache: Record<string, number> = {};
|
|
15
15
|
private changeNumber: number = -1;
|
|
16
|
-
private
|
|
16
|
+
private splitsWithSegmentsCount: number = 0;
|
|
17
17
|
private flagSetsCache: Record<string, ISet<string>> = {};
|
|
18
18
|
|
|
19
19
|
constructor(splitFiltersValidation?: ISplitFiltersValidation) {
|
|
@@ -25,7 +25,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
25
25
|
this.splitsCache = {};
|
|
26
26
|
this.ttCache = {};
|
|
27
27
|
this.changeNumber = -1;
|
|
28
|
-
this.
|
|
28
|
+
this.splitsWithSegmentsCount = 0;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
addSplit(name: string, split: ISplit): boolean {
|
|
@@ -38,8 +38,9 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
38
38
|
|
|
39
39
|
this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
|
|
41
|
+
if (usesSegments(previousSplit)) { // Substract from segments count for the previous version of this Split.
|
|
42
|
+
this.splitsWithSegmentsCount--;
|
|
43
|
+
}
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
if (split) {
|
|
@@ -51,7 +52,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
51
52
|
this.addToFlagSets(split);
|
|
52
53
|
|
|
53
54
|
// Add to segments count for the new version of the Split
|
|
54
|
-
if (usesSegments(split)) this.
|
|
55
|
+
if (usesSegments(split)) this.splitsWithSegmentsCount++;
|
|
55
56
|
|
|
56
57
|
return true;
|
|
57
58
|
} else {
|
|
@@ -71,7 +72,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
71
72
|
this.removeFromFlagSets(split.name, split.sets);
|
|
72
73
|
|
|
73
74
|
// Update the segments count.
|
|
74
|
-
if (usesSegments(split)) this.
|
|
75
|
+
if (usesSegments(split)) this.splitsWithSegmentsCount--;
|
|
75
76
|
|
|
76
77
|
return true;
|
|
77
78
|
} else {
|
|
@@ -101,7 +102,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
usesSegments(): boolean {
|
|
104
|
-
return this.getChangeNumber() === -1 || this.
|
|
105
|
+
return this.getChangeNumber() === -1 || this.splitsWithSegmentsCount > 0;
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
getNamesByFlagSets(flagSets: string[]): ISet<string>[] {
|
|
@@ -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
|
-
lsC: 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
|
|
|
@@ -20,7 +20,7 @@ const DEFAULT_OPTIONS = {
|
|
|
20
20
|
const DEFAULT_LIBRARY_OPTIONS = {
|
|
21
21
|
enableOfflineQueue: false,
|
|
22
22
|
connectTimeout: DEFAULT_OPTIONS.connectionTimeout,
|
|
23
|
-
lazyConnect: false
|
|
23
|
+
lazyConnect: false
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
interface IRedisCommand {
|
|
@@ -53,10 +53,10 @@ export class SegmentsCacheInRedis implements ISegmentsCacheAsync {
|
|
|
53
53
|
return this.redis.get(this.keys.buildSegmentTillKey(name)).then((value: string | null) => {
|
|
54
54
|
const i = parseInt(value as string, 10);
|
|
55
55
|
|
|
56
|
-
return isNaNNumber(i) ?
|
|
56
|
+
return isNaNNumber(i) ? undefined : i;
|
|
57
57
|
}).catch((e) => {
|
|
58
58
|
this.log.error(LOG_PREFIX + 'Could not retrieve changeNumber from segments storage. Error: ' + e);
|
|
59
|
-
return
|
|
59
|
+
return undefined;
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -17,19 +17,25 @@ export interface InRedisStorageOptions {
|
|
|
17
17
|
options?: Record<string, any>
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
let RD: typeof RedisAdapter | undefined;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Using `require` to prevent error when bundling or importing the SDK in a .mjs file, since ioredis is a CommonJS module.
|
|
24
|
+
// Redis storage is not supported with .mjs files.
|
|
25
|
+
RD = require('./RedisAdapter').RedisAdapter;
|
|
26
|
+
} catch (error) { /* empty */ }
|
|
27
|
+
|
|
20
28
|
/**
|
|
21
|
-
* InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node.
|
|
29
|
+
* InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node.js
|
|
22
30
|
* @see {@link https://www.npmjs.com/package/ioredis}
|
|
23
31
|
*/
|
|
24
32
|
export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsyncFactory {
|
|
25
33
|
|
|
26
|
-
// Lazy loading to prevent error when bundling or importing the SDK in a .mjs file, since ioredis is a CommonJS module.
|
|
27
|
-
// Redis storage is not supported with .mjs files.
|
|
28
|
-
const RD = require('./RedisAdapter').RedisAdapter;
|
|
29
|
-
|
|
30
34
|
const prefix = validatePrefix(options.prefix);
|
|
31
35
|
|
|
32
36
|
function InRedisStorageFactory(params: IStorageFactoryParams): IStorageAsync {
|
|
37
|
+
if (!RD) throw new Error('The SDK Redis storage is unavailable. Make sure your runtime environment supports CommonJS (`require`) so the `ioredis` dependency can be imported.');
|
|
38
|
+
|
|
33
39
|
const { onReadyCb, settings, settings: { log, sync: { impressionsMode } } } = params;
|
|
34
40
|
const metadata = metadataBuilder(settings);
|
|
35
41
|
const keys = new KeyBuilderSS(prefix, metadata);
|
|
@@ -38,7 +44,7 @@ export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsy
|
|
|
38
44
|
const impressionCountsCache = impressionsMode !== DEBUG ? new ImpressionCountsCacheInRedis(log, keys.buildImpressionsCountKey(), redisClient) : undefined;
|
|
39
45
|
const uniqueKeysCache = impressionsMode === NONE ? new UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient) : undefined;
|
|
40
46
|
|
|
41
|
-
//
|
|
47
|
+
// Subscription to Redis connect event in order to emit SDK_READY event on consumer mode
|
|
42
48
|
redisClient.on('connect', () => {
|
|
43
49
|
onReadyCb();
|
|
44
50
|
if (impressionCountsCache) impressionCountsCache.start();
|
|
@@ -80,10 +80,10 @@ export class SegmentsCachePluggable implements ISegmentsCacheAsync {
|
|
|
80
80
|
return this.wrapper.get(this.keys.buildSegmentTillKey(name)).then((value: string | null) => {
|
|
81
81
|
const i = parseInt(value as string, 10);
|
|
82
82
|
|
|
83
|
-
return isNaNNumber(i) ?
|
|
83
|
+
return isNaNNumber(i) ? undefined : i;
|
|
84
84
|
}).catch((e) => {
|
|
85
85
|
this.log.error(LOG_PREFIX + 'Could not retrieve changeNumber from segments storage. Error: ' + e);
|
|
86
|
-
return
|
|
86
|
+
return undefined;
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -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
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IPluggableStorageWrapper, IStorageAsyncFactory, IStorageFactoryParams, ITelemetryCacheAsync } from '../types';
|
|
1
|
+
import { IPluggableStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams, ITelemetryCacheAsync } from '../types';
|
|
2
2
|
|
|
3
3
|
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
4
4
|
import { SplitsCachePluggable } from './SplitsCachePluggable';
|
|
@@ -62,12 +62,11 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
62
62
|
|
|
63
63
|
const prefix = validatePrefix(options.prefix);
|
|
64
64
|
|
|
65
|
-
function PluggableStorageFactory(params: IStorageFactoryParams) {
|
|
65
|
+
function PluggableStorageFactory(params: IStorageFactoryParams): IStorageAsync {
|
|
66
66
|
const { onReadyCb, settings, settings: { log, mode, sync: { impressionsMode }, scheduler: { impressionsQueueSize, eventsQueueSize } } } = params;
|
|
67
67
|
const metadata = metadataBuilder(settings);
|
|
68
68
|
const keys = new KeyBuilderSS(prefix, metadata);
|
|
69
69
|
const wrapper = wrapperAdapter(log, options.wrapper);
|
|
70
|
-
let connectPromise: Promise<void>;
|
|
71
70
|
|
|
72
71
|
const isSyncronizer = mode === undefined; // If mode is not defined, the synchronizer is running
|
|
73
72
|
const isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
|
|
@@ -90,6 +89,35 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
90
89
|
new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
|
|
91
90
|
undefined;
|
|
92
91
|
|
|
92
|
+
// Connects to wrapper and emits SDK_READY event on main client
|
|
93
|
+
const connectPromise = wrapper.connect().then(() => {
|
|
94
|
+
if (isSyncronizer) {
|
|
95
|
+
// In standalone or producer mode, clear storage if SDK key or feature flag filter has changed
|
|
96
|
+
return wrapper.get(keys.buildHashKey()).then((hash) => {
|
|
97
|
+
const currentHash = getStorageHash(settings);
|
|
98
|
+
if (hash !== currentHash) {
|
|
99
|
+
log.info(LOG_PREFIX + 'Storage HASH has changed (SDK key, flags filter criteria or flags spec version was modified). Clearing cache');
|
|
100
|
+
return wrapper.getKeysByPrefix(`${keys.prefix}.`).then(storageKeys => {
|
|
101
|
+
return Promise.all(storageKeys.map(storageKey => wrapper.del(storageKey)));
|
|
102
|
+
}).then(() => wrapper.set(keys.buildHashKey(), currentHash));
|
|
103
|
+
}
|
|
104
|
+
}).then(() => {
|
|
105
|
+
onReadyCb();
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
// Start periodic flush of async storages if not running synchronizer (producer mode)
|
|
109
|
+
if (impressionCountsCache && (impressionCountsCache as ImpressionCountsCachePluggable).start) (impressionCountsCache as ImpressionCountsCachePluggable).start();
|
|
110
|
+
if (uniqueKeysCache && (uniqueKeysCache as UniqueKeysCachePluggable).start) (uniqueKeysCache as UniqueKeysCachePluggable).start();
|
|
111
|
+
if (telemetry && (telemetry as ITelemetryCacheAsync).recordConfig) (telemetry as ITelemetryCacheAsync).recordConfig();
|
|
112
|
+
|
|
113
|
+
onReadyCb();
|
|
114
|
+
}
|
|
115
|
+
}).catch((e) => {
|
|
116
|
+
e = e || new Error('Error connecting wrapper');
|
|
117
|
+
onReadyCb(e);
|
|
118
|
+
return e; // Propagate error for shared clients
|
|
119
|
+
});
|
|
120
|
+
|
|
93
121
|
return {
|
|
94
122
|
splits: new SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
95
123
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
@@ -99,39 +127,6 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
99
127
|
telemetry,
|
|
100
128
|
uniqueKeys: uniqueKeysCache,
|
|
101
129
|
|
|
102
|
-
init() {
|
|
103
|
-
if (connectPromise) return connectPromise;
|
|
104
|
-
|
|
105
|
-
// Connects to wrapper and emits SDK_READY event on main client
|
|
106
|
-
return connectPromise = wrapper.connect().then(() => {
|
|
107
|
-
if (isSyncronizer) {
|
|
108
|
-
// In standalone or producer mode, clear storage if SDK key or feature flag filter has changed
|
|
109
|
-
return wrapper.get(keys.buildHashKey()).then((hash) => {
|
|
110
|
-
const currentHash = getStorageHash(settings);
|
|
111
|
-
if (hash !== currentHash) {
|
|
112
|
-
log.info(LOG_PREFIX + 'Storage HASH has changed (SDK key, flags filter criteria or flags spec version was modified). Clearing cache');
|
|
113
|
-
return wrapper.getKeysByPrefix(`${keys.prefix}.`).then(storageKeys => {
|
|
114
|
-
return Promise.all(storageKeys.map(storageKey => wrapper.del(storageKey)));
|
|
115
|
-
}).then(() => wrapper.set(keys.buildHashKey(), currentHash));
|
|
116
|
-
}
|
|
117
|
-
}).then(() => {
|
|
118
|
-
onReadyCb();
|
|
119
|
-
});
|
|
120
|
-
} else {
|
|
121
|
-
// Start periodic flush of async storages if not running synchronizer (producer mode)
|
|
122
|
-
if (impressionCountsCache && (impressionCountsCache as ImpressionCountsCachePluggable).start) (impressionCountsCache as ImpressionCountsCachePluggable).start();
|
|
123
|
-
if (uniqueKeysCache && (uniqueKeysCache as UniqueKeysCachePluggable).start) (uniqueKeysCache as UniqueKeysCachePluggable).start();
|
|
124
|
-
if (telemetry && (telemetry as ITelemetryCacheAsync).recordConfig) (telemetry as ITelemetryCacheAsync).recordConfig();
|
|
125
|
-
|
|
126
|
-
onReadyCb();
|
|
127
|
-
}
|
|
128
|
-
}).catch((e) => {
|
|
129
|
-
e = e || new Error('Error connecting wrapper');
|
|
130
|
-
onReadyCb(e);
|
|
131
|
-
return e; // Propagate error for shared clients
|
|
132
|
-
});
|
|
133
|
-
},
|
|
134
|
-
|
|
135
130
|
// Stop periodic flush and disconnect the underlying storage
|
|
136
131
|
destroy() {
|
|
137
132
|
return Promise.all(isSyncronizer ? [] : [
|
|
@@ -141,8 +136,8 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
141
136
|
},
|
|
142
137
|
|
|
143
138
|
// emits SDK_READY event on shared clients and returns a reference to the storage
|
|
144
|
-
shared(_
|
|
145
|
-
|
|
139
|
+
shared(_, onReadyCb) {
|
|
140
|
+
connectPromise.then(onReadyCb);
|
|
146
141
|
|
|
147
142
|
return {
|
|
148
143
|
...this,
|
package/src/storages/types.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { MaybeThenable, ISplit
|
|
2
|
-
import { MySegmentsData } from '../sync/polling/types';
|
|
1
|
+
import { MaybeThenable, ISplit } from '../dtos/types';
|
|
3
2
|
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, MultiMethodExceptions, MultiMethodLatencies, MultiConfigs, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
4
3
|
import { SplitIO, ImpressionDTO, ISettings } from '../types';
|
|
5
4
|
import { ISet } from '../utils/lang/sets';
|
|
@@ -205,9 +204,11 @@ export interface ISplitsCacheBase {
|
|
|
205
204
|
getSplitNames(): MaybeThenable<string[]>,
|
|
206
205
|
// should never reject or throw an exception. Instead return true by default, asssuming the TT might exist.
|
|
207
206
|
trafficTypeExists(trafficType: string): MaybeThenable<boolean>,
|
|
208
|
-
// only for Client-Side
|
|
207
|
+
// only for Client-Side
|
|
209
208
|
usesSegments(): MaybeThenable<boolean>,
|
|
210
209
|
clear(): MaybeThenable<boolean | void>,
|
|
210
|
+
// should never reject or throw an exception. Instead return false by default, to avoid emitting SDK_READY_FROM_CACHE.
|
|
211
|
+
checkCache(): MaybeThenable<boolean>,
|
|
211
212
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): MaybeThenable<boolean>,
|
|
212
213
|
getNamesByFlagSets(flagSets: string[]): MaybeThenable<ISet<string>[]>
|
|
213
214
|
}
|
|
@@ -217,13 +218,14 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
|
|
|
217
218
|
removeSplits(names: string[]): boolean[],
|
|
218
219
|
getSplit(name: string): ISplit | null,
|
|
219
220
|
getSplits(names: string[]): Record<string, ISplit | null>,
|
|
220
|
-
setChangeNumber(changeNumber: number): boolean
|
|
221
|
+
setChangeNumber(changeNumber: number): boolean,
|
|
221
222
|
getChangeNumber(): number,
|
|
222
223
|
getAll(): ISplit[],
|
|
223
224
|
getSplitNames(): string[],
|
|
224
225
|
trafficTypeExists(trafficType: string): boolean,
|
|
225
226
|
usesSegments(): boolean,
|
|
226
227
|
clear(): void,
|
|
228
|
+
checkCache(): boolean,
|
|
227
229
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean,
|
|
228
230
|
getNamesByFlagSets(flagSets: string[]): ISet<string>[]
|
|
229
231
|
}
|
|
@@ -240,6 +242,7 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
|
|
|
240
242
|
trafficTypeExists(trafficType: string): Promise<boolean>,
|
|
241
243
|
usesSegments(): Promise<boolean>,
|
|
242
244
|
clear(): Promise<boolean | void>,
|
|
245
|
+
checkCache(): Promise<boolean>,
|
|
243
246
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>,
|
|
244
247
|
getNamesByFlagSets(flagSets: string[]): Promise<ISet<string>[]>
|
|
245
248
|
}
|
|
@@ -253,7 +256,7 @@ export interface ISegmentsCacheBase {
|
|
|
253
256
|
registerSegments(names: string[]): MaybeThenable<boolean | void> // only for Server-Side
|
|
254
257
|
getRegisteredSegments(): MaybeThenable<string[]> // only for Server-Side
|
|
255
258
|
setChangeNumber(name: string, changeNumber: number): MaybeThenable<boolean | void> // only for Server-Side
|
|
256
|
-
getChangeNumber(name: string): MaybeThenable<number> // only for Server-Side
|
|
259
|
+
getChangeNumber(name: string): MaybeThenable<number | undefined> // only for Server-Side
|
|
257
260
|
clear(): MaybeThenable<boolean | void>
|
|
258
261
|
}
|
|
259
262
|
|
|
@@ -265,9 +268,9 @@ export interface ISegmentsCacheSync extends ISegmentsCacheBase {
|
|
|
265
268
|
registerSegments(names: string[]): boolean
|
|
266
269
|
getRegisteredSegments(): string[]
|
|
267
270
|
getKeysCount(): number // only used for telemetry
|
|
268
|
-
setChangeNumber(name: string, changeNumber: number): boolean
|
|
269
|
-
getChangeNumber(name
|
|
270
|
-
resetSegments(
|
|
271
|
+
setChangeNumber(name: string, changeNumber: number): boolean
|
|
272
|
+
getChangeNumber(name: string): number | undefined
|
|
273
|
+
resetSegments(names: string[]): boolean // only for Sync Client-Side
|
|
271
274
|
clear(): void
|
|
272
275
|
}
|
|
273
276
|
|
|
@@ -278,7 +281,7 @@ export interface ISegmentsCacheAsync extends ISegmentsCacheBase {
|
|
|
278
281
|
registerSegments(names: string[]): Promise<boolean | void>
|
|
279
282
|
getRegisteredSegments(): Promise<string[]>
|
|
280
283
|
setChangeNumber(name: string, changeNumber: number): Promise<boolean | void>
|
|
281
|
-
getChangeNumber(name: string): Promise<number>
|
|
284
|
+
getChangeNumber(name: string): Promise<number | undefined>
|
|
282
285
|
clear(): Promise<boolean | void>
|
|
283
286
|
}
|
|
284
287
|
|
|
@@ -462,7 +465,6 @@ export interface IStorageBase<
|
|
|
462
465
|
events: TEventsCache,
|
|
463
466
|
telemetry?: TTelemetryCache,
|
|
464
467
|
uniqueKeys?: TUniqueKeysCache,
|
|
465
|
-
init?: () => void | Promise<void>,
|
|
466
468
|
destroy(): void | Promise<void>,
|
|
467
469
|
shared?: (matchingKey: string, onReadyCb: (error?: any) => void) => this
|
|
468
470
|
}
|
|
@@ -475,10 +477,7 @@ export interface IStorageSync extends IStorageBase<
|
|
|
475
477
|
IEventsCacheSync,
|
|
476
478
|
ITelemetryCacheSync,
|
|
477
479
|
IUniqueKeysCacheSync
|
|
478
|
-
> {
|
|
479
|
-
// Defined in client-side
|
|
480
|
-
largeSegments?: ISegmentsCacheSync,
|
|
481
|
-
}
|
|
480
|
+
> { }
|
|
482
481
|
|
|
483
482
|
export interface IStorageAsync extends IStorageBase<
|
|
484
483
|
ISplitsCacheAsync,
|
|
@@ -492,6 +491,8 @@ export interface IStorageAsync extends IStorageBase<
|
|
|
492
491
|
|
|
493
492
|
/** StorageFactory */
|
|
494
493
|
|
|
494
|
+
export type DataLoader = (storage: IStorageSync, matchingKey: string) => void
|
|
495
|
+
|
|
495
496
|
export interface IStorageFactoryParams {
|
|
496
497
|
settings: ISettings,
|
|
497
498
|
/**
|
|
@@ -499,7 +500,6 @@ export interface IStorageFactoryParams {
|
|
|
499
500
|
* It is meant for emitting SDK_READY event in consumer mode, and waiting before using the storage in the synchronizer.
|
|
500
501
|
*/
|
|
501
502
|
onReadyCb: (error?: any) => void,
|
|
502
|
-
onReadyFromCacheCb: (error?: any) => void,
|
|
503
503
|
}
|
|
504
504
|
|
|
505
505
|
export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';
|