@splitsoftware/splitio-commons 2.12.0 → 3.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +14 -1
- package/cjs/evaluator/condition/engineUtils.js +2 -2
- package/cjs/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.js +70 -0
- package/cjs/evaluator/fallbackConfigsCalculator/index.js +25 -0
- package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
- package/cjs/evaluator/fallbackTreatmentsCalculator/index.js +21 -32
- package/cjs/evaluator/index.js +67 -42
- package/cjs/evaluator/matchers/whitelist.js +1 -1
- package/cjs/integrations/pluggable.js +1 -1
- package/cjs/listeners/browser.js +4 -3
- package/cjs/listeners/node.js +4 -4
- package/cjs/logger/constants.js +14 -20
- package/cjs/logger/index.js +1 -1
- package/cjs/logger/messages/debug.js +6 -7
- package/cjs/logger/messages/error.js +4 -4
- package/cjs/logger/messages/info.js +2 -4
- package/cjs/logger/messages/warn.js +9 -9
- package/cjs/platform/browser.js +15 -0
- package/cjs/platform/getEventSource/browser.js +8 -0
- package/cjs/platform/getEventSource/eventsource.js +480 -0
- package/cjs/platform/getEventSource/node.js +26 -0
- package/cjs/platform/getFetch/browser.js +9 -0
- package/cjs/platform/getFetch/node.js +27 -0
- package/cjs/platform/getOptions/node.js +25 -0
- package/cjs/platform/node.js +17 -0
- package/cjs/readiness/constants.js +2 -1
- package/cjs/sdkClient/client.js +9 -35
- package/cjs/sdkClient/clientAttributesDecoration.js +3 -3
- package/cjs/sdkClient/clientInputValidation.js +38 -81
- package/cjs/sdkClient/identity.js +1 -1
- package/cjs/sdkClient/sdkClient.js +4 -49
- package/cjs/sdkClient/sdkLifecycle.js +70 -0
- package/cjs/sdkClient/trackMethod.js +56 -0
- package/cjs/sdkFactory/index.js +8 -45
- package/cjs/sdkManager/index.js +3 -3
- package/cjs/services/splitApi.js +18 -13
- package/cjs/services/splitHttpClient.js +1 -1
- package/cjs/storages/AbstractSplitsCacheAsync.js +1 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
- package/cjs/storages/KeyBuilder.js +12 -12
- package/cjs/storages/KeyBuilderCS.js +13 -13
- package/cjs/storages/KeyBuilderSS.js +15 -15
- package/cjs/storages/getRolloutPlan.js +1 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +1 -1
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +1 -1
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +1 -1
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +2 -2
- package/cjs/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +5 -5
- package/cjs/storages/inRedis/ImpressionsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RedisAdapter.js +8 -8
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +6 -6
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +7 -7
- package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +3 -3
- package/cjs/storages/pluggable/EventsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +6 -6
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/SplitsCachePluggable.js +4 -4
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +7 -7
- package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +2 -2
- package/cjs/storages/pluggable/index.js +3 -3
- package/cjs/storages/pluggable/wrapperAdapter.js +1 -1
- package/cjs/storages/setRolloutPlan.js +1 -1
- package/cjs/storages/utils.js +6 -6
- package/cjs/sync/offline/splitsParser/parseCondition.js +1 -1
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +23 -14
- package/cjs/sync/polling/pollingManagerCS.js +11 -11
- package/cjs/sync/polling/pollingManagerSS.js +13 -13
- package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +12 -0
- package/cjs/sync/polling/updaters/{splitChangesUpdater.js → definitionChangesUpdater.js} +67 -59
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +1 -1
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +6 -6
- package/cjs/sync/streaming/SSEClient/index.js +2 -2
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +2 -2
- package/cjs/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -2
- package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +4 -4
- package/cjs/sync/streaming/parseUtils.js +12 -12
- package/cjs/sync/streaming/pushManager.js +2 -2
- package/cjs/sync/submitters/impressionsSubmitter.js +6 -6
- package/cjs/sync/submitters/submitter.js +1 -1
- package/cjs/sync/syncManagerOnline.js +5 -2
- package/cjs/trackers/eventTracker.js +10 -12
- package/cjs/trackers/impressionObserver/buildKey.js +1 -1
- package/cjs/trackers/impressionsTracker.js +37 -20
- package/cjs/trackers/uniqueKeysTracker.js +1 -1
- package/cjs/utils/EventEmitter.js +391 -0
- package/cjs/utils/filter/bloomFilter.js +37 -0
- package/cjs/utils/inputValidation/apiKey.js +1 -1
- package/cjs/utils/inputValidation/attribute.js +2 -2
- package/cjs/utils/inputValidation/{split.js → definition.js} +10 -10
- package/cjs/utils/inputValidation/{splitExistence.js → definitionExistence.js} +6 -6
- package/cjs/utils/inputValidation/definitions.js +25 -0
- package/cjs/utils/inputValidation/eventProperties.js +1 -1
- package/cjs/utils/inputValidation/index.js +7 -7
- package/cjs/utils/inputValidation/isOperational.js +4 -4
- package/cjs/utils/inputValidation/target.js +22 -0
- package/cjs/utils/labels/index.js +3 -3
- package/cjs/utils/lang/index.js +1 -1
- package/cjs/utils/promise/timeout.js +1 -1
- package/cjs/utils/settingsValidation/splitFilters.js +4 -4
- package/cjs/utils/settingsValidation/url.js +5 -5
- package/esm/evaluator/condition/engineUtils.js +2 -2
- package/esm/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.js +64 -0
- package/esm/evaluator/fallbackConfigsCalculator/index.js +21 -0
- package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
- package/esm/evaluator/fallbackTreatmentsCalculator/index.js +21 -33
- package/esm/evaluator/index.js +66 -42
- package/esm/evaluator/matchers/whitelist.js +1 -1
- package/esm/integrations/pluggable.js +1 -1
- package/esm/listeners/browser.js +4 -3
- package/esm/listeners/node.js +4 -4
- package/esm/logger/constants.js +11 -17
- package/esm/logger/index.js +1 -1
- package/esm/logger/messages/debug.js +5 -6
- package/esm/logger/messages/error.js +3 -3
- package/esm/logger/messages/info.js +1 -3
- package/esm/logger/messages/warn.js +8 -8
- package/esm/platform/browser.js +12 -0
- package/esm/platform/getEventSource/browser.js +4 -0
- package/esm/platform/getEventSource/eventsource.js +480 -0
- package/esm/platform/getEventSource/node.js +20 -0
- package/esm/platform/getFetch/browser.js +5 -0
- package/esm/platform/getFetch/node.js +22 -0
- package/esm/platform/getOptions/node.js +20 -0
- package/esm/platform/node.js +14 -0
- package/esm/readiness/constants.js +1 -0
- package/esm/sdkClient/client.js +10 -37
- package/esm/sdkClient/clientAttributesDecoration.js +3 -3
- package/esm/sdkClient/clientInputValidation.js +40 -83
- package/esm/sdkClient/identity.js +1 -1
- package/esm/sdkClient/sdkClient.js +4 -49
- package/esm/sdkClient/sdkLifecycle.js +66 -0
- package/esm/sdkClient/trackMethod.js +52 -0
- package/esm/sdkFactory/index.js +8 -45
- package/esm/sdkManager/index.js +4 -4
- package/esm/services/splitApi.js +18 -13
- package/esm/services/splitHttpClient.js +1 -1
- package/esm/storages/AbstractSplitsCacheAsync.js +1 -1
- package/esm/storages/AbstractSplitsCacheSync.js +1 -1
- package/esm/storages/KeyBuilder.js +12 -12
- package/esm/storages/KeyBuilderCS.js +12 -12
- package/esm/storages/KeyBuilderSS.js +14 -14
- package/esm/storages/getRolloutPlan.js +1 -1
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +1 -1
- package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +2 -2
- package/esm/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +4 -4
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/RedisAdapter.js +7 -7
- package/esm/storages/inRedis/SplitsCacheInRedis.js +4 -4
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +7 -7
- package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +1 -1
- package/esm/storages/pluggable/EventsCachePluggable.js +1 -1
- package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +5 -5
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/esm/storages/pluggable/SplitsCachePluggable.js +2 -2
- package/esm/storages/pluggable/TelemetryCachePluggable.js +7 -7
- package/esm/storages/pluggable/UniqueKeysCachePluggable.js +1 -1
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/storages/pluggable/wrapperAdapter.js +1 -1
- package/esm/storages/setRolloutPlan.js +1 -1
- package/esm/storages/utils.js +6 -6
- package/esm/sync/offline/splitsParser/parseCondition.js +1 -1
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +24 -15
- package/esm/sync/polling/pollingManagerCS.js +11 -11
- package/esm/sync/polling/pollingManagerSS.js +13 -13
- package/esm/sync/polling/syncTasks/definitionsSyncTask.js +8 -0
- package/esm/sync/polling/updaters/{splitChangesUpdater.js → definitionChangesUpdater.js} +67 -59
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +7 -7
- package/esm/sync/streaming/SSEClient/index.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +4 -4
- package/esm/sync/streaming/parseUtils.js +10 -10
- package/esm/sync/streaming/pushManager.js +3 -3
- package/esm/sync/submitters/impressionsSubmitter.js +6 -6
- package/esm/sync/submitters/submitter.js +1 -1
- package/esm/sync/syncManagerOnline.js +5 -2
- package/esm/trackers/eventTracker.js +10 -12
- package/esm/trackers/impressionObserver/buildKey.js +1 -1
- package/esm/trackers/impressionsTracker.js +38 -21
- package/esm/trackers/uniqueKeysTracker.js +1 -1
- package/esm/utils/EventEmitter.js +387 -0
- package/esm/utils/filter/bloomFilter.js +33 -0
- package/esm/utils/inputValidation/apiKey.js +1 -1
- package/esm/utils/inputValidation/attribute.js +2 -2
- package/esm/utils/inputValidation/{split.js → definition.js} +8 -8
- package/esm/utils/inputValidation/definitionExistence.js +15 -0
- package/esm/utils/inputValidation/definitions.js +21 -0
- package/esm/utils/inputValidation/index.js +3 -3
- package/esm/utils/inputValidation/isOperational.js +4 -4
- package/esm/utils/inputValidation/target.js +18 -0
- package/esm/utils/labels/index.js +2 -2
- package/esm/utils/promise/timeout.js +1 -1
- package/esm/utils/settingsValidation/splitFilters.js +4 -4
- package/esm/utils/settingsValidation/url.js +5 -5
- package/package.json +15 -6
- package/src/dtos/types.ts +65 -70
- package/src/evaluator/Engine.ts +4 -4
- package/src/evaluator/combiners/and.ts +3 -3
- package/src/evaluator/combiners/ifelseif.ts +2 -2
- package/src/evaluator/condition/engineUtils.ts +2 -2
- package/src/evaluator/condition/index.ts +3 -3
- package/src/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.ts +76 -0
- package/src/evaluator/fallbackConfigsCalculator/index.ts +24 -0
- package/src/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.ts +5 -7
- package/src/evaluator/fallbackTreatmentsCalculator/index.ts +27 -41
- package/src/evaluator/index.ts +80 -45
- package/src/evaluator/matchers/dependency.ts +2 -2
- package/src/evaluator/matchers/matcherTypes.ts +2 -2
- package/src/evaluator/matchers/prerequisites.ts +4 -4
- package/src/evaluator/matchers/rbsegment.ts +2 -2
- package/src/evaluator/matchers/whitelist.ts +2 -2
- package/src/evaluator/matchersTransform/index.ts +2 -2
- package/src/evaluator/matchersTransform/whitelist.ts +2 -2
- package/src/evaluator/parser/index.ts +4 -4
- package/src/evaluator/treatments/index.ts +2 -2
- package/src/evaluator/types.ts +6 -6
- package/src/evaluator/value/index.ts +1 -1
- package/src/integrations/pluggable.ts +1 -1
- package/src/listeners/browser.ts +11 -8
- package/src/listeners/node.ts +2 -5
- package/src/logger/constants.ts +11 -17
- package/src/logger/messages/debug.ts +5 -6
- package/src/logger/messages/error.ts +3 -3
- package/src/logger/messages/info.ts +1 -3
- package/src/logger/messages/warn.ts +8 -8
- package/src/platform/browser.ts +14 -0
- package/src/platform/getEventSource/browser.ts +4 -0
- package/src/platform/getEventSource/eventsource.js +519 -0
- package/src/platform/getEventSource/node.ts +23 -0
- package/src/platform/getFetch/browser.ts +5 -0
- package/src/platform/getFetch/node.ts +27 -0
- package/src/platform/getOptions/node.ts +24 -0
- package/src/platform/node.ts +16 -0
- package/src/readiness/constants.ts +1 -0
- package/src/sdkClient/client.ts +11 -41
- package/src/sdkClient/clientInputValidation.ts +44 -84
- package/src/sdkClient/sdkClient.ts +5 -54
- package/src/sdkClient/sdkLifecycle.ts +78 -0
- package/src/sdkClient/trackMethod.ts +59 -0
- package/src/sdkFactory/index.ts +10 -54
- package/src/sdkFactory/types.ts +19 -16
- package/src/sdkManager/index.ts +9 -9
- package/src/services/splitApi.ts +6 -0
- package/src/services/types.ts +3 -2
- package/src/storages/AbstractSplitsCacheAsync.ts +7 -7
- package/src/storages/AbstractSplitsCacheSync.ts +10 -10
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +2 -2
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +6 -6
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +2 -2
- package/src/storages/inMemory/SplitsCacheInMemory.ts +5 -5
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +2 -2
- package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +2 -2
- package/src/storages/inRedis/SplitsCacheInRedis.ts +9 -9
- package/src/storages/pluggable/RBSegmentsCachePluggable.ts +2 -2
- package/src/storages/pluggable/SplitsCachePluggable.ts +9 -9
- package/src/storages/types.ts +21 -16
- package/src/sync/offline/splitsParser/parseCondition.ts +2 -2
- package/src/sync/offline/splitsParser/splitsParserFromSettings.ts +3 -3
- package/src/sync/offline/splitsParser/types.ts +6 -3
- package/src/sync/offline/syncManagerOffline.ts +2 -2
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +6 -6
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +57 -22
- package/src/sync/polling/fetchers/types.ts +5 -3
- package/src/sync/polling/pollingManagerCS.ts +12 -10
- package/src/sync/polling/pollingManagerSS.ts +15 -13
- package/src/sync/polling/syncTasks/{splitsSyncTask.ts → definitionsSyncTask.ts} +10 -11
- package/src/sync/polling/types.ts +3 -3
- package/src/sync/polling/updaters/{splitChangesUpdater.ts → definitionChangesUpdater.ts} +77 -68
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -2
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +7 -7
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +6 -6
- package/src/sync/streaming/parseUtils.ts +12 -12
- package/src/sync/streaming/pushManager.ts +3 -3
- package/src/sync/submitters/impressionsSubmitter.ts +9 -9
- package/src/sync/submitters/types.ts +3 -0
- package/src/sync/syncManagerOnline.ts +6 -2
- package/src/trackers/eventTracker.ts +7 -10
- package/src/trackers/impressionsTracker.ts +42 -26
- package/src/trackers/types.ts +3 -1
- package/src/utils/EventEmitter.js +444 -0
- package/src/utils/filter/bloomFilter.ts +38 -0
- package/src/utils/inputValidation/definition.ts +27 -0
- package/src/utils/inputValidation/definitionExistence.ts +19 -0
- package/src/utils/inputValidation/definitions.ts +21 -0
- package/src/utils/inputValidation/index.ts +3 -3
- package/src/utils/inputValidation/isOperational.ts +4 -4
- package/src/utils/inputValidation/target.ts +21 -0
- package/src/utils/labels/index.ts +2 -2
- package/src/utils/settingsValidation/splitFilters.ts +3 -3
- package/types/splitio.d.ts +202 -9
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +0 -13
- package/cjs/utils/inputValidation/splits.js +0 -25
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +0 -9
- package/esm/utils/inputValidation/splitExistence.js +0 -15
- package/esm/utils/inputValidation/splits.js +0 -21
- package/src/utils/inputValidation/split.ts +0 -27
- package/src/utils/inputValidation/splitExistence.ts +0 -19
- package/src/utils/inputValidation/splits.ts +0 -21
package/src/sdkFactory/index.ts
CHANGED
|
@@ -4,16 +4,10 @@ import { impressionsTrackerFactory } from '../trackers/impressionsTracker';
|
|
|
4
4
|
import { eventTrackerFactory } from '../trackers/eventTracker';
|
|
5
5
|
import { telemetryTrackerFactory } from '../trackers/telemetryTracker';
|
|
6
6
|
import SplitIO from '../../types/splitio';
|
|
7
|
-
import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey';
|
|
8
7
|
import { createLoggerAPI } from '../logger/sdkLogger';
|
|
9
8
|
import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
10
9
|
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../readiness/constants';
|
|
11
10
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
12
|
-
import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
|
|
13
|
-
import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized';
|
|
14
|
-
import { strategyNoneFactory } from '../trackers/strategy/strategyNone';
|
|
15
|
-
import { uniqueKeysTrackerFactory } from '../trackers/uniqueKeysTracker';
|
|
16
|
-
import { DEBUG, OPTIMIZED } from '../utils/constants';
|
|
17
11
|
import { setRolloutPlan } from '../storages/setRolloutPlan';
|
|
18
12
|
import { IStorageSync } from '../storages/types';
|
|
19
13
|
import { getMatching } from '../utils/key';
|
|
@@ -24,24 +18,13 @@ import { FallbackTreatmentsCalculator } from '../evaluator/fallbackTreatmentsCal
|
|
|
24
18
|
*/
|
|
25
19
|
export function sdkFactory(params: ISdkFactoryParams): SplitIO.ISDK | SplitIO.IAsyncSDK | SplitIO.IBrowserSDK | SplitIO.IBrowserAsyncSDK {
|
|
26
20
|
|
|
27
|
-
const { settings, platform, storageFactory, splitApiFactory, extraProps,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
filterAdapterFactory, lazyInit } = params;
|
|
31
|
-
const { log, sync: { impressionsMode }, initialRolloutPlan, core: { key } } = settings;
|
|
21
|
+
const { settings, platform, storageFactory, splitApiFactory, extraProps, syncManagerFactory,
|
|
22
|
+
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory, lazyInit } = params;
|
|
23
|
+
const { log, initialRolloutPlan, core: { key } } = settings;
|
|
32
24
|
|
|
33
25
|
// @TODO handle non-recoverable errors, such as, global `fetch` not available, invalid SDK Key, etc.
|
|
34
26
|
// On non-recoverable errors, we should mark the SDK as destroyed and not start synchronization.
|
|
35
27
|
|
|
36
|
-
// initialization
|
|
37
|
-
let hasInit = false;
|
|
38
|
-
const initCallbacks: (() => void)[] = [];
|
|
39
|
-
|
|
40
|
-
function whenInit(cb: () => void) {
|
|
41
|
-
if (hasInit) cb();
|
|
42
|
-
else initCallbacks.push(cb);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
28
|
const sdkReadinessManager = sdkReadinessManagerFactory(platform.EventEmitter, settings);
|
|
46
29
|
const readiness = sdkReadinessManager.readinessManager;
|
|
47
30
|
|
|
@@ -61,40 +44,25 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ISDK | SplitIO.IA
|
|
|
61
44
|
}
|
|
62
45
|
});
|
|
63
46
|
|
|
64
|
-
const
|
|
47
|
+
const fallbackCalculator = FallbackTreatmentsCalculator(settings.fallbackTreatments);
|
|
65
48
|
|
|
66
49
|
if (initialRolloutPlan) {
|
|
67
50
|
setRolloutPlan(log, initialRolloutPlan, storage as IStorageSync, key && getMatching(key));
|
|
68
51
|
if ((storage as IStorageSync).splits.getChangeNumber() > -1) readiness.splits.emit(SDK_SPLITS_CACHE_LOADED, { initialCacheLoad: false /* Not an initial load, cache exists */ });
|
|
69
52
|
}
|
|
70
53
|
|
|
71
|
-
const clients: Record<string, SplitIO.IBasicClient> = {};
|
|
54
|
+
const clients: Record<string, SplitIO.IBasicClient & { init: () => void }> = {};
|
|
72
55
|
const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
73
56
|
const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage, telemetryTracker });
|
|
74
57
|
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const noneStrategy = strategyNoneFactory(storage.impressionCounts, uniqueKeysTracker);
|
|
79
|
-
const strategy = impressionsMode === OPTIMIZED ?
|
|
80
|
-
strategyOptimizedFactory(observer, storage.impressionCounts) :
|
|
81
|
-
impressionsMode === DEBUG ?
|
|
82
|
-
strategyDebugFactory(observer) :
|
|
83
|
-
noneStrategy;
|
|
84
|
-
|
|
85
|
-
const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, noneStrategy, strategy, whenInit, integrationsManager, storage.telemetry);
|
|
86
|
-
const eventTracker = eventTrackerFactory(settings, storage.events, whenInit, integrationsManager, storage.telemetry);
|
|
58
|
+
const impressionsTracker = impressionsTrackerFactory(params, storage, integrationsManager);
|
|
59
|
+
const eventTracker = eventTrackerFactory(settings, storage.events, integrationsManager, storage.telemetry);
|
|
87
60
|
|
|
88
61
|
// splitApi is used by SyncManager and Browser signal listener
|
|
89
62
|
const splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
|
|
90
63
|
|
|
91
|
-
const ctx: ISdkFactoryContext = { clients, splitApi, eventTracker, impressionsTracker, telemetryTracker,
|
|
92
|
-
|
|
93
|
-
const syncManager = syncManagerFactory && syncManagerFactory(ctx as ISdkFactoryContextSync);
|
|
94
|
-
ctx.syncManager = syncManager;
|
|
95
|
-
|
|
96
|
-
const signalListener = SignalListener && new SignalListener(syncManager, settings, storage, splitApi);
|
|
97
|
-
ctx.signalListener = signalListener;
|
|
64
|
+
const ctx: ISdkFactoryContext = { clients, splitApi, eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, readiness, settings, storage, platform, fallbackCalculator };
|
|
65
|
+
ctx.syncManager = syncManagerFactory && syncManagerFactory(ctx as ISdkFactoryContextSync);
|
|
98
66
|
|
|
99
67
|
// SDK client and manager
|
|
100
68
|
const clientMethod = sdkClientMethodFactory(ctx);
|
|
@@ -102,18 +70,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ISDK | SplitIO.IA
|
|
|
102
70
|
|
|
103
71
|
|
|
104
72
|
function init() {
|
|
105
|
-
|
|
106
|
-
hasInit = true;
|
|
107
|
-
|
|
108
|
-
// We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
|
|
109
|
-
validateAndTrackApiKey(log, settings.core.authorizationKey);
|
|
110
|
-
readiness.init();
|
|
111
|
-
uniqueKeysTracker.start();
|
|
112
|
-
syncManager && syncManager.start();
|
|
113
|
-
signalListener && signalListener.start();
|
|
114
|
-
|
|
115
|
-
initCallbacks.forEach((cb) => cb());
|
|
116
|
-
initCallbacks.length = 0;
|
|
73
|
+
Object.keys(clients).map(key => clients[key].init());
|
|
117
74
|
}
|
|
118
75
|
|
|
119
76
|
log.info(NEW_FACTORY, [settings.version]);
|
|
@@ -135,7 +92,6 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ISDK | SplitIO.IA
|
|
|
135
92
|
settings,
|
|
136
93
|
|
|
137
94
|
destroy() {
|
|
138
|
-
hasInit = false;
|
|
139
95
|
return Promise.all(Object.keys(clients).map(key => clients[key].destroy())).then(() => { });
|
|
140
96
|
}
|
|
141
97
|
}, extraProps && extraProps(ctx), lazyInit ? { init } : init());
|
package/src/sdkFactory/types.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { ISignalListener } from '../listeners/types';
|
|
|
3
3
|
import { IReadinessManager, ISdkReadinessManager } from '../readiness/types';
|
|
4
4
|
import type { sdkManagerFactory } from '../sdkManager';
|
|
5
5
|
import type { splitApiFactory } from '../services/splitApi';
|
|
6
|
-
import type {
|
|
6
|
+
import type { IFallbackCalculator } from '../evaluator/fallbackTreatmentsCalculator';
|
|
7
7
|
import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
|
|
8
8
|
import { IStorageAsync, IStorageSync, IStorageFactoryParams } from '../storages/types';
|
|
9
9
|
import { ISyncManager } from '../sync/types';
|
|
10
10
|
import { IImpressionObserver } from '../trackers/impressionObserver/types';
|
|
11
|
-
import { IImpressionsTracker, IEventTracker, ITelemetryTracker, IFilterAdapter
|
|
11
|
+
import { IImpressionsTracker, IEventTracker, ITelemetryTracker, IFilterAdapter } from '../trackers/types';
|
|
12
12
|
import { ISettings } from '../types';
|
|
13
13
|
import SplitIO from '../../types/splitio';
|
|
14
14
|
|
|
@@ -35,9 +35,17 @@ export interface IPlatform {
|
|
|
35
35
|
/**
|
|
36
36
|
* Function used to track latencies for telemetry.
|
|
37
37
|
*/
|
|
38
|
-
now?: () => number
|
|
38
|
+
now?: () => number,
|
|
39
|
+
/**
|
|
40
|
+
* Optional signal listener constructor. Used to listen and handle runtime environment states, like server shutdown, app paused or resumed.
|
|
41
|
+
*/
|
|
42
|
+
// eslint-disable-next-line no-use-before-define
|
|
43
|
+
SignalListener?: new (params: ISdkFactoryContext) => ISignalListener, // Used by BrowserSignalListener
|
|
39
44
|
}
|
|
40
45
|
|
|
46
|
+
// Definition type
|
|
47
|
+
export type EntityType = 'config' | 'flag';
|
|
48
|
+
|
|
41
49
|
export interface ISdkFactoryContext {
|
|
42
50
|
platform: IPlatform,
|
|
43
51
|
sdkReadinessManager: ISdkReadinessManager,
|
|
@@ -47,12 +55,11 @@ export interface ISdkFactoryContext {
|
|
|
47
55
|
eventTracker: IEventTracker,
|
|
48
56
|
telemetryTracker: ITelemetryTracker,
|
|
49
57
|
storage: IStorageSync | IStorageAsync,
|
|
50
|
-
|
|
51
|
-
signalListener?: ISignalListener
|
|
52
|
-
splitApi?: ISplitApi
|
|
58
|
+
splitApi?: ISplitApi,
|
|
53
59
|
syncManager?: ISyncManager,
|
|
54
60
|
clients: Record<string, SplitIO.IBasicClient>,
|
|
55
|
-
|
|
61
|
+
fallbackCalculator: IFallbackCalculator,
|
|
62
|
+
entityType?: EntityType
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
export interface ISdkFactoryContextSync extends ISdkFactoryContext {
|
|
@@ -98,21 +105,17 @@ export interface ISdkFactoryParams {
|
|
|
98
105
|
|
|
99
106
|
// Sdk client method factory.
|
|
100
107
|
// It Allows to distinguish SDK clients with the client-side API (`IBrowserSDK` and `IBrowserAsyncSDK`) or server-side API (`ISDK` and `IAsyncSDK`).
|
|
101
|
-
sdkClientMethodFactory: (params: ISdkFactoryContext) => (
|
|
108
|
+
sdkClientMethodFactory: (params: ISdkFactoryContext) => (
|
|
109
|
+
{ (): SplitIO.IBrowserClient & { init(): void }; (key: SplitIO.SplitKey): SplitIO.IBrowserClient & { init(): void }; } |
|
|
110
|
+
(() => SplitIO.IClient & { init(): void }) |
|
|
111
|
+
(() => SplitIO.IAsyncClient & { init(): void })
|
|
112
|
+
)
|
|
102
113
|
|
|
103
114
|
// Impression observer factory.
|
|
104
115
|
impressionsObserverFactory: () => IImpressionObserver
|
|
105
116
|
|
|
106
117
|
filterAdapterFactory?: () => IFilterAdapter
|
|
107
118
|
|
|
108
|
-
// Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed.
|
|
109
|
-
// Pass only if `syncManager` (used by NodeSignalListener) and `splitApi` (used by Browser listener) are passed.
|
|
110
|
-
SignalListener?: new (
|
|
111
|
-
syncManager: ISyncManager | undefined, // Used by NodeSignalListener to flush data, and by BrowserSignalListener to close streaming connection.
|
|
112
|
-
settings: ISettings, // Used by BrowserSignalListener
|
|
113
|
-
storage: IStorageSync | IStorageAsync, // Used by BrowserSignalListener
|
|
114
|
-
serviceApi: ISplitApi | undefined) => ISignalListener, // Used by BrowserSignalListener
|
|
115
|
-
|
|
116
119
|
// @TODO review impressionListener and integrations interfaces. What about handling impressionListener as an integration ?
|
|
117
120
|
integrationsManagerFactory?: (params: IIntegrationFactoryParams) => IIntegrationManager | undefined,
|
|
118
121
|
|
package/src/sdkManager/index.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
3
|
import { find } from '../utils/lang';
|
|
4
|
-
import {
|
|
4
|
+
import { validateDefinition, validateDefinitionExistence, validateIfOperational } from '../utils/inputValidation';
|
|
5
5
|
import { ISplitsCacheAsync, ISplitsCacheSync } from '../storages/types';
|
|
6
6
|
import { ISdkReadinessManager } from '../readiness/types';
|
|
7
|
-
import {
|
|
7
|
+
import { IDefinition } from '../dtos/types';
|
|
8
8
|
import { ISettings } from '../types';
|
|
9
9
|
import SplitIO from '../../types/splitio';
|
|
10
10
|
import { isConsumerMode } from '../utils/settingsValidation/mode';
|
|
11
11
|
import { SPLIT_FN_LABEL, SPLITS_FN_LABEL, NAMES_FN_LABEL } from '../utils/constants';
|
|
12
12
|
|
|
13
|
-
function collectTreatments(splitObject:
|
|
13
|
+
function collectTreatments(splitObject: IDefinition) {
|
|
14
14
|
const conditions = splitObject.conditions;
|
|
15
15
|
// Rollout conditions are supposed to have the entire partitions list, so we find the first one.
|
|
16
16
|
let allTreatmentsCondition = find(conditions, (cond) => cond.conditionType === 'ROLLOUT');
|
|
@@ -20,7 +20,7 @@ function collectTreatments(splitObject: ISplit) {
|
|
|
20
20
|
return allTreatmentsCondition ? allTreatmentsCondition.partitions!.map(v => v.treatment) : [];
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function objectToView(splitObject:
|
|
23
|
+
function objectToView(splitObject: IDefinition | null): SplitIO.SplitView | null {
|
|
24
24
|
if (!splitObject) return null;
|
|
25
25
|
|
|
26
26
|
return {
|
|
@@ -29,7 +29,7 @@ function objectToView(splitObject: ISplit | null): SplitIO.SplitView | null {
|
|
|
29
29
|
killed: splitObject.killed,
|
|
30
30
|
changeNumber: splitObject.changeNumber || 0,
|
|
31
31
|
treatments: collectTreatments(splitObject),
|
|
32
|
-
configs: splitObject.configurations || {},
|
|
32
|
+
configs: splitObject.configurations as SplitIO.SplitView['configs'] || {},
|
|
33
33
|
sets: splitObject.sets || [],
|
|
34
34
|
defaultTreatment: splitObject.defaultTreatment,
|
|
35
35
|
impressionsDisabled: splitObject.impressionsDisabled === true,
|
|
@@ -37,7 +37,7 @@ function objectToView(splitObject: ISplit | null): SplitIO.SplitView | null {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function objectsToViews(splitObjects:
|
|
40
|
+
function objectsToViews(splitObjects: IDefinition[]) {
|
|
41
41
|
let views: SplitIO.SplitView[] = [];
|
|
42
42
|
|
|
43
43
|
splitObjects.forEach(split => {
|
|
@@ -65,7 +65,7 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
|
|
|
65
65
|
* Get the feature flag object corresponding to the given feature flag name if valid
|
|
66
66
|
*/
|
|
67
67
|
split(featureFlagName: string) {
|
|
68
|
-
const splitName =
|
|
68
|
+
const splitName = validateDefinition(log, featureFlagName, SPLIT_FN_LABEL);
|
|
69
69
|
if (!validateIfOperational(log, readinessManager, SPLIT_FN_LABEL) || !splitName) {
|
|
70
70
|
return isAsync ? Promise.resolve(null) : null;
|
|
71
71
|
}
|
|
@@ -74,12 +74,12 @@ export function sdkManagerFactory<TSplitCache extends ISplitsCacheSync | ISplits
|
|
|
74
74
|
|
|
75
75
|
if (thenable(split)) {
|
|
76
76
|
return split.catch(() => null).then(result => { // handle possible rejections when using pluggable storage
|
|
77
|
-
|
|
77
|
+
validateDefinitionExistence(log, readinessManager, splitName, result, SPLIT_FN_LABEL);
|
|
78
78
|
return objectToView(result);
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
validateDefinitionExistence(log, readinessManager, splitName, split, SPLIT_FN_LABEL);
|
|
83
83
|
|
|
84
84
|
return objectToView(split);
|
|
85
85
|
},
|
package/src/services/splitApi.ts
CHANGED
|
@@ -61,6 +61,12 @@ export function splitApiFactory(
|
|
|
61
61
|
});
|
|
62
62
|
},
|
|
63
63
|
|
|
64
|
+
// @TODO support filterQueryString and handle ERROR_TOO_MANY_SETS error
|
|
65
|
+
fetchConfigs(since: number, noCache?: boolean, till?: number) {
|
|
66
|
+
const url = `${urls.sdk}/v1/configs?since=${since}${filterQueryString || ''}${till ? '&till=' + till : ''}`;
|
|
67
|
+
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined);
|
|
68
|
+
},
|
|
69
|
+
|
|
64
70
|
fetchSegmentChanges(since: number, segmentName: string, noCache?: boolean, till?: number) {
|
|
65
71
|
const url = `${urls.sdk}/segmentChanges/${segmentName}?since=${since}${till ? '&till=' + till : ''}`;
|
|
66
72
|
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SEGMENT));
|
package/src/services/types.ts
CHANGED
|
@@ -35,7 +35,7 @@ export type ISplitHttpClient = (url: string, options?: IRequestOptions, latencyT
|
|
|
35
35
|
|
|
36
36
|
export type IFetchAuth = (userKeys?: string[]) => Promise<IResponse>
|
|
37
37
|
|
|
38
|
-
export type
|
|
38
|
+
export type IFetchDefinitionChanges = (since: number, noCache?: boolean, till?: number, rbSince?: number) => Promise<IResponse>
|
|
39
39
|
|
|
40
40
|
export type IFetchSegmentChanges = (since: number, segmentName: string, noCache?: boolean, till?: number) => Promise<IResponse>
|
|
41
41
|
|
|
@@ -59,7 +59,8 @@ export interface ISplitApi {
|
|
|
59
59
|
getSdkAPIHealthCheck: IHealthCheckAPI
|
|
60
60
|
getEventsAPIHealthCheck: IHealthCheckAPI
|
|
61
61
|
fetchAuth: IFetchAuth
|
|
62
|
-
fetchSplitChanges:
|
|
62
|
+
fetchSplitChanges: IFetchDefinitionChanges
|
|
63
|
+
fetchConfigs: IFetchDefinitionChanges
|
|
63
64
|
fetchSegmentChanges: IFetchSegmentChanges
|
|
64
65
|
fetchMemberships: IFetchMemberships
|
|
65
66
|
postEventsBulk: IPostEventsBulk
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ISplitsCacheAsync } from './types';
|
|
2
|
-
import {
|
|
2
|
+
import { IDefinition } from '../dtos/types';
|
|
3
3
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -8,24 +8,24 @@ import { objectAssign } from '../utils/lang/objectAssign';
|
|
|
8
8
|
*/
|
|
9
9
|
export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
|
|
10
10
|
|
|
11
|
-
protected abstract addSplit(split:
|
|
11
|
+
protected abstract addSplit(split: IDefinition): Promise<boolean>
|
|
12
12
|
protected abstract removeSplit(name: string): Promise<boolean>
|
|
13
13
|
protected abstract setChangeNumber(changeNumber: number): Promise<boolean | void>
|
|
14
14
|
|
|
15
|
-
update(toAdd:
|
|
15
|
+
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): Promise<boolean> {
|
|
16
16
|
return Promise.all([
|
|
17
17
|
this.setChangeNumber(changeNumber),
|
|
18
18
|
Promise.all(toAdd.map(addedFF => this.addSplit(addedFF))),
|
|
19
|
-
Promise.all(toRemove.map(removedFF => this.removeSplit(removedFF
|
|
19
|
+
Promise.all(toRemove.map(removedFF => this.removeSplit(removedFF)))
|
|
20
20
|
]).then(([, added, removed]) => {
|
|
21
21
|
return added.some(result => result) || removed.some(result => result);
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
abstract getSplit(name: string): Promise<
|
|
26
|
-
abstract getSplits(names: string[]): Promise<Record<string,
|
|
25
|
+
abstract getSplit(name: string): Promise<IDefinition | null>
|
|
26
|
+
abstract getSplits(names: string[]): Promise<Record<string, IDefinition | null>>
|
|
27
27
|
abstract getChangeNumber(): Promise<number>
|
|
28
|
-
abstract getAll(): Promise<
|
|
28
|
+
abstract getAll(): Promise<IDefinition[]>
|
|
29
29
|
abstract getSplitNames(): Promise<string[]>
|
|
30
30
|
abstract getNamesByFlagSets(flagSets: string[]): Promise<Set<string>[]>
|
|
31
31
|
abstract trafficTypeExists(trafficType: string): Promise<boolean>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ISplitsCacheSync, IStorageSync } from './types';
|
|
2
|
-
import { IRBSegment,
|
|
2
|
+
import { IRBSegment, IDefinition } from '../dtos/types';
|
|
3
3
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
4
4
|
import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
|
|
5
5
|
|
|
@@ -9,21 +9,21 @@ import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
|
|
|
9
9
|
*/
|
|
10
10
|
export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
11
11
|
|
|
12
|
-
protected abstract addSplit(split:
|
|
12
|
+
protected abstract addSplit(split: IDefinition): boolean
|
|
13
13
|
protected abstract removeSplit(name: string): boolean
|
|
14
14
|
protected abstract setChangeNumber(changeNumber: number): boolean | void
|
|
15
15
|
|
|
16
|
-
update(toAdd:
|
|
16
|
+
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): boolean {
|
|
17
17
|
let updated = toAdd.map(addedFF => this.addSplit(addedFF)).some(result => result);
|
|
18
|
-
updated = toRemove.map(removedFF => this.removeSplit(removedFF
|
|
18
|
+
updated = toRemove.map(removedFF => this.removeSplit(removedFF)).some(result => result) || updated;
|
|
19
19
|
this.setChangeNumber(changeNumber);
|
|
20
20
|
return updated;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
abstract getSplit(name: string):
|
|
23
|
+
abstract getSplit(name: string): IDefinition | null
|
|
24
24
|
|
|
25
|
-
getSplits(names: string[]): Record<string,
|
|
26
|
-
const splits: Record<string,
|
|
25
|
+
getSplits(names: string[]): Record<string, IDefinition | null> {
|
|
26
|
+
const splits: Record<string, IDefinition | null> = {};
|
|
27
27
|
names.forEach(name => {
|
|
28
28
|
splits[name] = this.getSplit(name);
|
|
29
29
|
});
|
|
@@ -32,8 +32,8 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
32
32
|
|
|
33
33
|
abstract getChangeNumber(): number
|
|
34
34
|
|
|
35
|
-
getAll():
|
|
36
|
-
return this.getSplitNames().map(key => this.getSplit(key) as
|
|
35
|
+
getAll(): IDefinition[] {
|
|
36
|
+
return this.getSplitNames().map(key => this.getSplit(key) as IDefinition);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
abstract getSplitNames(): string[]
|
|
@@ -73,7 +73,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
73
73
|
* Given a parsed split, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists).
|
|
74
74
|
* This util is intended to simplify the implementation of `splitsCache::usesSegments` method
|
|
75
75
|
*/
|
|
76
|
-
export function usesSegments(ruleEntity:
|
|
76
|
+
export function usesSegments(ruleEntity: IDefinition | IRBSegment) {
|
|
77
77
|
const conditions = ruleEntity.conditions || [];
|
|
78
78
|
for (let i = 0; i < conditions.length; i++) {
|
|
79
79
|
const matchers = conditions[i].matcherGroup.matchers;
|
|
@@ -25,9 +25,9 @@ export class RBSegmentsCacheInLocal implements IRBSegmentsCacheSync {
|
|
|
25
25
|
this.storage.removeItem(this.keys.buildRBSegmentsTillKey());
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
28
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): boolean {
|
|
29
29
|
let updated = toAdd.map(toAdd => this.add(toAdd)).some(result => result);
|
|
30
|
-
updated = toRemove.map(toRemove => this.remove(toRemove
|
|
30
|
+
updated = toRemove.map(toRemove => this.remove(toRemove)).some(result => result) || updated;
|
|
31
31
|
this.setChangeNumber(changeNumber);
|
|
32
32
|
return updated;
|
|
33
33
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IDefinition } from '../../dtos/types';
|
|
2
2
|
import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
|
|
3
3
|
import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
|
|
4
4
|
import { KeyBuilderCS } from '../KeyBuilderCS';
|
|
@@ -30,7 +30,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
30
30
|
else this.storage.removeItem(key);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
private _decrementCounts(split:
|
|
33
|
+
private _decrementCounts(split: IDefinition) {
|
|
34
34
|
try {
|
|
35
35
|
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
36
36
|
this._decrementCount(ttKey);
|
|
@@ -44,7 +44,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
private _incrementCounts(split:
|
|
47
|
+
private _incrementCounts(split: IDefinition) {
|
|
48
48
|
try {
|
|
49
49
|
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
50
50
|
this.storage.setItem(ttKey, (toNumber(this.storage.getItem(ttKey)) + 1) + '');
|
|
@@ -79,7 +79,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
79
79
|
this.hasSync = false;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
addSplit(split:
|
|
82
|
+
addSplit(split: IDefinition) {
|
|
83
83
|
const name = split.name;
|
|
84
84
|
const splitKey = this.keys.buildSplitKey(name);
|
|
85
85
|
const splitFromStorage = this.storage.getItem(splitKey);
|
|
@@ -110,7 +110,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
110
110
|
return true;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
getSplit(name: string):
|
|
113
|
+
getSplit(name: string): IDefinition | null {
|
|
114
114
|
const item = this.storage.getItem(this.keys.buildSplitKey(name));
|
|
115
115
|
return item && JSON.parse(item);
|
|
116
116
|
}
|
|
@@ -184,7 +184,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
private addToFlagSets(featureFlag:
|
|
187
|
+
private addToFlagSets(featureFlag: IDefinition) {
|
|
188
188
|
if (!featureFlag.sets) return;
|
|
189
189
|
|
|
190
190
|
featureFlag.sets.forEach(featureFlagSet => {
|
|
@@ -15,9 +15,9 @@ export class RBSegmentsCacheInMemory implements IRBSegmentsCacheSync {
|
|
|
15
15
|
this.segmentsCount = 0;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
18
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): boolean {
|
|
19
19
|
let updated = toAdd.map(toAdd => this.add(toAdd)).some(result => result);
|
|
20
|
-
updated = toRemove.map(toRemove => this.remove(toRemove
|
|
20
|
+
updated = toRemove.map(toRemove => this.remove(toRemove)).some(result => result) || updated;
|
|
21
21
|
this.changeNumber = changeNumber;
|
|
22
22
|
return updated;
|
|
23
23
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IDefinition, ISplitFiltersValidation } from '../../dtos/types';
|
|
2
2
|
import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
|
|
3
3
|
import { isFiniteNumber } from '../../utils/lang';
|
|
4
4
|
|
|
@@ -8,7 +8,7 @@ import { isFiniteNumber } from '../../utils/lang';
|
|
|
8
8
|
export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
9
9
|
|
|
10
10
|
private flagSetsFilter: string[];
|
|
11
|
-
private splitsCache: Record<string,
|
|
11
|
+
private splitsCache: Record<string, IDefinition> = {};
|
|
12
12
|
private ttCache: Record<string, number> = {};
|
|
13
13
|
private changeNumber: number = -1;
|
|
14
14
|
private segmentsCount: number = 0;
|
|
@@ -27,7 +27,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
27
27
|
this.flagSetsCache = {};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
addSplit(split:
|
|
30
|
+
addSplit(split: IDefinition): boolean {
|
|
31
31
|
const name = split.name;
|
|
32
32
|
const previousSplit = this.getSplit(name);
|
|
33
33
|
if (previousSplit) { // We had this Split already
|
|
@@ -73,7 +73,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
73
73
|
return true;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
getSplit(name: string):
|
|
76
|
+
getSplit(name: string): IDefinition | null {
|
|
77
77
|
return this.splitsCache[name] || null;
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -102,7 +102,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
102
102
|
return flagSets.map(flagSet => this.flagSetsCache[flagSet] || new Set());
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
private addToFlagSets(featureFlag:
|
|
105
|
+
private addToFlagSets(featureFlag: IDefinition) {
|
|
106
106
|
if (!featureFlag.sets) return;
|
|
107
107
|
featureFlag.sets.forEach(featureFlagSet => {
|
|
108
108
|
|
|
@@ -20,8 +20,8 @@ const ACCEPTANCE_RANGE = 0.001;
|
|
|
20
20
|
* Record telemetry if mode is not localhost.
|
|
21
21
|
* All factory instances track telemetry on server-side, and 0.1% on client-side.
|
|
22
22
|
*/
|
|
23
|
-
export function shouldRecordTelemetry({ settings }: IStorageFactoryParams) {
|
|
24
|
-
return settings.mode !== LOCALHOST_MODE && (checkIfServerSide(settings) || Math.random() <= ACCEPTANCE_RANGE);
|
|
23
|
+
export function shouldRecordTelemetry({ settings, disableTelemetry }: IStorageFactoryParams) {
|
|
24
|
+
return !disableTelemetry && settings.mode !== LOCALHOST_MODE && (checkIfServerSide(settings) || Math.random() <= ACCEPTANCE_RANGE);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
@@ -37,7 +37,7 @@ export class RBSegmentsCacheInRedis implements IRBSegmentsCacheAsync {
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
40
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): Promise<boolean> {
|
|
41
41
|
return Promise.all([
|
|
42
42
|
this.setChangeNumber(changeNumber),
|
|
43
43
|
Promise.all(toAdd.map(toAdd => {
|
|
@@ -46,7 +46,7 @@ export class RBSegmentsCacheInRedis implements IRBSegmentsCacheAsync {
|
|
|
46
46
|
return this.redis.set(key, stringifiedNewRBSegment).then(() => true);
|
|
47
47
|
})),
|
|
48
48
|
Promise.all(toRemove.map(toRemove => {
|
|
49
|
-
const key = this.keys.buildRBSegmentKey(toRemove
|
|
49
|
+
const key = this.keys.buildRBSegmentKey(toRemove);
|
|
50
50
|
return this.redis.del(key).then((status: number) => status === 1);
|
|
51
51
|
}))
|
|
52
52
|
]).then(([, added, removed]) => {
|
|
@@ -2,7 +2,7 @@ import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
|
|
|
2
2
|
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
3
3
|
import { ILogger } from '../../logger/types';
|
|
4
4
|
import { LOG_PREFIX } from './constants';
|
|
5
|
-
import {
|
|
5
|
+
import { IDefinition, ISplitFiltersValidation } from '../../dtos/types';
|
|
6
6
|
import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
|
|
7
7
|
import { returnDifference } from '../../utils/lang/sets';
|
|
8
8
|
import type { RedisAdapter } from './RedisAdapter';
|
|
@@ -47,14 +47,14 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
private _decrementCounts(split:
|
|
50
|
+
private _decrementCounts(split: IDefinition) {
|
|
51
51
|
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
52
52
|
return this.redis.decr(ttKey).then((count: number) => {
|
|
53
53
|
if (count === 0) return this.redis.del(ttKey);
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
private _incrementCounts(split:
|
|
57
|
+
private _incrementCounts(split: IDefinition) {
|
|
58
58
|
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
59
59
|
return this.redis.incr(ttKey);
|
|
60
60
|
}
|
|
@@ -82,13 +82,13 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
82
82
|
* The returned promise is resolved when the operation success
|
|
83
83
|
* or rejected if it fails (e.g., redis operation fails)
|
|
84
84
|
*/
|
|
85
|
-
addSplit(split:
|
|
85
|
+
addSplit(split: IDefinition): Promise<boolean> {
|
|
86
86
|
const name = split.name;
|
|
87
87
|
const splitKey = this.keys.buildSplitKey(name);
|
|
88
88
|
return this.redis.get(splitKey).then((splitFromStorage: string | null) => {
|
|
89
89
|
|
|
90
90
|
// handling parsing error
|
|
91
|
-
let parsedPreviousSplit:
|
|
91
|
+
let parsedPreviousSplit: IDefinition, stringifiedNewSplit;
|
|
92
92
|
try {
|
|
93
93
|
parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
|
|
94
94
|
stringifiedNewSplit = JSON.stringify(split);
|
|
@@ -127,7 +127,7 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
127
127
|
* Get split definition or null if it's not defined.
|
|
128
128
|
* Returned promise is rejected if redis operation fails.
|
|
129
129
|
*/
|
|
130
|
-
getSplit(name: string): Promise<
|
|
130
|
+
getSplit(name: string): Promise<IDefinition | null> {
|
|
131
131
|
if (this.redisError) {
|
|
132
132
|
this.log.error(LOG_PREFIX + this.redisError);
|
|
133
133
|
|
|
@@ -171,7 +171,7 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
171
171
|
* or rejected if redis operation fails.
|
|
172
172
|
*/
|
|
173
173
|
// @TODO we need to benchmark which is the maximun number of commands we could pipeline without kill redis performance.
|
|
174
|
-
getAll(): Promise<
|
|
174
|
+
getAll(): Promise<IDefinition[]> {
|
|
175
175
|
return this.redis.keys(this.keys.searchPatternForSplitKeys())
|
|
176
176
|
.then((listOfKeys: string[]) => this.redis.pipeline(listOfKeys.map((k: string) => ['get', k])).exec())
|
|
177
177
|
.then(processPipelineAnswer)
|
|
@@ -242,7 +242,7 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
242
242
|
* Fetches multiple splits definitions.
|
|
243
243
|
* Returned promise is rejected if redis operation fails.
|
|
244
244
|
*/
|
|
245
|
-
getSplits(names: string[]): Promise<Record<string,
|
|
245
|
+
getSplits(names: string[]): Promise<Record<string, IDefinition | null>> {
|
|
246
246
|
if (this.redisError) {
|
|
247
247
|
this.log.error(LOG_PREFIX + this.redisError);
|
|
248
248
|
|
|
@@ -252,7 +252,7 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
252
252
|
const keys = names.map(name => this.keys.buildSplitKey(name));
|
|
253
253
|
return this.redis.mget(...keys)
|
|
254
254
|
.then((splitDefinitions: (string | null)[]) => {
|
|
255
|
-
const splits: Record<string,
|
|
255
|
+
const splits: Record<string, IDefinition | null> = {};
|
|
256
256
|
names.forEach((name, idx) => {
|
|
257
257
|
const split = splitDefinitions[idx];
|
|
258
258
|
splits[name] = split && JSON.parse(split);
|
|
@@ -36,7 +36,7 @@ export class RBSegmentsCachePluggable implements IRBSegmentsCacheAsync {
|
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
update(toAdd: IRBSegment[], toRemove:
|
|
39
|
+
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): Promise<boolean> {
|
|
40
40
|
return Promise.all([
|
|
41
41
|
this.setChangeNumber(changeNumber),
|
|
42
42
|
Promise.all(toAdd.map(toAdd => {
|
|
@@ -45,7 +45,7 @@ export class RBSegmentsCachePluggable implements IRBSegmentsCacheAsync {
|
|
|
45
45
|
return this.wrapper.set(key, stringifiedNewRBSegment).then(() => true);
|
|
46
46
|
})),
|
|
47
47
|
Promise.all(toRemove.map(toRemove => {
|
|
48
|
-
const key = this.keys.buildRBSegmentKey(toRemove
|
|
48
|
+
const key = this.keys.buildRBSegmentKey(toRemove);
|
|
49
49
|
return this.wrapper.del(key);
|
|
50
50
|
}))
|
|
51
51
|
]).then(([, added, removed]) => {
|