@splitsoftware/splitio-commons 1.6.2-rc.0 → 1.6.2-rc.1
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/listeners/browser.js +2 -1
- package/cjs/logger/constants.js +2 -1
- package/cjs/sdkFactory/index.js +13 -5
- package/cjs/services/splitApi.js +20 -0
- package/cjs/sync/submitters/submitterManager.js +3 -0
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +70 -0
- package/cjs/trackers/impressionsTracker.js +7 -28
- package/cjs/trackers/strategy/strategyDebug.js +25 -0
- package/cjs/trackers/strategy/strategyNone.js +29 -0
- package/cjs/trackers/strategy/strategyOptimized.js +34 -0
- package/cjs/trackers/uniqueKeysTracker.js +69 -0
- package/cjs/utils/constants/index.js +3 -2
- package/cjs/utils/settingsValidation/impressionsMode.js +2 -2
- package/cjs/utils/settingsValidation/index.js +3 -0
- package/esm/listeners/browser.js +3 -2
- package/esm/logger/constants.js +1 -0
- package/esm/sdkFactory/index.js +13 -5
- package/esm/services/splitApi.js +20 -0
- package/esm/sync/submitters/submitterManager.js +3 -0
- package/esm/sync/submitters/uniqueKeysSubmitter.js +64 -0
- package/esm/trackers/impressionsTracker.js +7 -28
- package/esm/trackers/strategy/strategyDebug.js +21 -0
- package/esm/trackers/strategy/strategyNone.js +25 -0
- package/esm/trackers/strategy/strategyOptimized.js +30 -0
- package/esm/trackers/uniqueKeysTracker.js +65 -0
- package/esm/utils/constants/index.js +1 -0
- package/esm/utils/settingsValidation/impressionsMode.js +3 -3
- package/esm/utils/settingsValidation/index.js +3 -0
- package/package.json +1 -1
- package/src/listeners/browser.ts +3 -2
- package/src/logger/constants.ts +1 -0
- package/src/sdkFactory/index.ts +15 -5
- package/src/sdkFactory/types.ts +7 -4
- package/src/services/splitApi.ts +22 -0
- package/src/services/types.ts +6 -0
- package/src/storages/types.ts +17 -4
- package/src/sync/submitters/submitterManager.ts +2 -0
- package/src/sync/submitters/types.ts +20 -1
- package/src/sync/submitters/uniqueKeysSubmitter.ts +79 -0
- package/src/trackers/impressionsTracker.ts +12 -34
- package/src/trackers/strategy/strategyDebug.ts +28 -0
- package/src/trackers/strategy/strategyNone.ts +34 -0
- package/src/trackers/strategy/strategyOptimized.ts +42 -0
- package/src/trackers/types.ts +30 -0
- package/src/trackers/uniqueKeysTracker.ts +80 -0
- package/src/types.ts +2 -1
- package/src/utils/constants/index.ts +1 -0
- package/src/utils/settingsValidation/impressionsMode.ts +3 -3
- package/src/utils/settingsValidation/index.ts +4 -0
- package/types/logger/browser/{debugLogger.d.ts → DebugLogger.d.ts} +0 -0
- package/types/logger/browser/{errorLogger.d.ts → ErrorLogger.d.ts} +0 -0
- package/types/logger/browser/{infoLogger.d.ts → InfoLogger.d.ts} +0 -0
- package/types/logger/browser/{warnLogger.d.ts → WarnLogger.d.ts} +0 -0
- package/types/logger/constants.d.ts +1 -0
- package/types/sdkFactory/types.d.ts +4 -2
- package/types/services/types.d.ts +4 -0
- package/types/storages/types.d.ts +16 -3
- package/types/sync/submitters/types.d.ts +18 -1
- package/types/sync/submitters/uniqueKeysSubmitter.d.ts +10 -4
- package/types/trackers/filter/bloomFilter.d.ts +10 -0
- package/types/trackers/filter/dictionaryFilter.d.ts +8 -0
- package/types/trackers/filter/types.d.ts +5 -0
- package/types/trackers/impressionsTracker.d.ts +4 -6
- package/types/trackers/types.d.ts +29 -0
- package/types/types.d.ts +2 -1
- package/types/utils/constants/index.d.ts +1 -0
- package/types/utils/settingsValidation/index.d.ts +1 -0
- package/types/utils/timeTracker/index.d.ts +70 -1
- package/src/logger/.DS_Store +0 -0
- package/src/splitio.d.ts +0 -1602
- package/types/integrations/ga/GaToSplitPlugin.d.ts +0 -3
- package/types/integrations/ga/SplitToGaPlugin.d.ts +0 -4
- package/types/integrations/ga/autoRequire.d.ts +0 -4
- package/types/logger/codes.d.ts +0 -2
- package/types/logger/codesConstants.d.ts +0 -117
- package/types/logger/codesConstantsBrowser.d.ts +0 -2
- package/types/logger/codesConstantsNode.d.ts +0 -14
- package/types/logger/codesDebug.d.ts +0 -1
- package/types/logger/codesDebugBrowser.d.ts +0 -1
- package/types/logger/codesDebugNode.d.ts +0 -1
- package/types/logger/codesError.d.ts +0 -1
- package/types/logger/codesErrorNode.d.ts +0 -1
- package/types/logger/codesInfo.d.ts +0 -1
- package/types/logger/codesWarn.d.ts +0 -1
- package/types/logger/codesWarnNode.d.ts +0 -1
- package/types/logger/debugLogger.d.ts +0 -2
- package/types/logger/errorLogger.d.ts +0 -2
- package/types/logger/infoLogger.d.ts +0 -2
- package/types/logger/messages/debugBrowser.d.ts +0 -1
- package/types/logger/messages/debugNode.d.ts +0 -1
- package/types/logger/messages/errorNode.d.ts +0 -1
- package/types/logger/messages/warnNode.d.ts +0 -1
- package/types/logger/noopLogger.d.ts +0 -2
- package/types/logger/warnLogger.d.ts +0 -2
- package/types/sdkFactory/userConsentProps.d.ts +0 -6
- package/types/sdkManager/sdkManagerMethod.d.ts +0 -6
- package/types/storages/getRegisteredSegments.d.ts +0 -10
- package/types/storages/inMemory/index.d.ts +0 -10
- package/types/storages/parseSegments.d.ts +0 -6
- package/types/sync/polling/syncTasks/splitsSyncTask.copy.d.ts +0 -35
- package/types/sync/polling/syncTasks/splitsSyncTask.morelikeoriginal.d.ts +0 -35
- package/types/sync/streaming/AuthClient/indexV1.d.ts +0 -12
- package/types/sync/streaming/AuthClient/indexV2.d.ts +0 -8
- package/types/sync/streaming/pushManagerCS.d.ts +0 -1
- package/types/sync/streaming/pushManagerNoUsers.d.ts +0 -13
- package/types/sync/streaming/pushManagerSS.d.ts +0 -1
- package/types/sync/submitters/telemetrySyncTask.d.ts +0 -0
- package/types/sync/syncManagerFromFile.d.ts +0 -2
- package/types/sync/syncManagerFromObject.d.ts +0 -2
- package/types/sync/syncManagerOffline.d.ts +0 -9
- package/types/trackers/telemetryRecorder.d.ts +0 -0
- package/types/utils/EventEmitter.d.ts +0 -4
- package/types/utils/consent.d.ts +0 -2
- package/types/utils/lang/errors.d.ts +0 -10
- package/types/utils/murmur3/commons.d.ts +0 -12
- package/types/utils/settingsValidation/buildMetadata.d.ts +0 -3
- package/types/utils/settingsValidation/localhost/index.d.ts +0 -9
- package/types/utils/settingsValidation/logger.d.ts +0 -11
- package/types/utils/settingsValidation/runtime/browser.d.ts +0 -2
- package/types/utils/settingsValidation/runtime/node.d.ts +0 -2
- package/types/utils/settingsValidation/userConsent.d.ts +0 -5
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { setToArray } from '../../utils/lang/sets';
|
|
2
|
+
import { submitterFactory } from './submitter';
|
|
3
|
+
/**
|
|
4
|
+
* Invert keys for feature to features for key
|
|
5
|
+
*/
|
|
6
|
+
function invertUniqueKeys(uniqueKeys) {
|
|
7
|
+
var featureNames = Object.keys(uniqueKeys);
|
|
8
|
+
var inverted = {};
|
|
9
|
+
for (var i = 0; i < featureNames.length; i++) {
|
|
10
|
+
var featureName = featureNames[i];
|
|
11
|
+
var featureKeys = setToArray(uniqueKeys[featureName]);
|
|
12
|
+
for (var j = 0; j < featureKeys.length; j++) {
|
|
13
|
+
var featureKey = featureKeys[j];
|
|
14
|
+
if (!inverted[featureKey])
|
|
15
|
+
inverted[featureKey] = [];
|
|
16
|
+
inverted[featureKey].push(featureName);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return inverted;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Converts `uniqueKeys` data from cache into request payload for CS.
|
|
23
|
+
*/
|
|
24
|
+
export function fromUniqueKeysCollectorCs(uniqueKeys) {
|
|
25
|
+
var payload = [];
|
|
26
|
+
var featuresPerKey = invertUniqueKeys(uniqueKeys);
|
|
27
|
+
var keys = Object.keys(featuresPerKey);
|
|
28
|
+
for (var k = 0; k < keys.length; k++) {
|
|
29
|
+
var key = keys[k];
|
|
30
|
+
var uniqueKeysPayload = {
|
|
31
|
+
k: key,
|
|
32
|
+
fs: featuresPerKey[key]
|
|
33
|
+
};
|
|
34
|
+
payload.push(uniqueKeysPayload);
|
|
35
|
+
}
|
|
36
|
+
return { keys: payload };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Converts `uniqueKeys` data from cache into request payload for SS.
|
|
40
|
+
*/
|
|
41
|
+
export function fromUniqueKeysCollectorSs(uniqueKeys) {
|
|
42
|
+
var payload = [];
|
|
43
|
+
var featureNames = Object.keys(uniqueKeys);
|
|
44
|
+
for (var i = 0; i < featureNames.length; i++) {
|
|
45
|
+
var featureName = featureNames[i];
|
|
46
|
+
var featureKeys = setToArray(uniqueKeys[featureName]);
|
|
47
|
+
var uniqueKeysPayload = {
|
|
48
|
+
f: featureName,
|
|
49
|
+
ks: featureKeys
|
|
50
|
+
};
|
|
51
|
+
payload.push(uniqueKeysPayload);
|
|
52
|
+
}
|
|
53
|
+
return { keys: payload };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Submitter that periodically posts impression counts
|
|
57
|
+
*/
|
|
58
|
+
export function uniqueKeysSubmitterFactory(params) {
|
|
59
|
+
var _a = params.settings, log = _a.log, uniqueKeysRefreshRate = _a.scheduler.uniqueKeysRefreshRate, key = _a.core.key, _b = params.splitApi, postUniqueKeysBulkCs = _b.postUniqueKeysBulkCs, postUniqueKeysBulkSs = _b.postUniqueKeysBulkSs, uniqueKeys = params.storage.uniqueKeys;
|
|
60
|
+
var isClientSide = key !== undefined;
|
|
61
|
+
var postUniqueKeysBulk = isClientSide ? postUniqueKeysBulkCs : postUniqueKeysBulkSs;
|
|
62
|
+
var fromUniqueKeysCollector = isClientSide ? fromUniqueKeysCollectorCs : fromUniqueKeysCollectorSs;
|
|
63
|
+
return submitterFactory(log, postUniqueKeysBulk, uniqueKeys, uniqueKeysRefreshRate, 'unique keys', fromUniqueKeysCollector);
|
|
64
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
|
-
import { truncateTimeFrame } from '../utils/time';
|
|
4
3
|
import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER } from '../logger/constants';
|
|
5
4
|
import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants';
|
|
6
5
|
/**
|
|
@@ -10,37 +9,17 @@ import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants';
|
|
|
10
9
|
* @param metadata runtime metadata (ip, hostname and version)
|
|
11
10
|
* @param impressionListener optional impression listener
|
|
12
11
|
* @param integrationsManager optional integrations manager
|
|
13
|
-
* @param
|
|
14
|
-
* @param countsCache optional cache to save impressions count. If provided, impressions will be deduped (OPTIMIZED mode)
|
|
12
|
+
* @param strategy strategy for impressions tracking.
|
|
15
13
|
*/
|
|
16
|
-
export function impressionsTrackerFactory(settings, impressionsCache, integrationsManager,
|
|
17
|
-
// if observer is provided, it implies `shouldAddPreviousTime` flag (i.e., if impressions previous time should be added or not)
|
|
18
|
-
observer,
|
|
19
|
-
// if countsCache is provided, it implies `isOptimized` flag (i.e., if impressions should be deduped or not)
|
|
20
|
-
countsCache, telemetryCache) {
|
|
14
|
+
export function impressionsTrackerFactory(settings, impressionsCache, strategy, integrationsManager, telemetryCache) {
|
|
21
15
|
var log = settings.log, impressionListener = settings.impressionListener, _a = settings.runtime, ip = _a.ip, hostname = _a.hostname, version = settings.version;
|
|
22
16
|
return {
|
|
23
17
|
track: function (impressions, attributes) {
|
|
24
18
|
if (settings.userConsent === CONSENT_DECLINED)
|
|
25
19
|
return;
|
|
26
20
|
var impressionsCount = impressions.length;
|
|
27
|
-
var
|
|
28
|
-
|
|
29
|
-
impressions.forEach(function (impression) {
|
|
30
|
-
if (observer) {
|
|
31
|
-
// Adds previous time if it is enabled
|
|
32
|
-
impression.pt = observer.testAndSet(impression);
|
|
33
|
-
}
|
|
34
|
-
var now = Date.now();
|
|
35
|
-
if (countsCache) {
|
|
36
|
-
// Increments impression counter per featureName
|
|
37
|
-
countsCache.track(impression.feature, now, 1);
|
|
38
|
-
}
|
|
39
|
-
// Checks if the impression should be added in queue to be sent
|
|
40
|
-
if (!countsCache || !impression.pt || impression.pt < truncateTimeFrame(now)) {
|
|
41
|
-
impressionsToStore.push(impression);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
21
|
+
var _a = strategy.process(impressions), impressionsToStore = _a.impressionsToStore, impressionsToListener = _a.impressionsToListener, deduped = _a.deduped;
|
|
22
|
+
var impressionsToListenerCount = impressionsToListener.length;
|
|
44
23
|
var res = impressionsCache.track(impressionsToStore);
|
|
45
24
|
// If we're on an async storage, handle error and log it.
|
|
46
25
|
if (thenable(res)) {
|
|
@@ -55,7 +34,7 @@ countsCache, telemetryCache) {
|
|
|
55
34
|
// @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
|
|
56
35
|
if (telemetryCache) {
|
|
57
36
|
telemetryCache.recordImpressionStats(QUEUED, impressionsToStore.length);
|
|
58
|
-
telemetryCache.recordImpressionStats(DEDUPED,
|
|
37
|
+
telemetryCache.recordImpressionStats(DEDUPED, deduped);
|
|
59
38
|
}
|
|
60
39
|
}
|
|
61
40
|
// @TODO next block might be handled by the integration manager. In that case, the metadata object doesn't need to be passed in the constructor
|
|
@@ -63,7 +42,7 @@ countsCache, telemetryCache) {
|
|
|
63
42
|
var _loop_1 = function (i) {
|
|
64
43
|
var impressionData = {
|
|
65
44
|
// copy of impression, to avoid unexpected behaviour if modified by integrations or impressionListener
|
|
66
|
-
impression: objectAssign({},
|
|
45
|
+
impression: objectAssign({}, impressionsToListener[i]),
|
|
67
46
|
attributes: attributes,
|
|
68
47
|
ip: ip,
|
|
69
48
|
hostname: hostname,
|
|
@@ -83,7 +62,7 @@ countsCache, telemetryCache) {
|
|
|
83
62
|
}
|
|
84
63
|
}, 0);
|
|
85
64
|
};
|
|
86
|
-
for (var i = 0; i <
|
|
65
|
+
for (var i = 0; i < impressionsToListenerCount; i++) {
|
|
87
66
|
_loop_1(i);
|
|
88
67
|
}
|
|
89
68
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
3
|
+
*
|
|
4
|
+
* @param impressionsObserver impression observer. Previous time (pt property) is included in impression instances
|
|
5
|
+
* @returns IStrategyResult
|
|
6
|
+
*/
|
|
7
|
+
export function strategyDebugFactory(impressionsObserver) {
|
|
8
|
+
return {
|
|
9
|
+
process: function (impressions) {
|
|
10
|
+
impressions.forEach(function (impression) {
|
|
11
|
+
// Adds previous time if it is enabled
|
|
12
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
impressionsToStore: impressions,
|
|
16
|
+
impressionsToListener: impressions,
|
|
17
|
+
deduped: 0
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* None strategy for impressions tracker.
|
|
3
|
+
*
|
|
4
|
+
* @param impressionsCounter cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
5
|
+
* @param uniqueKeysTracker unique keys tracker in charge of tracking the unique keys per split.
|
|
6
|
+
* @returns IStrategyResult
|
|
7
|
+
*/
|
|
8
|
+
export function strategyNoneFactory(impressionsCounter, uniqueKeysTracker) {
|
|
9
|
+
return {
|
|
10
|
+
process: function (impressions) {
|
|
11
|
+
impressions.forEach(function (impression) {
|
|
12
|
+
var now = Date.now();
|
|
13
|
+
// Increments impression counter per featureName
|
|
14
|
+
impressionsCounter.track(impression.feature, now, 1);
|
|
15
|
+
// Keep track by unique key
|
|
16
|
+
uniqueKeysTracker.track(impression.feature, impression.keyName);
|
|
17
|
+
});
|
|
18
|
+
return {
|
|
19
|
+
impressionsToStore: [],
|
|
20
|
+
impressionsToListener: impressions,
|
|
21
|
+
deduped: 0
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { truncateTimeFrame } from '../../utils/time';
|
|
2
|
+
/**
|
|
3
|
+
* Optimized strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
4
|
+
*
|
|
5
|
+
* @param impressionsObserver impression observer. previous time (pt property) is included in impression instances
|
|
6
|
+
* @param impressionsCounter cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
7
|
+
* @returns IStrategyResult
|
|
8
|
+
*/
|
|
9
|
+
export function strategyOptimizedFactory(impressionsObserver, impressionsCounter) {
|
|
10
|
+
return {
|
|
11
|
+
process: function (impressions) {
|
|
12
|
+
var impressionsToStore = [];
|
|
13
|
+
impressions.forEach(function (impression) {
|
|
14
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
15
|
+
var now = Date.now();
|
|
16
|
+
// Increments impression counter per featureName
|
|
17
|
+
impressionsCounter.track(impression.feature, now, 1);
|
|
18
|
+
// Checks if the impression should be added in queue to be sent
|
|
19
|
+
if (!impression.pt || impression.pt < truncateTimeFrame(now)) {
|
|
20
|
+
impressionsToStore.push(impression);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
impressionsToStore: impressionsToStore,
|
|
25
|
+
impressionsToListener: impressions,
|
|
26
|
+
deduped: impressions.length - impressionsToStore.length
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { LOG_PREFIX_UNIQUE_KEYS_TRACKER } from '../logger/constants';
|
|
2
|
+
import { _Set } from '../utils/lang/sets';
|
|
3
|
+
var noopFilterAdapter = {
|
|
4
|
+
add: function () { return true; },
|
|
5
|
+
contains: function () { return true; },
|
|
6
|
+
clear: function () { }
|
|
7
|
+
};
|
|
8
|
+
var DEFAULT_CACHE_SIZE = 30000;
|
|
9
|
+
/**
|
|
10
|
+
* Trackes uniques keys
|
|
11
|
+
* Unique Keys Tracker will be in charge of checking if the MTK was already sent to the BE in the last period
|
|
12
|
+
* or schedule to be sent; if not it will be added in an internal cache and sent in the next post.
|
|
13
|
+
*
|
|
14
|
+
* @param log Logger instance
|
|
15
|
+
* @param filterAdapter filter adapter
|
|
16
|
+
* @param cacheSize optional internal cache size
|
|
17
|
+
* @param maxBulkSize optional max MTKs bulk size
|
|
18
|
+
*/
|
|
19
|
+
export function uniqueKeysTrackerFactory(log, filterAdapter, cacheSize) {
|
|
20
|
+
if (filterAdapter === void 0) { filterAdapter = noopFilterAdapter; }
|
|
21
|
+
if (cacheSize === void 0) { cacheSize = DEFAULT_CACHE_SIZE; }
|
|
22
|
+
var uniqueKeysTracker = {};
|
|
23
|
+
var uniqueTrackerSize = 0;
|
|
24
|
+
return {
|
|
25
|
+
track: function (featureName, key) {
|
|
26
|
+
if (!filterAdapter.add(featureName, key)) {
|
|
27
|
+
log.debug(LOG_PREFIX_UNIQUE_KEYS_TRACKER + "The feature " + featureName + " and key " + key + " exist in the filter");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!uniqueKeysTracker[featureName])
|
|
31
|
+
uniqueKeysTracker[featureName] = new _Set();
|
|
32
|
+
var tracker = uniqueKeysTracker[featureName];
|
|
33
|
+
if (!tracker.has(key)) {
|
|
34
|
+
tracker.add(key);
|
|
35
|
+
log.debug(LOG_PREFIX_UNIQUE_KEYS_TRACKER + "Key " + key + " added to feature " + featureName);
|
|
36
|
+
uniqueTrackerSize++;
|
|
37
|
+
}
|
|
38
|
+
if (uniqueTrackerSize >= cacheSize) {
|
|
39
|
+
log.warn(LOG_PREFIX_UNIQUE_KEYS_TRACKER + "The UniqueKeysTracker size reached the maximum limit");
|
|
40
|
+
// @TODO trigger event to submitter to send mtk
|
|
41
|
+
uniqueTrackerSize = 0;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
* Pop the collected data, used as payload for posting.
|
|
46
|
+
*/
|
|
47
|
+
pop: function () {
|
|
48
|
+
var data = uniqueKeysTracker;
|
|
49
|
+
uniqueKeysTracker = {};
|
|
50
|
+
return data;
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Clear the data stored on the cache.
|
|
54
|
+
*/
|
|
55
|
+
clear: function () {
|
|
56
|
+
uniqueKeysTracker = {};
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Check if the cache is empty.
|
|
60
|
+
*/
|
|
61
|
+
isEmpty: function () {
|
|
62
|
+
return Object.keys(uniqueKeysTracker).length === 0;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -13,6 +13,7 @@ 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';
|
|
16
17
|
// SDK Modes
|
|
17
18
|
export var LOCALHOST_MODE = 'localhost';
|
|
18
19
|
export var STANDALONE_MODE = 'standalone';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
|
|
2
|
-
import { DEBUG, OPTIMIZED } from '../constants';
|
|
2
|
+
import { DEBUG, OPTIMIZED, NONE } from '../constants';
|
|
3
3
|
import { stringToUpperCase } from '../lang';
|
|
4
4
|
export function validImpressionsMode(log, impressionsMode) {
|
|
5
5
|
impressionsMode = stringToUpperCase(impressionsMode);
|
|
6
|
-
if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) > -1)
|
|
6
|
+
if ([DEBUG, OPTIMIZED, NONE].indexOf(impressionsMode) > -1)
|
|
7
7
|
return impressionsMode;
|
|
8
|
-
log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED], OPTIMIZED]);
|
|
8
|
+
log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED, NONE], OPTIMIZED]);
|
|
9
9
|
return OPTIMIZED;
|
|
10
10
|
}
|
|
@@ -31,6 +31,8 @@ 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,
|
|
34
36
|
// fetch offline changes each 15 sec
|
|
35
37
|
offlineRefreshRate: 15,
|
|
36
38
|
// publish events every 60 seconds after the first flush
|
|
@@ -109,6 +111,7 @@ export function settingsValidation(config, validationParams) {
|
|
|
109
111
|
scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
|
|
110
112
|
scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
|
|
111
113
|
scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
|
|
114
|
+
scheduler.uniqueKeysRefreshRate = fromSecondsToMillis(scheduler.uniqueKeysRefreshRate);
|
|
112
115
|
scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
|
|
113
116
|
// Default impressionsRefreshRate for DEBUG mode is 60 secs
|
|
114
117
|
if (get(config, 'scheduler.impressionsRefreshRate') === undefined && withDefaults.sync.impressionsMode === DEBUG)
|
package/package.json
CHANGED
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 } from '../utils/constants';
|
|
10
|
+
import { OPTIMIZED, DEBUG, NONE } 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,9 +88,10 @@ 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;
|
|
91
92
|
const extraMetadata = {
|
|
92
93
|
// sim stands for Sync/Split Impressions Mode
|
|
93
|
-
sim:
|
|
94
|
+
sim: sim === OPTIMIZED ? OPTIMIZED : sim === DEBUG ? DEBUG : NONE
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
|
package/src/logger/constants.ts
CHANGED
|
@@ -143,4 +143,5 @@ 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: ';
|
|
146
147
|
export const LOG_PREFIX_CLEANUP = 'cleanup: ';
|
package/src/sdkFactory/index.ts
CHANGED
|
@@ -13,6 +13,11 @@ 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 } from '../utils/constants';
|
|
16
21
|
|
|
17
22
|
/**
|
|
18
23
|
* Modular SDK factory
|
|
@@ -21,8 +26,10 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
21
26
|
|
|
22
27
|
const { settings, platform, storageFactory, splitApiFactory, extraProps,
|
|
23
28
|
syncManagerFactory, SignalListener, impressionsObserverFactory,
|
|
24
|
-
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory
|
|
29
|
+
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory,
|
|
30
|
+
filterAdapterFactory } = params;
|
|
25
31
|
const log = settings.log;
|
|
32
|
+
const impressionsMode = settings.sync.impressionsMode;
|
|
26
33
|
|
|
27
34
|
// @TODO handle non-recoverable errors, such as, global `fetch` not available, invalid API Key, etc.
|
|
28
35
|
// On non-recoverable errors, we should mark the SDK as destroyed and not start synchronization.
|
|
@@ -62,16 +69,19 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
62
69
|
|
|
63
70
|
const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage });
|
|
64
71
|
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
const
|
|
72
|
+
const observer = impressionsObserverFactory();
|
|
73
|
+
const uniqueKeysTracker = impressionsMode === NONE ? uniqueKeysTrackerFactory(log, filterAdapterFactory && filterAdapterFactory()) : undefined;
|
|
74
|
+
const strategy = (storageFactoryParams.optimize) ? strategyOptimizedFactory(observer, storage.impressionCounts!) :
|
|
75
|
+
(impressionsMode === NONE) ? strategyNoneFactory(storage.impressionCounts!, uniqueKeysTracker!) : strategyDebugFactory(observer);
|
|
76
|
+
|
|
77
|
+
const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, strategy, integrationsManager, storage.telemetry);
|
|
68
78
|
const eventTracker = eventTrackerFactory(settings, storage.events, integrationsManager, storage.telemetry);
|
|
69
79
|
const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
70
80
|
|
|
71
81
|
// splitApi is used by SyncManager and Browser signal listener
|
|
72
82
|
const splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
|
|
73
83
|
|
|
74
|
-
const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, readiness, settings, storage, platform };
|
|
84
|
+
const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker, uniqueKeysTracker, sdkReadinessManager, readiness, settings, storage, platform };
|
|
75
85
|
|
|
76
86
|
const syncManager = syncManagerFactory && syncManagerFactory(ctx as ISdkFactoryContextSync);
|
|
77
87
|
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 } from '../trackers/types';
|
|
9
|
+
import { IImpressionsTracker, IEventTracker, ITelemetryTracker, IFilterAdapter, IUniqueKeysTracker } from '../trackers/types';
|
|
10
10
|
import { SplitIO, ISettings, IEventEmitter } from '../types';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -44,6 +44,7 @@ export interface ISdkFactoryContext {
|
|
|
44
44
|
eventTracker: IEventTracker,
|
|
45
45
|
telemetryTracker: ITelemetryTracker,
|
|
46
46
|
storage: IStorageSync | IStorageAsync,
|
|
47
|
+
uniqueKeysTracker?: IUniqueKeysTracker,
|
|
47
48
|
signalListener?: ISignalListener
|
|
48
49
|
splitApi?: ISplitApi
|
|
49
50
|
syncManager?: ISyncManager,
|
|
@@ -96,6 +97,11 @@ export interface ISdkFactoryParams {
|
|
|
96
97
|
// It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
|
|
97
98
|
sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
|
|
98
99
|
|
|
100
|
+
// Impression observer factory. If provided, will be used for impressions dedupe
|
|
101
|
+
impressionsObserverFactory: () => IImpressionObserver
|
|
102
|
+
|
|
103
|
+
filterAdapterFactory?: () => IFilterAdapter
|
|
104
|
+
|
|
99
105
|
// Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed.
|
|
100
106
|
// Pass only if `syncManager` (used by Node listener) and `splitApi` (used by Browser listener) are passed.
|
|
101
107
|
SignalListener?: new (
|
|
@@ -107,9 +113,6 @@ export interface ISdkFactoryParams {
|
|
|
107
113
|
// @TODO review impressionListener and integrations interfaces. What about handling impressionListener as an integration ?
|
|
108
114
|
integrationsManagerFactory?: (params: IIntegrationFactoryParams) => IIntegrationManager | undefined,
|
|
109
115
|
|
|
110
|
-
// Impression observer factory. If provided, will be used for impressions dedupe
|
|
111
|
-
impressionsObserverFactory?: () => IImpressionObserver
|
|
112
|
-
|
|
113
116
|
// Optional function to assign additional properties to the factory instance
|
|
114
117
|
extraProps?: (params: ISdkFactoryContext) => object
|
|
115
118
|
}
|
package/src/services/splitApi.ts
CHANGED
|
@@ -106,6 +106,28 @@ 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}/api/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}/api/v1/keys/ss`;
|
|
129
|
+
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY));
|
|
130
|
+
},
|
|
109
131
|
|
|
110
132
|
postMetricsConfig(body: string) {
|
|
111
133
|
const url = `${urls.telemetry}/v1/metrics/config`;
|
package/src/services/types.ts
CHANGED
|
@@ -43,6 +43,10 @@ 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
|
+
|
|
46
50
|
export type IPostTestImpressionsBulk = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
47
51
|
|
|
48
52
|
export type IPostTestImpressionsCount = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
@@ -59,6 +63,8 @@ export interface ISplitApi {
|
|
|
59
63
|
fetchSegmentChanges: IFetchSegmentChanges
|
|
60
64
|
fetchMySegments: IFetchMySegments
|
|
61
65
|
postEventsBulk: IPostEventsBulk
|
|
66
|
+
postUniqueKeysBulkCs: IPostUniqueKeysBulkCs
|
|
67
|
+
postUniqueKeysBulkSs: IPostUniqueKeysBulkSs
|
|
62
68
|
postTestImpressionsBulk: IPostTestImpressionsBulk
|
|
63
69
|
postTestImpressionsCount: IPostTestImpressionsCount
|
|
64
70
|
postMetricsConfig: IPostMetricsConfig
|
package/src/storages/types.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { MaybeThenable, IMetadata, ISplitFiltersValidation } from '../dtos/types
|
|
|
2
2
|
import { ILogger } from '../logger/types';
|
|
3
3
|
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent } from '../sync/submitters/types';
|
|
4
4
|
import { SplitIO, ImpressionDTO, SDKMode } from '../types';
|
|
5
|
+
import { ISet } from '../utils/lang/sets';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Interface of a pluggable storage wrapper.
|
|
@@ -355,6 +356,14 @@ export interface IImpressionCountsCacheSync extends IRecorderCacheProducerSync<R
|
|
|
355
356
|
pop(toMerge?: Record<string, number> ): Record<string, number> // pop cache data
|
|
356
357
|
}
|
|
357
358
|
|
|
359
|
+
export interface IUniqueKeysCacheBase extends IRecorderCacheProducerSync<{ [featureName: string]: ISet<string> }>{
|
|
360
|
+
// Used by unique Keys tracker
|
|
361
|
+
track(featureName: string, timeFrame: number, amount: number): void
|
|
362
|
+
|
|
363
|
+
// Used by unique keys submitter in standalone and producer mode
|
|
364
|
+
isEmpty(): boolean // check if cache is empty. Return true if the cache was just created or cleared.
|
|
365
|
+
pop(toMerge?: { [featureName: string]: ISet<string> } ): { [featureName: string]: ISet<string> } // pop cache data
|
|
366
|
+
}
|
|
358
367
|
|
|
359
368
|
/**
|
|
360
369
|
* Telemetry storage interface for standalone and partial consumer modes.
|
|
@@ -445,14 +454,16 @@ export interface IStorageBase<
|
|
|
445
454
|
TSegmentsCache extends ISegmentsCacheBase,
|
|
446
455
|
TImpressionsCache extends IImpressionsCacheBase,
|
|
447
456
|
TEventsCache extends IEventsCacheBase,
|
|
448
|
-
TTelemetryCache extends ITelemetryCacheSync | ITelemetryCacheAsync
|
|
457
|
+
TTelemetryCache extends ITelemetryCacheSync | ITelemetryCacheAsync,
|
|
458
|
+
TUniqueKeysCache extends IUniqueKeysCacheBase
|
|
449
459
|
> {
|
|
450
460
|
splits: TSplitsCache,
|
|
451
461
|
segments: TSegmentsCache,
|
|
452
462
|
impressions: TImpressionsCache,
|
|
453
463
|
impressionCounts?: IImpressionCountsCacheSync,
|
|
454
464
|
events: TEventsCache,
|
|
455
|
-
telemetry?: TTelemetryCache
|
|
465
|
+
telemetry?: TTelemetryCache,
|
|
466
|
+
uniqueKeys?: TUniqueKeysCache,
|
|
456
467
|
destroy(): void | Promise<void>,
|
|
457
468
|
shared?: (matchingKey: string, onReadyCb: (error?: any) => void) => this
|
|
458
469
|
}
|
|
@@ -462,7 +473,8 @@ export interface IStorageSync extends IStorageBase<
|
|
|
462
473
|
ISegmentsCacheSync,
|
|
463
474
|
IImpressionsCacheSync,
|
|
464
475
|
IEventsCacheSync,
|
|
465
|
-
ITelemetryCacheSync
|
|
476
|
+
ITelemetryCacheSync,
|
|
477
|
+
IUniqueKeysCacheBase
|
|
466
478
|
> { }
|
|
467
479
|
|
|
468
480
|
export interface IStorageAsync extends IStorageBase<
|
|
@@ -470,7 +482,8 @@ export interface IStorageAsync extends IStorageBase<
|
|
|
470
482
|
ISegmentsCacheAsync,
|
|
471
483
|
IImpressionsCacheAsync | IImpressionsCacheSync,
|
|
472
484
|
IEventsCacheAsync | IEventsCacheSync,
|
|
473
|
-
ITelemetryCacheAsync
|
|
485
|
+
ITelemetryCacheAsync,
|
|
486
|
+
IUniqueKeysCacheBase
|
|
474
487
|
> { }
|
|
475
488
|
|
|
476
489
|
/** StorageFactory */
|
|
@@ -4,6 +4,7 @@ import { impressionCountsSubmitterFactory } from './impressionCountsSubmitter';
|
|
|
4
4
|
import { telemetrySubmitterFactory } from './telemetrySubmitter';
|
|
5
5
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
6
6
|
import { ISubmitterManager } from './types';
|
|
7
|
+
import { uniqueKeysSubmitterFactory } from './uniqueKeysSubmitter';
|
|
7
8
|
|
|
8
9
|
export function submitterManagerFactory(params: ISdkFactoryContextSync): ISubmitterManager {
|
|
9
10
|
|
|
@@ -15,6 +16,7 @@ export function submitterManagerFactory(params: ISdkFactoryContextSync): ISubmit
|
|
|
15
16
|
const impressionCountsSubmitter = impressionCountsSubmitterFactory(params);
|
|
16
17
|
if (impressionCountsSubmitter) submitters.push(impressionCountsSubmitter);
|
|
17
18
|
const telemetrySubmitter = telemetrySubmitterFactory(params);
|
|
19
|
+
if (params.uniqueKeysTracker) submitters.push(uniqueKeysSubmitterFactory(params));
|
|
18
20
|
|
|
19
21
|
return {
|
|
20
22
|
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
@@ -35,6 +35,24 @@ export type ImpressionCountsPayload = {
|
|
|
35
35
|
}[]
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export type UniqueKeysPayloadSs = {
|
|
39
|
+
keys: {
|
|
40
|
+
/** Split name */
|
|
41
|
+
f: string
|
|
42
|
+
/** keyNames */
|
|
43
|
+
ks: string[]
|
|
44
|
+
}[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type UniqueKeysPayloadCs = {
|
|
48
|
+
keys: {
|
|
49
|
+
/** keyNames */
|
|
50
|
+
k: string
|
|
51
|
+
/** Split name */
|
|
52
|
+
fs: string[]
|
|
53
|
+
}[]
|
|
54
|
+
}
|
|
55
|
+
|
|
38
56
|
export type StoredImpressionWithMetadata = {
|
|
39
57
|
/** Metadata */
|
|
40
58
|
m: IMetadata,
|
|
@@ -148,7 +166,8 @@ export type OperationMode = STANDALONE_ENUM | CONSUMER_ENUM | CONSUMER_PARTIAL_E
|
|
|
148
166
|
|
|
149
167
|
export type OPTIMIZED_ENUM = 0;
|
|
150
168
|
export type DEBUG_ENUM = 1;
|
|
151
|
-
export type
|
|
169
|
+
export type NONE_ENUM = 2;
|
|
170
|
+
export type ImpressionsMode = OPTIMIZED_ENUM | DEBUG_ENUM | NONE_ENUM;
|
|
152
171
|
|
|
153
172
|
export type RefreshRates = {
|
|
154
173
|
sp: number, // splits
|