@splitsoftware/splitio-commons 1.6.2-rc.5 → 1.6.2-rc.6
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/cjs/consent/sdkUserConsent.js +2 -2
- package/cjs/evaluator/index.js +10 -11
- package/cjs/integrations/ga/GaToSplit.js +8 -5
- package/cjs/listeners/browser.js +1 -2
- package/cjs/logger/constants.js +1 -2
- package/cjs/sdkFactory/index.js +7 -25
- package/cjs/sdkManager/index.js +3 -11
- package/cjs/services/splitApi.js +0 -20
- package/cjs/storages/AbstractSplitsCacheAsync.js +7 -9
- package/cjs/storages/AbstractSplitsCacheSync.js +7 -9
- package/cjs/storages/KeyBuilderSS.js +0 -6
- package/cjs/storages/dataLoader.js +1 -1
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +5 -6
- package/cjs/storages/inLocalStorage/index.js +0 -4
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -12
- package/cjs/storages/inMemory/InMemoryStorage.js +1 -5
- package/cjs/storages/inMemory/InMemoryStorageCS.js +1 -5
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +7 -10
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +15 -9
- package/cjs/storages/inRedis/constants.js +1 -4
- package/cjs/storages/inRedis/index.js +1 -15
- package/cjs/storages/pluggable/SplitsCachePluggable.js +14 -9
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +1 -1
- package/cjs/sync/submitters/submitterManager.js +0 -3
- package/cjs/sync/submitters/telemetrySubmitter.js +0 -1
- package/cjs/trackers/impressionsTracker.js +41 -22
- package/cjs/trackers/telemetryTracker.js +6 -0
- package/cjs/utils/constants/index.js +2 -4
- package/cjs/utils/settingsValidation/impressionsMode.js +2 -2
- package/cjs/utils/settingsValidation/index.js +0 -3
- package/esm/consent/sdkUserConsent.js +2 -2
- package/esm/evaluator/index.js +10 -11
- package/esm/integrations/ga/GaToSplit.js +8 -5
- package/esm/listeners/browser.js +2 -3
- package/esm/logger/constants.js +0 -1
- package/esm/sdkFactory/index.js +7 -25
- package/esm/sdkManager/index.js +3 -11
- package/esm/services/splitApi.js +0 -20
- package/esm/storages/AbstractSplitsCacheAsync.js +7 -9
- package/esm/storages/AbstractSplitsCacheSync.js +7 -9
- package/esm/storages/KeyBuilderSS.js +0 -6
- package/esm/storages/dataLoader.js +1 -1
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +5 -6
- package/esm/storages/inLocalStorage/index.js +1 -5
- package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -12
- package/esm/storages/inMemory/InMemoryStorage.js +2 -6
- package/esm/storages/inMemory/InMemoryStorageCS.js +2 -6
- package/esm/storages/inMemory/SplitsCacheInMemory.js +7 -10
- package/esm/storages/inRedis/SplitsCacheInRedis.js +15 -9
- package/esm/storages/inRedis/constants.js +0 -3
- package/esm/storages/inRedis/index.js +2 -16
- package/esm/storages/pluggable/SplitsCachePluggable.js +14 -9
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
- package/esm/sync/polling/updaters/splitChangesUpdater.js +1 -1
- package/esm/sync/submitters/submitterManager.js +0 -3
- package/esm/sync/submitters/telemetrySubmitter.js +1 -2
- package/esm/trackers/impressionsTracker.js +41 -22
- package/esm/trackers/telemetryTracker.js +6 -0
- package/esm/utils/constants/index.js +0 -2
- package/esm/utils/settingsValidation/impressionsMode.js +3 -3
- package/esm/utils/settingsValidation/index.js +0 -3
- package/package.json +1 -1
- package/src/consent/sdkUserConsent.ts +2 -2
- package/src/evaluator/index.ts +8 -9
- package/src/integrations/ga/GaToSplit.ts +9 -5
- package/src/integrations/types.ts +2 -1
- package/src/listeners/browser.ts +2 -3
- package/src/logger/.DS_Store +0 -0
- package/src/logger/constants.ts +0 -1
- package/src/sdkFactory/index.ts +7 -28
- package/src/sdkFactory/types.ts +4 -7
- package/src/sdkManager/index.ts +3 -12
- package/src/services/splitApi.ts +0 -22
- package/src/services/types.ts +0 -6
- package/src/storages/AbstractSplitsCacheAsync.ts +13 -14
- package/src/storages/AbstractSplitsCacheSync.ts +14 -16
- package/src/storages/KeyBuilderSS.ts +0 -8
- package/src/storages/dataLoader.ts +1 -1
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +8 -10
- package/src/storages/inLocalStorage/index.ts +1 -4
- package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +1 -16
- package/src/storages/inMemory/InMemoryStorage.ts +2 -5
- package/src/storages/inMemory/InMemoryStorageCS.ts +2 -6
- package/src/storages/inMemory/SplitsCacheInMemory.ts +10 -14
- package/src/storages/inRedis/SplitsCacheInRedis.ts +21 -17
- package/src/storages/inRedis/constants.ts +0 -3
- package/src/storages/inRedis/index.ts +3 -12
- package/src/storages/pluggable/SplitsCachePluggable.ts +20 -17
- package/src/storages/types.ts +21 -40
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +5 -6
- package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -2
- package/src/sync/submitters/submitterManager.ts +0 -2
- package/src/sync/submitters/telemetrySubmitter.ts +3 -4
- package/src/sync/submitters/types.ts +1 -20
- package/src/trackers/impressionsTracker.ts +48 -27
- package/src/trackers/telemetryTracker.ts +7 -2
- package/src/trackers/types.ts +4 -26
- package/src/types.ts +1 -3
- package/src/utils/constants/index.ts +0 -2
- package/src/utils/settingsValidation/impressionsMode.ts +3 -3
- package/src/utils/settingsValidation/index.ts +0 -4
- package/types/integrations/types.d.ts +2 -1
- package/types/logger/constants.d.ts +0 -1
- package/types/sdkFactory/types.d.ts +2 -4
- package/types/services/types.d.ts +0 -4
- package/types/storages/AbstractSplitsCacheAsync.d.ts +6 -5
- package/types/storages/AbstractSplitsCacheSync.d.ts +5 -5
- package/types/storages/KeyBuilderSS.d.ts +0 -2
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +3 -3
- package/types/storages/inMemory/ImpressionCountsCacheInMemory.d.ts +1 -5
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +3 -2
- package/types/storages/inRedis/SplitsCacheInRedis.d.ts +6 -5
- package/types/storages/inRedis/constants.d.ts +0 -3
- package/types/storages/pluggable/SplitsCachePluggable.d.ts +6 -5
- package/types/storages/types.d.ts +18 -28
- package/types/sync/polling/updaters/splitChangesUpdater.d.ts +1 -1
- package/types/sync/submitters/types.d.ts +1 -18
- package/types/trackers/impressionsTracker.d.ts +6 -4
- package/types/trackers/types.d.ts +4 -21
- package/types/types.d.ts +1 -3
- package/types/utils/constants/index.d.ts +0 -2
- package/types/utils/settingsValidation/index.d.ts +0 -1
- package/cjs/storages/inMemory/uniqueKeysCacheInMemory.js +0 -73
- package/cjs/storages/inMemory/uniqueKeysCacheInMemoryCS.js +0 -78
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +0 -46
- package/cjs/storages/inRedis/uniqueKeysCacheInRedis.js +0 -55
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +0 -26
- package/cjs/trackers/strategy/strategyDebug.js +0 -25
- package/cjs/trackers/strategy/strategyNone.js +0 -29
- package/cjs/trackers/strategy/strategyOptimized.js +0 -34
- package/cjs/trackers/uniqueKeysTracker.js +0 -31
- package/esm/storages/inMemory/uniqueKeysCacheInMemory.js +0 -70
- package/esm/storages/inMemory/uniqueKeysCacheInMemoryCS.js +0 -75
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +0 -43
- package/esm/storages/inRedis/uniqueKeysCacheInRedis.js +0 -52
- package/esm/sync/submitters/uniqueKeysSubmitter.js +0 -22
- package/esm/trackers/strategy/strategyDebug.js +0 -21
- package/esm/trackers/strategy/strategyNone.js +0 -25
- package/esm/trackers/strategy/strategyOptimized.js +0 -30
- package/esm/trackers/uniqueKeysTracker.js +0 -27
- package/src/storages/inMemory/uniqueKeysCacheInMemory.ts +0 -82
- package/src/storages/inMemory/uniqueKeysCacheInMemoryCS.ts +0 -88
- package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +0 -48
- package/src/storages/inRedis/uniqueKeysCacheInRedis.ts +0 -61
- package/src/sync/submitters/uniqueKeysSubmitter.ts +0 -35
- package/src/trackers/strategy/strategyDebug.ts +0 -28
- package/src/trackers/strategy/strategyNone.ts +0 -34
- package/src/trackers/strategy/strategyOptimized.ts +0 -42
- package/src/trackers/uniqueKeysTracker.ts +0 -37
- package/types/sdkClient/types.d.ts +0 -18
- package/types/storages/inMemory/CountsCacheInMemory.d.ts +0 -20
- package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +0 -20
- package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +0 -35
- package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +0 -37
- package/types/storages/inRedis/CountsCacheInRedis.d.ts +0 -9
- package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +0 -13
- package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +0 -9
- package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +0 -14
- package/types/sync/offline/LocalhostFromFile.d.ts +0 -2
- package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +0 -2
- package/types/sync/submitters/eventsSyncTask.d.ts +0 -8
- package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +0 -5
- package/types/sync/submitters/impressionCountsSyncTask.d.ts +0 -13
- package/types/sync/submitters/impressionsSyncTask.d.ts +0 -14
- package/types/sync/submitters/metricsSyncTask.d.ts +0 -12
- package/types/sync/submitters/submitterSyncTask.d.ts +0 -10
- package/types/sync/submitters/uniqueKeysSubmitter.d.ts +0 -5
- package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +0 -5
- package/types/sync/syncTaskComposite.d.ts +0 -5
- package/types/trackers/filter/bloomFilter.d.ts +0 -10
- package/types/trackers/filter/dictionaryFilter.d.ts +0 -8
- package/types/trackers/filter/types.d.ts +0 -5
- package/types/trackers/strategy/strategyDebug.d.ts +0 -9
- package/types/trackers/strategy/strategyNone.d.ts +0 -10
- package/types/trackers/strategy/strategyOptimized.d.ts +0 -11
- package/types/trackers/uniqueKeysTracker.d.ts +0 -13
- package/types/utils/timeTracker/index.d.ts +0 -70
|
@@ -46,6 +46,11 @@ export function telemetryTrackerFactory(telemetryCache, now) {
|
|
|
46
46
|
if (e === TOKEN_REFRESH)
|
|
47
47
|
telemetryCache.recordTokenRefreshes();
|
|
48
48
|
}
|
|
49
|
+
},
|
|
50
|
+
addTag: function (tag) {
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
if (telemetryCache.addTag)
|
|
53
|
+
telemetryCache.addTag(tag);
|
|
49
54
|
}
|
|
50
55
|
};
|
|
51
56
|
}
|
|
@@ -56,6 +61,7 @@ export function telemetryTrackerFactory(telemetryCache, now) {
|
|
|
56
61
|
trackHttp: noopTrack,
|
|
57
62
|
sessionLength: function () { },
|
|
58
63
|
streamingEvent: function () { },
|
|
64
|
+
addTag: function () { }
|
|
59
65
|
};
|
|
60
66
|
}
|
|
61
67
|
}
|
|
@@ -13,7 +13,6 @@ export var SPLIT_EVENT = 'EVENT';
|
|
|
13
13
|
// Impression collection modes
|
|
14
14
|
export var DEBUG = 'DEBUG';
|
|
15
15
|
export var OPTIMIZED = 'OPTIMIZED';
|
|
16
|
-
export var NONE = 'NONE';
|
|
17
16
|
// SDK Modes
|
|
18
17
|
export var LOCALHOST_MODE = 'localhost';
|
|
19
18
|
export var STANDALONE_MODE = 'standalone';
|
|
@@ -38,7 +37,6 @@ export var CONSUMER_ENUM = 1;
|
|
|
38
37
|
export var CONSUMER_PARTIAL_ENUM = 2;
|
|
39
38
|
export var OPTIMIZED_ENUM = 0;
|
|
40
39
|
export var DEBUG_ENUM = 1;
|
|
41
|
-
export var NONE_ENUM = 2;
|
|
42
40
|
export var SPLITS = 'sp';
|
|
43
41
|
export var IMPRESSIONS = 'im';
|
|
44
42
|
export var IMPRESSIONS_COUNT = 'ic';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
|
|
2
|
-
import { DEBUG, OPTIMIZED
|
|
2
|
+
import { DEBUG, OPTIMIZED } from '../constants';
|
|
3
3
|
import { stringToUpperCase } from '../lang';
|
|
4
4
|
export function validImpressionsMode(log, impressionsMode) {
|
|
5
5
|
impressionsMode = stringToUpperCase(impressionsMode);
|
|
6
|
-
if ([DEBUG, OPTIMIZED
|
|
6
|
+
if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) > -1)
|
|
7
7
|
return impressionsMode;
|
|
8
|
-
log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED
|
|
8
|
+
log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED], OPTIMIZED]);
|
|
9
9
|
return OPTIMIZED;
|
|
10
10
|
}
|
|
@@ -31,8 +31,6 @@ export var base = {
|
|
|
31
31
|
telemetryRefreshRate: 3600,
|
|
32
32
|
// publish evaluations each 300 sec (default value for OPTIMIZED impressions mode)
|
|
33
33
|
impressionsRefreshRate: 300,
|
|
34
|
-
// publish unique Keys each 900 sec (15 min)
|
|
35
|
-
uniqueKeysRefreshRate: 900,
|
|
36
34
|
// fetch offline changes each 15 sec
|
|
37
35
|
offlineRefreshRate: 15,
|
|
38
36
|
// publish events every 60 seconds after the first flush
|
|
@@ -111,7 +109,6 @@ export function settingsValidation(config, validationParams) {
|
|
|
111
109
|
scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
|
|
112
110
|
scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
|
|
113
111
|
scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
|
|
114
|
-
scheduler.uniqueKeysRefreshRate = fromSecondsToMillis(scheduler.uniqueKeysRefreshRate);
|
|
115
112
|
scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
|
|
116
113
|
// Default impressionsRefreshRate for DEBUG mode is 60 secs
|
|
117
114
|
if (get(config, 'scheduler.impressionsRefreshRate') === undefined && withDefaults.sync.impressionsMode === DEBUG)
|
package/package.json
CHANGED
|
@@ -40,8 +40,8 @@ export function createUserConsentAPI(params: ISdkFactoryContext) {
|
|
|
40
40
|
|
|
41
41
|
// @ts-ignore, clear method is present in storage for standalone and partial consumer mode
|
|
42
42
|
if (events.clear) events.clear(); // @ts-ignore
|
|
43
|
-
if (impressions.clear) impressions.clear()
|
|
44
|
-
if (impressionCounts
|
|
43
|
+
if (impressions.clear) impressions.clear();
|
|
44
|
+
if (impressionCounts) impressionCounts.clear();
|
|
45
45
|
}
|
|
46
46
|
} else {
|
|
47
47
|
log.info(USER_CONSENT_NOT_UPDATED, [newConsentStatus]);
|
package/src/evaluator/index.ts
CHANGED
|
@@ -68,28 +68,28 @@ export function evaluateFeatures(
|
|
|
68
68
|
attributes: SplitIO.Attributes | undefined,
|
|
69
69
|
storage: IStorageSync | IStorageAsync,
|
|
70
70
|
): MaybeThenable<Record<string, IEvaluationResult>> {
|
|
71
|
-
let
|
|
71
|
+
let parsedSplits;
|
|
72
72
|
|
|
73
73
|
try {
|
|
74
|
-
|
|
74
|
+
parsedSplits = storage.splits.getSplits(splitNames);
|
|
75
75
|
} catch (e) {
|
|
76
76
|
// Exception on sync `getSplits` storage. Not possible ATM with InMemory and InLocal storages.
|
|
77
77
|
return treatmentsException(splitNames);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
return
|
|
81
|
-
|
|
80
|
+
return thenable(parsedSplits) ?
|
|
81
|
+
parsedSplits.then(splits => getEvaluations(log, splitNames, splits, key, attributes, storage))
|
|
82
82
|
.catch(() => {
|
|
83
83
|
// Exception on async `getSplits` storage. For example, when the storage is redis or
|
|
84
84
|
// pluggable and there is a connection issue and we can't retrieve the split to be evaluated
|
|
85
85
|
return treatmentsException(splitNames);
|
|
86
86
|
}) :
|
|
87
|
-
getEvaluations(log, splitNames,
|
|
87
|
+
getEvaluations(log, splitNames, parsedSplits, key, attributes, storage);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function getEvaluation(
|
|
91
91
|
log: ILogger,
|
|
92
|
-
|
|
92
|
+
splitJSON: ISplit | null,
|
|
93
93
|
key: SplitIO.SplitKey,
|
|
94
94
|
attributes: SplitIO.Attributes | undefined,
|
|
95
95
|
storage: IStorageSync | IStorageAsync,
|
|
@@ -100,8 +100,7 @@ function getEvaluation(
|
|
|
100
100
|
config: null
|
|
101
101
|
};
|
|
102
102
|
|
|
103
|
-
if (
|
|
104
|
-
const splitJSON: ISplit = JSON.parse(stringifiedSplit);
|
|
103
|
+
if (splitJSON) {
|
|
105
104
|
const split = Engine.parse(log, splitJSON, storage);
|
|
106
105
|
evaluation = split.getTreatment(key, attributes, evaluateFeature);
|
|
107
106
|
|
|
@@ -125,7 +124,7 @@ function getEvaluation(
|
|
|
125
124
|
function getEvaluations(
|
|
126
125
|
log: ILogger,
|
|
127
126
|
splitNames: string[],
|
|
128
|
-
splits: Record<string,
|
|
127
|
+
splits: Record<string, ISplit | null>,
|
|
129
128
|
key: SplitIO.SplitKey,
|
|
130
129
|
attributes: SplitIO.Attributes | undefined,
|
|
131
130
|
storage: IStorageSync | IStorageAsync,
|
|
@@ -12,6 +12,7 @@ import { SplitIO } from '../../types';
|
|
|
12
12
|
import { Identity, GoogleAnalyticsToSplitOptions } from './types';
|
|
13
13
|
import { ILogger } from '../../logger/types';
|
|
14
14
|
import { IIntegrationFactoryParams } from '../types';
|
|
15
|
+
import { ITelemetryTracker } from '../../trackers/types';
|
|
15
16
|
|
|
16
17
|
const logPrefix = 'ga-to-split: ';
|
|
17
18
|
const logNameMapper = 'ga-to-split:mapper';
|
|
@@ -25,7 +26,7 @@ const logNameMapper = 'ga-to-split:mapper';
|
|
|
25
26
|
* @param log Logger instance.
|
|
26
27
|
* @param autoRequire If true, log error when auto-require script is not detected
|
|
27
28
|
*/
|
|
28
|
-
function providePlugin(window: any, pluginName: string, pluginConstructor: Function, log: ILogger, autoRequire?:
|
|
29
|
+
function providePlugin(window: any, pluginName: string, pluginConstructor: Function, log: ILogger, autoRequire: boolean, telemetryTracker?: ITelemetryTracker) {
|
|
29
30
|
// get reference to global command queue. Init it if not defined yet.
|
|
30
31
|
const gaAlias = window.GoogleAnalyticsObject || 'ga';
|
|
31
32
|
window[gaAlias] = window[gaAlias] || function () {
|
|
@@ -35,10 +36,13 @@ function providePlugin(window: any, pluginName: string, pluginConstructor: Funct
|
|
|
35
36
|
// provides the plugin for use with analytics.js.
|
|
36
37
|
window[gaAlias]('provide', pluginName, pluginConstructor);
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
const hasAutoRequire = window[gaAlias].q && window[gaAlias].q.push !== [].push;
|
|
40
|
+
if (autoRequire && !hasAutoRequire) { // Expecting spy on ga.q push method but not found
|
|
40
41
|
log.error(logPrefix + 'integration is configured to autorequire the splitTracker plugin, but the necessary script does not seem to have run. Please check the docs.');
|
|
41
42
|
}
|
|
43
|
+
if (telemetryTracker && hasAutoRequire) {
|
|
44
|
+
telemetryTracker.addTag('integration:ga-autorequire');
|
|
45
|
+
}
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
// Default mapping: object used for building the default mapper from hits to Split events
|
|
@@ -191,7 +195,7 @@ export function fixEventTypeId(log: ILogger, eventTypeId: any) {
|
|
|
191
195
|
*/
|
|
192
196
|
export function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, params: IIntegrationFactoryParams) {
|
|
193
197
|
|
|
194
|
-
const { storage, settings: { core: coreSettings, log } } = params;
|
|
198
|
+
const { storage, settings: { core: coreSettings, log }, telemetryTracker } = params;
|
|
195
199
|
|
|
196
200
|
const defaultOptions = {
|
|
197
201
|
prefix: defaultPrefix,
|
|
@@ -291,5 +295,5 @@ export function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, params: IIn
|
|
|
291
295
|
}
|
|
292
296
|
|
|
293
297
|
// Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
|
|
294
|
-
providePlugin(window, 'splitTracker', SplitTracker, log, sdkOptions.autoRequire === true);
|
|
298
|
+
providePlugin(window, 'splitTracker', SplitTracker, log, sdkOptions.autoRequire === true, telemetryTracker);
|
|
295
299
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IEventsCacheBase } from '../storages/types';
|
|
2
|
-
import { IEventsHandler, IImpressionsHandler } from '../trackers/types';
|
|
2
|
+
import { IEventsHandler, IImpressionsHandler, ITelemetryTracker } from '../trackers/types';
|
|
3
3
|
import { ISettings, SplitIO } from '../types';
|
|
4
4
|
|
|
5
5
|
export interface IIntegration {
|
|
@@ -11,6 +11,7 @@ export type IIntegrationManager = IEventsHandler & IImpressionsHandler;
|
|
|
11
11
|
export interface IIntegrationFactoryParams {
|
|
12
12
|
storage: { events: IEventsCacheBase }
|
|
13
13
|
settings: ISettings
|
|
14
|
+
telemetryTracker: ITelemetryTracker
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export type IntegrationFactory = {
|
package/src/listeners/browser.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { fromImpressionCountsCollector } from '../sync/submitters/impressionCoun
|
|
|
7
7
|
import { IResponse, ISplitApi } from '../services/types';
|
|
8
8
|
import { ImpressionDTO, ISettings } from '../types';
|
|
9
9
|
import { ImpressionsPayload } from '../sync/submitters/types';
|
|
10
|
-
import { OPTIMIZED, DEBUG
|
|
10
|
+
import { OPTIMIZED, DEBUG } from '../utils/constants';
|
|
11
11
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
12
12
|
import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
|
|
13
13
|
import { ISyncManager } from '../sync/types';
|
|
@@ -88,10 +88,9 @@ export class BrowserSignalListener implements ISignalListener {
|
|
|
88
88
|
// Flush impressions & events data if there is user consent
|
|
89
89
|
if (isConsentGranted(this.settings)) {
|
|
90
90
|
const eventsUrl = this.settings.urls.events;
|
|
91
|
-
const sim = this.settings.sync.impressionsMode;
|
|
92
91
|
const extraMetadata = {
|
|
93
92
|
// sim stands for Sync/Split Impressions Mode
|
|
94
|
-
sim:
|
|
93
|
+
sim: this.settings.sync.impressionsMode === OPTIMIZED ? OPTIMIZED : DEBUG
|
|
95
94
|
};
|
|
96
95
|
|
|
97
96
|
this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
|
|
Binary file
|
package/src/logger/constants.ts
CHANGED
|
@@ -143,5 +143,4 @@ export const LOG_PREFIX_SYNC_POLLING = LOG_PREFIX_SYNC + ':polling-manager: ';
|
|
|
143
143
|
export const LOG_PREFIX_SYNC_SUBMITTERS = LOG_PREFIX_SYNC + ':submitter: ';
|
|
144
144
|
export const LOG_PREFIX_IMPRESSIONS_TRACKER = 'impressions-tracker: ';
|
|
145
145
|
export const LOG_PREFIX_EVENTS_TRACKER = 'events-tracker: ';
|
|
146
|
-
export const LOG_PREFIX_UNIQUE_KEYS_TRACKER = 'unique-keys-tracker: ';
|
|
147
146
|
export const LOG_PREFIX_CLEANUP = 'cleanup: ';
|
package/src/sdkFactory/index.ts
CHANGED
|
@@ -13,11 +13,6 @@ import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
|
13
13
|
import { metadataBuilder } from '../storages/metadataBuilder';
|
|
14
14
|
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
15
15
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
16
|
-
import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
|
|
17
|
-
import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized';
|
|
18
|
-
import { strategyNoneFactory } from '../trackers/strategy/strategyNone';
|
|
19
|
-
import { uniqueKeysTrackerFactory } from '../trackers/uniqueKeysTracker';
|
|
20
|
-
import { NONE, OPTIMIZED } from '../utils/constants';
|
|
21
16
|
|
|
22
17
|
/**
|
|
23
18
|
* Modular SDK factory
|
|
@@ -26,8 +21,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
26
21
|
|
|
27
22
|
const { settings, platform, storageFactory, splitApiFactory, extraProps,
|
|
28
23
|
syncManagerFactory, SignalListener, impressionsObserverFactory,
|
|
29
|
-
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory
|
|
30
|
-
filterAdapterFactory } = params;
|
|
24
|
+
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory } = params;
|
|
31
25
|
const log = settings.log;
|
|
32
26
|
|
|
33
27
|
// @TODO handle non-recoverable errors, such as, global `fetch` not available, invalid API Key, etc.
|
|
@@ -43,7 +37,6 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
43
37
|
const storageFactoryParams: IStorageFactoryParams = {
|
|
44
38
|
impressionsQueueSize: settings.scheduler.impressionsQueueSize,
|
|
45
39
|
eventsQueueSize: settings.scheduler.eventsQueueSize,
|
|
46
|
-
uniqueKeysCacheSize: settings.scheduler.uniqueKeysCacheSize,
|
|
47
40
|
optimize: shouldBeOptimized(settings),
|
|
48
41
|
|
|
49
42
|
// ATM, only used by InLocalStorage
|
|
@@ -52,7 +45,6 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
52
45
|
|
|
53
46
|
// ATM, only used by PluggableStorage
|
|
54
47
|
mode: settings.mode,
|
|
55
|
-
impressionsMode: settings.sync.impressionsMode,
|
|
56
48
|
|
|
57
49
|
// Callback used to emit SDK_READY in consumer mode, where `syncManagerFactory` is undefined,
|
|
58
50
|
// or partial consumer mode, where it only has submitters, and therefore it doesn't emit readiness events.
|
|
@@ -68,31 +60,18 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
68
60
|
const storage = storageFactory(storageFactoryParams);
|
|
69
61
|
// @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);`
|
|
70
62
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
const observer = impressionsObserverFactory();
|
|
74
|
-
const uniqueKeysTracker = storageFactoryParams.impressionsMode === NONE ? uniqueKeysTrackerFactory(log, storage.uniqueKeys!, filterAdapterFactory && filterAdapterFactory()) : undefined;
|
|
75
|
-
|
|
76
|
-
let strategy;
|
|
77
|
-
switch (storageFactoryParams.impressionsMode) {
|
|
78
|
-
case OPTIMIZED:
|
|
79
|
-
strategy = strategyOptimizedFactory(observer, storage.impressionCounts!);
|
|
80
|
-
break;
|
|
81
|
-
case NONE:
|
|
82
|
-
strategy = strategyNoneFactory(storage.impressionCounts!, uniqueKeysTracker!);
|
|
83
|
-
break;
|
|
84
|
-
default:
|
|
85
|
-
strategy = strategyDebugFactory(observer);
|
|
86
|
-
}
|
|
63
|
+
const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
64
|
+
const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage, telemetryTracker });
|
|
87
65
|
|
|
88
|
-
|
|
66
|
+
// trackers
|
|
67
|
+
const observer = impressionsObserverFactory && impressionsObserverFactory();
|
|
68
|
+
const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, integrationsManager, observer, storage.impressionCounts, storage.telemetry);
|
|
89
69
|
const eventTracker = eventTrackerFactory(settings, storage.events, integrationsManager, storage.telemetry);
|
|
90
|
-
const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
91
70
|
|
|
92
71
|
// splitApi is used by SyncManager and Browser signal listener
|
|
93
72
|
const splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
|
|
94
73
|
|
|
95
|
-
const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker,
|
|
74
|
+
const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, readiness, settings, storage, platform };
|
|
96
75
|
|
|
97
76
|
const syncManager = syncManagerFactory && syncManagerFactory(ctx as ISdkFactoryContextSync);
|
|
98
77
|
ctx.syncManager = syncManager;
|
package/src/sdkFactory/types.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
|
|
|
6
6
|
import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
|
|
7
7
|
import { ISyncManager } from '../sync/types';
|
|
8
8
|
import { IImpressionObserver } from '../trackers/impressionObserver/types';
|
|
9
|
-
import { IImpressionsTracker, IEventTracker, ITelemetryTracker
|
|
9
|
+
import { IImpressionsTracker, IEventTracker, ITelemetryTracker } from '../trackers/types';
|
|
10
10
|
import { SplitIO, ISettings, IEventEmitter } from '../types';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -44,7 +44,6 @@ export interface ISdkFactoryContext {
|
|
|
44
44
|
eventTracker: IEventTracker,
|
|
45
45
|
telemetryTracker: ITelemetryTracker,
|
|
46
46
|
storage: IStorageSync | IStorageAsync,
|
|
47
|
-
uniqueKeysTracker?: IUniqueKeysTracker,
|
|
48
47
|
signalListener?: ISignalListener
|
|
49
48
|
splitApi?: ISplitApi
|
|
50
49
|
syncManager?: ISyncManager,
|
|
@@ -97,11 +96,6 @@ export interface ISdkFactoryParams {
|
|
|
97
96
|
// It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
|
|
98
97
|
sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
|
|
99
98
|
|
|
100
|
-
// Impression observer factory. If provided, will be used for impressions dedupe
|
|
101
|
-
impressionsObserverFactory: () => IImpressionObserver
|
|
102
|
-
|
|
103
|
-
filterAdapterFactory?: () => IFilterAdapter
|
|
104
|
-
|
|
105
99
|
// Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed.
|
|
106
100
|
// Pass only if `syncManager` (used by Node listener) and `splitApi` (used by Browser listener) are passed.
|
|
107
101
|
SignalListener?: new (
|
|
@@ -113,6 +107,9 @@ export interface ISdkFactoryParams {
|
|
|
113
107
|
// @TODO review impressionListener and integrations interfaces. What about handling impressionListener as an integration ?
|
|
114
108
|
integrationsManagerFactory?: (params: IIntegrationFactoryParams) => IIntegrationManager | undefined,
|
|
115
109
|
|
|
110
|
+
// Impression observer factory. If provided, will be used for impressions dedupe
|
|
111
|
+
impressionsObserverFactory?: () => IImpressionObserver
|
|
112
|
+
|
|
116
113
|
// Optional function to assign additional properties to the factory instance
|
|
117
114
|
extraProps?: (params: ISdkFactoryContext) => object
|
|
118
115
|
}
|
package/src/sdkManager/index.ts
CHANGED
|
@@ -18,16 +18,7 @@ function collectTreatments(splitObject: ISplit) {
|
|
|
18
18
|
return allTreatmentsCondition ? allTreatmentsCondition.partitions.map(v => v.treatment) : [];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function objectToView(
|
|
22
|
-
let splitObject: ISplit | null;
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
// @ts-expect-error
|
|
26
|
-
splitObject = JSON.parse(json);
|
|
27
|
-
} catch (e) {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
|
|
21
|
+
function objectToView(splitObject: ISplit | null): SplitIO.SplitView | null {
|
|
31
22
|
if (!splitObject) return null;
|
|
32
23
|
|
|
33
24
|
return {
|
|
@@ -40,10 +31,10 @@ function objectToView(json: string | null): SplitIO.SplitView | null {
|
|
|
40
31
|
};
|
|
41
32
|
}
|
|
42
33
|
|
|
43
|
-
function objectsToViews(
|
|
34
|
+
function objectsToViews(splitObjects: ISplit[]) {
|
|
44
35
|
let views: SplitIO.SplitView[] = [];
|
|
45
36
|
|
|
46
|
-
|
|
37
|
+
splitObjects.forEach(split => {
|
|
47
38
|
const view = objectToView(split);
|
|
48
39
|
if (view) views.push(view);
|
|
49
40
|
});
|
package/src/services/splitApi.ts
CHANGED
|
@@ -106,28 +106,6 @@ export function splitApiFactory(
|
|
|
106
106
|
const url = `${urls.events}/testImpressions/count`;
|
|
107
107
|
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(IMPRESSIONS_COUNT));
|
|
108
108
|
},
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Post unique keys for client side.
|
|
112
|
-
*
|
|
113
|
-
* @param body unique keys payload
|
|
114
|
-
* @param headers Optionals headers to overwrite default ones. For example, it is used in producer mode to overwrite metadata headers.
|
|
115
|
-
*/
|
|
116
|
-
postUniqueKeysBulkCs(body: string, headers?: Record<string, string>) {
|
|
117
|
-
const url = `${urls.telemetry}/v1/keys/cs`;
|
|
118
|
-
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY));
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Post unique keys for server side.
|
|
123
|
-
*
|
|
124
|
-
* @param body unique keys payload
|
|
125
|
-
* @param headers Optionals headers to overwrite default ones. For example, it is used in producer mode to overwrite metadata headers.
|
|
126
|
-
*/
|
|
127
|
-
postUniqueKeysBulkSs(body: string, headers?: Record<string, string>) {
|
|
128
|
-
const url = `${urls.telemetry}/v1/keys/ss`;
|
|
129
|
-
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY));
|
|
130
|
-
},
|
|
131
109
|
|
|
132
110
|
postMetricsConfig(body: string) {
|
|
133
111
|
const url = `${urls.telemetry}/v1/metrics/config`;
|
package/src/services/types.ts
CHANGED
|
@@ -43,10 +43,6 @@ export type IFetchMySegments = (userMatchingKey: string, noCache?: boolean) => P
|
|
|
43
43
|
|
|
44
44
|
export type IPostEventsBulk = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
45
45
|
|
|
46
|
-
export type IPostUniqueKeysBulkCs = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
47
|
-
|
|
48
|
-
export type IPostUniqueKeysBulkSs = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
49
|
-
|
|
50
46
|
export type IPostTestImpressionsBulk = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
51
47
|
|
|
52
48
|
export type IPostTestImpressionsCount = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
@@ -63,8 +59,6 @@ export interface ISplitApi {
|
|
|
63
59
|
fetchSegmentChanges: IFetchSegmentChanges
|
|
64
60
|
fetchMySegments: IFetchMySegments
|
|
65
61
|
postEventsBulk: IPostEventsBulk
|
|
66
|
-
postUniqueKeysBulkCs: IPostUniqueKeysBulkCs
|
|
67
|
-
postUniqueKeysBulkSs: IPostUniqueKeysBulkSs
|
|
68
62
|
postTestImpressionsBulk: IPostTestImpressionsBulk
|
|
69
63
|
postTestImpressionsCount: IPostTestImpressionsCount
|
|
70
64
|
postMetricsConfig: IPostMetricsConfig
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ISplitsCacheAsync } from './types';
|
|
2
2
|
import { ISplit } from '../dtos/types';
|
|
3
|
+
import { objectAssign } from '../utils/lang/objectAssign';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* This class provides a skeletal implementation of the ISplitsCacheAsync interface
|
|
@@ -7,14 +8,15 @@ import { ISplit } from '../dtos/types';
|
|
|
7
8
|
*/
|
|
8
9
|
export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
abstract
|
|
11
|
+
// Implement addSplits and removeSplits here and others like AbstractSplitsCacheSync, to reuse code between redis and pluggable implementations
|
|
12
|
+
abstract addSplit(name: string, split: ISplit): Promise<boolean>
|
|
13
|
+
abstract addSplits(entries: [string, ISplit][]): Promise<boolean[] | void>
|
|
12
14
|
abstract removeSplits(names: string[]): Promise<boolean[] | void>
|
|
13
|
-
abstract getSplit(name: string): Promise<
|
|
14
|
-
abstract getSplits(names: string[]): Promise<Record<string,
|
|
15
|
+
abstract getSplit(name: string): Promise<ISplit | null>
|
|
16
|
+
abstract getSplits(names: string[]): Promise<Record<string, ISplit | null>>
|
|
15
17
|
abstract setChangeNumber(changeNumber: number): Promise<boolean | void>
|
|
16
18
|
abstract getChangeNumber(): Promise<number>
|
|
17
|
-
abstract getAll(): Promise<
|
|
19
|
+
abstract getAll(): Promise<ISplit[]>
|
|
18
20
|
abstract getSplitNames(): Promise<string[]>
|
|
19
21
|
abstract trafficTypeExists(trafficType: string): Promise<boolean>
|
|
20
22
|
abstract clear(): Promise<boolean | void>
|
|
@@ -47,16 +49,13 @@ export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
|
|
|
47
49
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean> {
|
|
48
50
|
return this.getSplit(name).then(split => {
|
|
49
51
|
|
|
50
|
-
if (split) {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
parsedSplit.changeNumber = changeNumber;
|
|
56
|
-
const newSplit = JSON.stringify(parsedSplit);
|
|
52
|
+
if (split && (!split.changeNumber || split.changeNumber < changeNumber)) {
|
|
53
|
+
const newSplit = objectAssign({}, split);
|
|
54
|
+
newSplit.killed = true;
|
|
55
|
+
newSplit.defaultTreatment = defaultTreatment;
|
|
56
|
+
newSplit.changeNumber = changeNumber;
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
}
|
|
58
|
+
return this.addSplit(name, newSplit);
|
|
60
59
|
}
|
|
61
60
|
return false;
|
|
62
61
|
}).catch(() => false);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ISplitsCacheSync } from './types';
|
|
2
2
|
import { ISplit } from '../dtos/types';
|
|
3
|
+
import { objectAssign } from '../utils/lang/objectAssign';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* This class provides a skeletal implementation of the ISplitsCacheSync interface
|
|
@@ -7,9 +8,9 @@ import { ISplit } from '../dtos/types';
|
|
|
7
8
|
*/
|
|
8
9
|
export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
9
10
|
|
|
10
|
-
abstract addSplit(name: string, split:
|
|
11
|
+
abstract addSplit(name: string, split: ISplit): boolean
|
|
11
12
|
|
|
12
|
-
addSplits(entries: [string,
|
|
13
|
+
addSplits(entries: [string, ISplit][]): boolean[] {
|
|
13
14
|
return entries.map(keyValuePair => this.addSplit(keyValuePair[0], keyValuePair[1]));
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -19,10 +20,10 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
19
20
|
return names.map(name => this.removeSplit(name));
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
abstract getSplit(name: string):
|
|
23
|
+
abstract getSplit(name: string): ISplit | null
|
|
23
24
|
|
|
24
|
-
getSplits(names: string[]): Record<string,
|
|
25
|
-
const splits: Record<string,
|
|
25
|
+
getSplits(names: string[]): Record<string, ISplit | null> {
|
|
26
|
+
const splits: Record<string, ISplit | null> = {};
|
|
26
27
|
names.forEach(name => {
|
|
27
28
|
splits[name] = this.getSplit(name);
|
|
28
29
|
});
|
|
@@ -33,8 +34,8 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
33
34
|
|
|
34
35
|
abstract getChangeNumber(): number
|
|
35
36
|
|
|
36
|
-
getAll():
|
|
37
|
-
return this.getSplitNames().map(key => this.getSplit(key) as
|
|
37
|
+
getAll(): ISplit[] {
|
|
38
|
+
return this.getSplitNames().map(key => this.getSplit(key) as ISplit);
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
abstract getSplitNames(): string[]
|
|
@@ -66,16 +67,13 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
66
67
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean {
|
|
67
68
|
const split = this.getSplit(name);
|
|
68
69
|
|
|
69
|
-
if (split) {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
parsedSplit.changeNumber = changeNumber;
|
|
75
|
-
const newSplit = JSON.stringify(parsedSplit);
|
|
70
|
+
if (split && (!split.changeNumber || split.changeNumber < changeNumber)) {
|
|
71
|
+
const newSplit = objectAssign({}, split);
|
|
72
|
+
newSplit.killed = true;
|
|
73
|
+
newSplit.defaultTreatment = defaultTreatment;
|
|
74
|
+
newSplit.changeNumber = changeNumber;
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
}
|
|
76
|
+
return this.addSplit(name, newSplit);
|
|
79
77
|
}
|
|
80
78
|
return false;
|
|
81
79
|
}
|
|
@@ -27,14 +27,6 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
27
27
|
return `${this.prefix}.impressions`;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
buildImpressionsCountKey() {
|
|
31
|
-
return `${this.prefix}.impressions.count`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
buildUniqueKeysKey() {
|
|
35
|
-
return `${this.prefix}.uniquekeys`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
30
|
buildEventsKey() {
|
|
39
31
|
return `${this.prefix}.events`;
|
|
40
32
|
}
|
|
@@ -39,7 +39,7 @@ export function dataLoaderFactory(preloadedData: SplitIO.PreloadedData): DataLoa
|
|
|
39
39
|
storage.splits.setChangeNumber(since);
|
|
40
40
|
|
|
41
41
|
// splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data
|
|
42
|
-
storage.splits.addSplits(Object.keys(splitsData).map(splitName =>
|
|
42
|
+
storage.splits.addSplits(Object.keys(splitsData).map(splitName => JSON.parse(splitsData[splitName])));
|
|
43
43
|
|
|
44
44
|
// add mySegments data
|
|
45
45
|
let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
|
|
@@ -38,7 +38,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
38
38
|
else localStorage.removeItem(key);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
private _decrementCounts(split: ISplit) {
|
|
41
|
+
private _decrementCounts(split: ISplit | null) {
|
|
42
42
|
try {
|
|
43
43
|
if (split) {
|
|
44
44
|
if (split.trafficTypeName) {
|
|
@@ -99,18 +99,16 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
99
99
|
this.hasSync = false;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
addSplit(name: string, split:
|
|
102
|
+
addSplit(name: string, split: ISplit) {
|
|
103
103
|
try {
|
|
104
104
|
const splitKey = this.keys.buildSplitKey(name);
|
|
105
105
|
const splitFromLocalStorage = localStorage.getItem(splitKey);
|
|
106
106
|
const previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
|
|
107
107
|
this._decrementCounts(previousSplit);
|
|
108
108
|
|
|
109
|
-
localStorage.setItem(splitKey, split);
|
|
109
|
+
localStorage.setItem(splitKey, JSON.stringify(split));
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
this._incrementCounts(parsedSplit);
|
|
111
|
+
this._incrementCounts(split);
|
|
114
112
|
|
|
115
113
|
return true;
|
|
116
114
|
} catch (e) {
|
|
@@ -124,8 +122,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
124
122
|
const split = this.getSplit(name);
|
|
125
123
|
localStorage.removeItem(this.keys.buildSplitKey(name));
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
this._decrementCounts(parsedSplit);
|
|
125
|
+
this._decrementCounts(split);
|
|
129
126
|
|
|
130
127
|
return true;
|
|
131
128
|
} catch (e) {
|
|
@@ -135,7 +132,8 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
135
132
|
}
|
|
136
133
|
|
|
137
134
|
getSplit(name: string) {
|
|
138
|
-
|
|
135
|
+
const item = localStorage.getItem(this.keys.buildSplitKey(name));
|
|
136
|
+
return item && JSON.parse(item);
|
|
139
137
|
}
|
|
140
138
|
|
|
141
139
|
setChangeNumber(changeNumber: number): boolean {
|
|
@@ -184,7 +182,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
184
182
|
return n;
|
|
185
183
|
}
|
|
186
184
|
|
|
187
|
-
getSplitNames() {
|
|
185
|
+
getSplitNames(): string[] {
|
|
188
186
|
const len = localStorage.length;
|
|
189
187
|
const accum = [];
|
|
190
188
|
|