@splitsoftware/splitio-commons 1.2.1-rc.3 → 1.2.1-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/listeners/browser.js +14 -10
- package/cjs/logger/constants.js +7 -4
- package/cjs/logger/messages/debug.js +3 -3
- package/cjs/logger/messages/error.js +3 -2
- package/cjs/logger/messages/info.js +5 -3
- package/cjs/sdkClient/client.js +10 -4
- package/cjs/sdkFactory/index.js +6 -4
- package/cjs/sdkFactory/userConsentProps.js +37 -0
- package/cjs/storages/KeyBuilder.js +1 -5
- package/cjs/storages/KeyBuilderCS.js +11 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -3
- package/cjs/storages/inLocalStorage/index.js +1 -1
- package/cjs/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +1 -1
- package/cjs/storages/inMemory/InMemoryStorageCS.js +1 -1
- package/cjs/storages/pluggable/index.js +2 -2
- package/cjs/sync/submitters/eventsSyncTask.js +17 -5
- package/cjs/sync/submitters/impressionsSyncTask.js +13 -1
- package/cjs/sync/syncManagerOnline.js +11 -7
- package/cjs/utils/consent.js +10 -0
- package/cjs/utils/constants/index.js +5 -1
- package/cjs/utils/lang/index.js +8 -1
- package/cjs/utils/settingsValidation/consent.js +16 -0
- package/cjs/utils/settingsValidation/impressionsMode.js +6 -6
- package/cjs/utils/settingsValidation/index.js +6 -1
- package/cjs/utils/settingsValidation/{runtime/browser.js → runtime.js} +1 -0
- package/esm/listeners/browser.js +14 -10
- package/esm/logger/constants.js +5 -2
- package/esm/logger/messages/debug.js +3 -3
- package/esm/logger/messages/error.js +3 -2
- package/esm/logger/messages/info.js +5 -3
- package/esm/sdkClient/client.js +11 -5
- package/esm/sdkFactory/index.js +6 -4
- package/esm/sdkFactory/userConsentProps.js +33 -0
- package/esm/storages/KeyBuilder.js +2 -6
- package/esm/storages/KeyBuilderCS.js +11 -1
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -3
- package/esm/storages/inLocalStorage/index.js +1 -1
- package/esm/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
- package/esm/storages/inMemory/InMemoryStorage.js +1 -1
- package/esm/storages/inMemory/InMemoryStorageCS.js +1 -1
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/sync/submitters/eventsSyncTask.js +18 -6
- package/esm/sync/submitters/impressionsSyncTask.js +13 -1
- package/esm/sync/syncManagerOnline.js +11 -7
- package/esm/utils/consent.js +6 -0
- package/esm/utils/constants/index.js +4 -0
- package/esm/utils/lang/index.js +6 -0
- package/esm/utils/settingsValidation/consent.js +12 -0
- package/esm/utils/settingsValidation/impressionsMode.js +7 -7
- package/esm/utils/settingsValidation/index.js +6 -1
- package/esm/utils/settingsValidation/{runtime/browser.js → runtime.js} +1 -0
- package/package.json +1 -2
- package/src/listeners/browser.ts +13 -9
- package/src/logger/constants.ts +5 -2
- package/src/logger/messages/debug.ts +3 -3
- package/src/logger/messages/error.ts +3 -2
- package/src/logger/messages/info.ts +5 -3
- package/src/sdkClient/client.ts +7 -5
- package/src/sdkFactory/index.ts +6 -4
- package/src/sdkFactory/types.ts +2 -0
- package/src/sdkFactory/userConsentProps.ts +40 -0
- package/src/storages/KeyBuilder.ts +2 -6
- package/src/storages/KeyBuilderCS.ts +13 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +23 -3
- package/src/storages/inLocalStorage/index.ts +1 -1
- package/src/storages/inMemory/ImpressionsCacheInMemory.ts +22 -1
- package/src/storages/inMemory/InMemoryStorage.ts +1 -1
- package/src/storages/inMemory/InMemoryStorageCS.ts +1 -1
- package/src/storages/pluggable/index.ts +2 -2
- package/src/storages/types.ts +5 -1
- package/src/sync/submitters/eventsSyncTask.ts +19 -6
- package/src/sync/submitters/impressionsSyncTask.ts +16 -1
- package/src/sync/syncManagerOnline.ts +13 -7
- package/src/sync/types.ts +4 -1
- package/src/types.ts +21 -0
- package/src/utils/consent.ts +8 -0
- package/src/utils/constants/index.ts +5 -0
- package/src/utils/lang/index.ts +8 -1
- package/src/utils/settingsValidation/consent.ts +15 -0
- package/src/utils/settingsValidation/impressionsMode.ts +8 -8
- package/src/utils/settingsValidation/index.ts +7 -1
- package/src/utils/settingsValidation/runtime.ts +9 -0
- package/src/utils/settingsValidation/types.ts +2 -0
- package/types/logger/constants.d.ts +5 -2
- package/types/sdkFactory/types.d.ts +1 -0
- package/types/sdkFactory/userConsentProps.d.ts +6 -0
- package/types/storages/KeyBuilderCS.d.ts +2 -0
- package/types/storages/inMemory/ImpressionsCacheInMemory.d.ts +9 -0
- package/types/storages/types.d.ts +2 -0
- package/types/sync/types.d.ts +3 -0
- package/types/types.d.ts +21 -0
- package/types/utils/consent.d.ts +2 -0
- package/types/utils/constants/index.d.ts +3 -0
- package/types/utils/lang/index.d.ts +4 -0
- package/types/utils/settingsValidation/consent.d.ts +5 -0
- package/types/utils/settingsValidation/impressionsMode.d.ts +1 -1
- package/types/utils/settingsValidation/runtime.d.ts +2 -0
- package/types/utils/settingsValidation/types.d.ts +2 -0
- package/types/utils/settingsValidation/userConsent.d.ts +5 -0
- package/cjs/utils/settingsValidation/runtime/node.js +0 -22
- package/esm/utils/settingsValidation/runtime/node.js +0 -17
- package/src/utils/settingsValidation/runtime/browser.ts +0 -8
- package/src/utils/settingsValidation/runtime/node.ts +0 -22
package/cjs/utils/lang/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.uniqueId = exports.uniqAsStrings = exports.uniq = exports.toString = exports.toNumber = exports.startsWith = exports.merge = exports.isString = exports.isObject = exports.isNaNNumber = exports.isIntegerNumber = exports.isFiniteNumber = exports.isBoolean = exports.groupBy = exports.get = exports.forOwn = exports.findIndex = exports.find = exports.endsWith = void 0;
|
|
3
|
+
exports.uniqueId = exports.uniqAsStrings = exports.uniq = exports.toString = exports.toNumber = exports.startsWith = exports.merge = exports.stringToUpperCase = exports.isString = exports.isObject = exports.isNaNNumber = exports.isIntegerNumber = exports.isFiniteNumber = exports.isBoolean = exports.groupBy = exports.get = exports.forOwn = exports.findIndex = exports.find = exports.endsWith = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
/**
|
|
6
6
|
* Checks if the target string ends with the sub string.
|
|
@@ -167,6 +167,13 @@ function isString(val) {
|
|
|
167
167
|
return typeof val === 'string' || val instanceof String;
|
|
168
168
|
}
|
|
169
169
|
exports.isString = isString;
|
|
170
|
+
/**
|
|
171
|
+
* String sanitizer. Returns the provided value converted to uppercase if it is a string.
|
|
172
|
+
*/
|
|
173
|
+
function stringToUpperCase(val) {
|
|
174
|
+
return isString(val) ? val.toUpperCase() : val;
|
|
175
|
+
}
|
|
176
|
+
exports.stringToUpperCase = stringToUpperCase;
|
|
170
177
|
/**
|
|
171
178
|
* Deep copy version of Object.assign using recursion.
|
|
172
179
|
* There are some assumptions here. It's for internal use and we don't need verbose errors
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateConsent = void 0;
|
|
4
|
+
var constants_1 = require("../../logger/constants");
|
|
5
|
+
var constants_2 = require("../constants");
|
|
6
|
+
var lang_1 = require("../lang");
|
|
7
|
+
var userConsentValues = [constants_2.CONSENT_DECLINED, constants_2.CONSENT_GRANTED, constants_2.CONSENT_UNKNOWN];
|
|
8
|
+
function validateConsent(_a) {
|
|
9
|
+
var userConsent = _a.userConsent, log = _a.log;
|
|
10
|
+
userConsent = (0, lang_1.stringToUpperCase)(userConsent);
|
|
11
|
+
if (userConsentValues.indexOf(userConsent) > -1)
|
|
12
|
+
return userConsent;
|
|
13
|
+
log.error(constants_1.ERROR_INVALID_CONFIG_PARAM, ['userConsent', userConsentValues, constants_2.CONSENT_GRANTED]);
|
|
14
|
+
return constants_2.CONSENT_GRANTED;
|
|
15
|
+
}
|
|
16
|
+
exports.validateConsent = validateConsent;
|
|
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.validImpressionsMode = void 0;
|
|
4
4
|
var constants_1 = require("../../logger/constants");
|
|
5
5
|
var constants_2 = require("../constants");
|
|
6
|
+
var lang_1 = require("../lang");
|
|
6
7
|
function validImpressionsMode(log, impressionsMode) {
|
|
7
|
-
impressionsMode =
|
|
8
|
-
if ([constants_2.DEBUG, constants_2.OPTIMIZED].indexOf(impressionsMode)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return impressionsMode;
|
|
8
|
+
impressionsMode = (0, lang_1.stringToUpperCase)(impressionsMode);
|
|
9
|
+
if ([constants_2.DEBUG, constants_2.OPTIMIZED].indexOf(impressionsMode) > -1)
|
|
10
|
+
return impressionsMode;
|
|
11
|
+
log.error(constants_1.ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [constants_2.DEBUG, constants_2.OPTIMIZED], constants_2.OPTIMIZED]);
|
|
12
|
+
return constants_2.OPTIMIZED;
|
|
13
13
|
}
|
|
14
14
|
exports.validImpressionsMode = validImpressionsMode;
|
|
@@ -36,6 +36,8 @@ var base = {
|
|
|
36
36
|
eventsPushRate: 60,
|
|
37
37
|
// how many events will be queued before flushing
|
|
38
38
|
eventsQueueSize: 500,
|
|
39
|
+
// how many impressions will be queued before flushing
|
|
40
|
+
impressionsQueueSize: 30000,
|
|
39
41
|
// backoff base seconds to wait before re attempting to connect to push notifications
|
|
40
42
|
pushRetryBackoffBase: 1,
|
|
41
43
|
},
|
|
@@ -81,7 +83,7 @@ function fromSecondsToMillis(n) {
|
|
|
81
83
|
* @param validationParams defaults and fields validators used to validate and creates a settings object from a given config
|
|
82
84
|
*/
|
|
83
85
|
function settingsValidation(config, validationParams) {
|
|
84
|
-
var defaults = validationParams.defaults, runtime = validationParams.runtime, storage = validationParams.storage, integrations = validationParams.integrations, logger = validationParams.logger, localhost = validationParams.localhost;
|
|
86
|
+
var defaults = validationParams.defaults, runtime = validationParams.runtime, storage = validationParams.storage, integrations = validationParams.integrations, logger = validationParams.logger, localhost = validationParams.localhost, consent = validationParams.consent;
|
|
85
87
|
// creates a settings object merging base, defaults and config objects.
|
|
86
88
|
var withDefaults = (0, lang_1.merge)({}, base, defaults, config);
|
|
87
89
|
// ensure a valid logger.
|
|
@@ -134,6 +136,9 @@ function settingsValidation(config, validationParams) {
|
|
|
134
136
|
withDefaults.sync.__splitFiltersValidation = splitFiltersValidation;
|
|
135
137
|
// ensure a valid impressionsMode
|
|
136
138
|
withDefaults.sync.impressionsMode = (0, impressionsMode_1.validImpressionsMode)(log, withDefaults.sync.impressionsMode);
|
|
139
|
+
// ensure a valid user consent value
|
|
140
|
+
// @ts-ignore, modify readonly prop
|
|
141
|
+
withDefaults.userConsent = consent(withDefaults);
|
|
137
142
|
return withDefaults;
|
|
138
143
|
}
|
|
139
144
|
exports.settingsValidation = settingsValidation;
|
package/esm/listeners/browser.js
CHANGED
|
@@ -3,6 +3,7 @@ import { fromImpressionCountsCollector } from '../sync/submitters/impressionCoun
|
|
|
3
3
|
import { OPTIMIZED, DEBUG } from '../utils/constants';
|
|
4
4
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
5
5
|
import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
|
|
6
|
+
import { isConsentGranted } from '../utils/consent';
|
|
6
7
|
// 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring.
|
|
7
8
|
var UNLOAD_DOM_EVENT = 'unload';
|
|
8
9
|
var EVENT_NAME = 'for unload page event.';
|
|
@@ -48,15 +49,18 @@ var BrowserSignalListener = /** @class */ (function () {
|
|
|
48
49
|
BrowserSignalListener.prototype.flushData = function () {
|
|
49
50
|
if (!this.syncManager)
|
|
50
51
|
return; // In consumer mode there is not sync manager and data to flush
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this._flushData(eventsUrl + '/
|
|
52
|
+
// Flush data if there is user consent
|
|
53
|
+
if (isConsentGranted(this.settings)) {
|
|
54
|
+
var eventsUrl = this.settings.urls.events;
|
|
55
|
+
var extraMetadata = {
|
|
56
|
+
// sim stands for Sync/Split Impressions Mode
|
|
57
|
+
sim: this.settings.sync.impressionsMode === OPTIMIZED ? OPTIMIZED : DEBUG
|
|
58
|
+
};
|
|
59
|
+
this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
|
|
60
|
+
this._flushData(eventsUrl + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
|
|
61
|
+
if (this.storage.impressionCounts)
|
|
62
|
+
this._flushData(eventsUrl + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, fromImpressionCountsCollector);
|
|
63
|
+
}
|
|
60
64
|
// Close streaming connection
|
|
61
65
|
if (this.syncManager.pushManager)
|
|
62
66
|
this.syncManager.pushManager.stop();
|
|
@@ -66,7 +70,7 @@ var BrowserSignalListener = /** @class */ (function () {
|
|
|
66
70
|
if (!cache.isEmpty()) {
|
|
67
71
|
var dataPayload = fromCacheToPayload ? fromCacheToPayload(cache.state()) : cache.state();
|
|
68
72
|
if (!this._sendBeacon(url, dataPayload, extraMetadata)) {
|
|
69
|
-
postService(JSON.stringify(dataPayload)).catch(function () { }); // no-op just to catch a possible
|
|
73
|
+
postService(JSON.stringify(dataPayload)).catch(function () { }); // no-op just to catch a possible exception
|
|
70
74
|
}
|
|
71
75
|
cache.clear();
|
|
72
76
|
}
|
package/esm/logger/constants.js
CHANGED
|
@@ -60,13 +60,15 @@ export var STREAMING_RECONNECT = 111;
|
|
|
60
60
|
export var STREAMING_CONNECTING = 112;
|
|
61
61
|
export var STREAMING_DISABLED = 113;
|
|
62
62
|
export var STREAMING_DISCONNECTING = 114;
|
|
63
|
-
export var
|
|
63
|
+
export var SUBMITTERS_PUSH_FULL_QUEUE = 115;
|
|
64
64
|
export var SUBMITTERS_PUSH = 116;
|
|
65
65
|
export var SYNC_START_POLLING = 117;
|
|
66
66
|
export var SYNC_CONTINUE_POLLING = 118;
|
|
67
67
|
export var SYNC_STOP_POLLING = 119;
|
|
68
68
|
export var EVENTS_TRACKER_SUCCESS = 120;
|
|
69
69
|
export var IMPRESSIONS_TRACKER_SUCCESS = 121;
|
|
70
|
+
export var USER_CONSENT_UPDATED = 122;
|
|
71
|
+
export var USER_CONSENT_NOT_UPDATED = 123;
|
|
70
72
|
export var ENGINE_VALUE_INVALID = 200;
|
|
71
73
|
export var ENGINE_VALUE_NO_ATTRIBUTES = 201;
|
|
72
74
|
export var CLIENT_NO_LISTENER = 202;
|
|
@@ -112,10 +114,11 @@ export var ERROR_INVALID_KEY_OBJECT = 317;
|
|
|
112
114
|
export var ERROR_INVALID = 318;
|
|
113
115
|
export var ERROR_EMPTY = 319;
|
|
114
116
|
export var ERROR_EMPTY_ARRAY = 320;
|
|
115
|
-
export var
|
|
117
|
+
export var ERROR_INVALID_CONFIG_PARAM = 321;
|
|
116
118
|
export var ERROR_HTTP = 322;
|
|
117
119
|
export var ERROR_LOCALHOST_MODULE_REQUIRED = 323;
|
|
118
120
|
export var ERROR_STORAGE_INVALID = 324;
|
|
121
|
+
export var ERROR_NOT_BOOLEAN = 325;
|
|
119
122
|
// Log prefixes (a.k.a. tags or categories)
|
|
120
123
|
export var LOG_PREFIX_SETTINGS = 'settings';
|
|
121
124
|
export var LOG_PREFIX_INSTANTIATION = 'Factory instantiation';
|
|
@@ -30,9 +30,9 @@ export var codesDebug = codesInfo.concat([
|
|
|
30
30
|
// SDK
|
|
31
31
|
[c.CLEANUP_REGISTERING, c.LOG_PREFIX_CLEANUP + 'Registering cleanup handler %s'],
|
|
32
32
|
[c.CLEANUP_DEREGISTERING, c.LOG_PREFIX_CLEANUP + 'Deregistering cleanup handler %s'],
|
|
33
|
-
[c.RETRIEVE_CLIENT_DEFAULT, '
|
|
34
|
-
[c.RETRIEVE_CLIENT_EXISTING, '
|
|
35
|
-
[c.RETRIEVE_MANAGER, '
|
|
33
|
+
[c.RETRIEVE_CLIENT_DEFAULT, 'Retrieving default SDK client.'],
|
|
34
|
+
[c.RETRIEVE_CLIENT_EXISTING, 'Retrieving existing SDK client.'],
|
|
35
|
+
[c.RETRIEVE_MANAGER, 'Retrieving manager instance.'],
|
|
36
36
|
// synchronizer
|
|
37
37
|
[c.SYNC_OFFLINE_DATA, c.LOG_PREFIX_SYNC_OFFLINE + 'Splits data: \n%s'],
|
|
38
38
|
[c.SYNC_SPLITS_FETCH, c.LOG_PREFIX_SYNC_SPLITS + 'Spin up split update using since = %s'],
|
|
@@ -4,7 +4,7 @@ export var codesError = [
|
|
|
4
4
|
[c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid Split, no valid rules found'],
|
|
5
5
|
// SDK
|
|
6
6
|
[c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'],
|
|
7
|
-
[c.ERROR_CLIENT_CANNOT_GET_READY, '
|
|
7
|
+
[c.ERROR_CLIENT_CANNOT_GET_READY, 'The SDK will not get ready. Reason: %s'],
|
|
8
8
|
[c.ERROR_IMPRESSIONS_TRACKER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Could not store impressions bulk with %s impression(s). Error: %s'],
|
|
9
9
|
[c.ERROR_IMPRESSIONS_LISTENER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Impression listener logImpression method threw: %s.'],
|
|
10
10
|
[c.ERROR_EVENTS_TRACKER, c.LOG_PREFIX_EVENTS_TRACKER + 'Failed to queue %s'],
|
|
@@ -27,8 +27,9 @@ export var codesError = [
|
|
|
27
27
|
[c.ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'],
|
|
28
28
|
[c.ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'],
|
|
29
29
|
[c.ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'],
|
|
30
|
+
[c.ERROR_NOT_BOOLEAN, '%s: provided param must be a boolean value.'],
|
|
30
31
|
// initialization / settings validation
|
|
31
|
-
[c.
|
|
32
|
+
[c.ERROR_INVALID_CONFIG_PARAM, c.LOG_PREFIX_SETTINGS + ': you passed an invalid "%s" config param. It should be one of the following values: %s. Defaulting to "%s".'],
|
|
32
33
|
[c.ERROR_LOCALHOST_MODULE_REQUIRED, c.LOG_PREFIX_SETTINGS + ': an invalid value was received for "sync.localhostMode" config. A valid entity should be provided for localhost mode.'],
|
|
33
34
|
[c.ERROR_STORAGE_INVALID, c.LOG_PREFIX_SETTINGS + ': The provided storage is invalid.%s Fallbacking into default MEMORY storage'],
|
|
34
35
|
];
|
|
@@ -8,16 +8,18 @@ export var codesInfo = codesWarn.concat([
|
|
|
8
8
|
// SDK
|
|
9
9
|
[c.IMPRESSION, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Split: %s. Key: %s. Evaluation: %s. Label: %s'],
|
|
10
10
|
[c.IMPRESSION_QUEUEING, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Queueing corresponding impression.'],
|
|
11
|
-
[c.NEW_SHARED_CLIENT, '
|
|
12
|
-
[c.NEW_FACTORY, '
|
|
11
|
+
[c.NEW_SHARED_CLIENT, 'New shared client instance created.'],
|
|
12
|
+
[c.NEW_FACTORY, 'New Split SDK instance created.'],
|
|
13
13
|
[c.EVENTS_TRACKER_SUCCESS, c.LOG_PREFIX_EVENTS_TRACKER + 'Successfully queued %s'],
|
|
14
14
|
[c.IMPRESSIONS_TRACKER_SUCCESS, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Successfully stored %s impression(s).'],
|
|
15
|
+
[c.USER_CONSENT_UPDATED, 'setUserConsent: consent status changed from %s to %s.'],
|
|
16
|
+
[c.USER_CONSENT_NOT_UPDATED, 'setUserConsent: call had no effect because it was the current consent status (%s).'],
|
|
15
17
|
// synchronizer
|
|
16
18
|
[c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
|
|
17
19
|
[c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
|
|
18
20
|
[c.POLLING_STOP, c.LOG_PREFIX_SYNC_POLLING + 'Stopping polling'],
|
|
19
21
|
[c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying download of splits #%s. Reason: %s'],
|
|
20
|
-
[c.
|
|
22
|
+
[c.SUBMITTERS_PUSH_FULL_QUEUE, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing full %s queue and reseting timer.'],
|
|
21
23
|
[c.SUBMITTERS_PUSH, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Pushing %s %s.'],
|
|
22
24
|
[c.STREAMING_REFRESH_TOKEN, c.LOG_PREFIX_SYNC_STREAMING + 'Refreshing streaming token in %s seconds, and connecting streaming in %s seconds.'],
|
|
23
25
|
[c.STREAMING_RECONNECT, c.LOG_PREFIX_SYNC_STREAMING + 'Attempting to reconnect streaming in %s seconds.'],
|
package/esm/sdkClient/client.js
CHANGED
|
@@ -4,20 +4,22 @@ import { getMatching, getBucketing } from '../utils/key';
|
|
|
4
4
|
import { validateSplitExistance } from '../utils/inputValidation/splitExistance';
|
|
5
5
|
import { validateTrafficTypeExistance } from '../utils/inputValidation/trafficTypeExistance';
|
|
6
6
|
import { SDK_NOT_READY } from '../utils/labels';
|
|
7
|
-
import { CONTROL } from '../utils/constants';
|
|
7
|
+
import { CONSENT_DECLINED, CONTROL } from '../utils/constants';
|
|
8
8
|
import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants';
|
|
9
9
|
/**
|
|
10
10
|
* Creator of base client with getTreatments and track methods.
|
|
11
11
|
*/
|
|
12
12
|
// @TODO missing time tracking to collect telemetry
|
|
13
13
|
export function clientFactory(params) {
|
|
14
|
-
var readinessManager = params.sdkReadinessManager.readinessManager, storage = params.storage,
|
|
14
|
+
var readinessManager = params.sdkReadinessManager.readinessManager, storage = params.storage, settings = params.settings, impressionsTracker = params.impressionsTracker, eventTracker = params.eventTracker;
|
|
15
|
+
var log = settings.log, mode = settings.mode;
|
|
15
16
|
function getTreatment(key, splitName, attributes, withConfig) {
|
|
16
17
|
if (withConfig === void 0) { withConfig = false; }
|
|
17
18
|
var wrapUp = function (evaluationResult) {
|
|
18
19
|
var queue = [];
|
|
19
20
|
var treatment = processEvaluation(evaluationResult, splitName, key, attributes, withConfig, "getTreatment" + (withConfig ? 'withConfig' : ''), queue);
|
|
20
|
-
|
|
21
|
+
if (settings.userConsent !== CONSENT_DECLINED)
|
|
22
|
+
impressionsTracker.track(queue, attributes);
|
|
21
23
|
return treatment;
|
|
22
24
|
};
|
|
23
25
|
var evaluation = evaluateFeature(log, key, splitName, attributes, storage);
|
|
@@ -34,7 +36,8 @@ export function clientFactory(params) {
|
|
|
34
36
|
Object.keys(evaluationResults).forEach(function (splitName) {
|
|
35
37
|
treatments[splitName] = processEvaluation(evaluationResults[splitName], splitName, key, attributes, withConfig, "getTreatments" + (withConfig ? 'withConfig' : ''), queue);
|
|
36
38
|
});
|
|
37
|
-
|
|
39
|
+
if (settings.userConsent !== CONSENT_DECLINED)
|
|
40
|
+
impressionsTracker.track(queue, attributes);
|
|
38
41
|
return treatments;
|
|
39
42
|
};
|
|
40
43
|
var evaluations = evaluateFeatures(log, key, splitNames, attributes, storage);
|
|
@@ -88,7 +91,10 @@ export function clientFactory(params) {
|
|
|
88
91
|
};
|
|
89
92
|
// This may be async but we only warn, we don't actually care if it is valid or not in terms of queueing the event.
|
|
90
93
|
validateTrafficTypeExistance(log, readinessManager, storage.splits, mode, trafficTypeName, 'track');
|
|
91
|
-
|
|
94
|
+
if (settings.userConsent !== CONSENT_DECLINED)
|
|
95
|
+
return eventTracker.track(eventData, size);
|
|
96
|
+
else
|
|
97
|
+
return false;
|
|
92
98
|
}
|
|
93
99
|
return {
|
|
94
100
|
getTreatment: getTreatment,
|
package/esm/sdkFactory/index.js
CHANGED
|
@@ -8,11 +8,12 @@ import { createLoggerAPI } from '../logger/sdkLogger';
|
|
|
8
8
|
import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
9
9
|
import { metadataBuilder } from '../storages/metadataBuilder';
|
|
10
10
|
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
11
|
+
import { objectAssign } from '../utils/lang/objectAssign';
|
|
11
12
|
/**
|
|
12
13
|
* Modular SDK factory
|
|
13
14
|
*/
|
|
14
15
|
export function sdkFactory(params) {
|
|
15
|
-
var settings = params.settings, platform = params.platform, storageFactory = params.storageFactory, splitApiFactory = params.splitApiFactory, syncManagerFactory = params.syncManagerFactory, SignalListener = params.SignalListener, impressionsObserverFactory = params.impressionsObserverFactory, impressionListener = params.impressionListener, integrationsManagerFactory = params.integrationsManagerFactory, sdkManagerFactory = params.sdkManagerFactory, sdkClientMethodFactory = params.sdkClientMethodFactory;
|
|
16
|
+
var settings = params.settings, platform = params.platform, storageFactory = params.storageFactory, splitApiFactory = params.splitApiFactory, extraProps = params.extraProps, syncManagerFactory = params.syncManagerFactory, SignalListener = params.SignalListener, impressionsObserverFactory = params.impressionsObserverFactory, impressionListener = params.impressionListener, integrationsManagerFactory = params.integrationsManagerFactory, sdkManagerFactory = params.sdkManagerFactory, sdkClientMethodFactory = params.sdkClientMethodFactory;
|
|
16
17
|
var log = settings.log;
|
|
17
18
|
// @TODO handle non-recoverable errors: not start sync, mark the SDK as destroyed, etc.
|
|
18
19
|
// We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
|
|
@@ -22,6 +23,7 @@ export function sdkFactory(params) {
|
|
|
22
23
|
var readinessManager = sdkReadinessManager.readinessManager;
|
|
23
24
|
// @TODO consider passing the settings object, so that each storage access only what it needs
|
|
24
25
|
var storageFactoryParams = {
|
|
26
|
+
impressionsQueueSize: settings.scheduler.impressionsQueueSize,
|
|
25
27
|
eventsQueueSize: settings.scheduler.eventsQueueSize,
|
|
26
28
|
optimize: shouldBeOptimized(settings),
|
|
27
29
|
// ATM, only used by InLocalStorage
|
|
@@ -64,11 +66,11 @@ export function sdkFactory(params) {
|
|
|
64
66
|
syncManager && syncManager.start();
|
|
65
67
|
signalListener && signalListener.start();
|
|
66
68
|
log.info(NEW_FACTORY);
|
|
67
|
-
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
return objectAssign({
|
|
68
71
|
// Split evaluation and event tracking engine
|
|
69
72
|
client: clientMethod,
|
|
70
73
|
// Manager API to explore available information
|
|
71
|
-
// @ts-ignore
|
|
72
74
|
manager: function () {
|
|
73
75
|
log.debug(RETRIEVE_MANAGER);
|
|
74
76
|
return managerInstance;
|
|
@@ -76,5 +78,5 @@ export function sdkFactory(params) {
|
|
|
76
78
|
// Logger wrapper API
|
|
77
79
|
Logger: createLoggerAPI(settings.log),
|
|
78
80
|
settings: settings,
|
|
79
|
-
};
|
|
81
|
+
}, extraProps && extraProps(settings, syncManager));
|
|
80
82
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ERROR_NOT_BOOLEAN, USER_CONSENT_UPDATED, USER_CONSENT_NOT_UPDATED } from '../logger/constants';
|
|
2
|
+
import { CONSENT_GRANTED, CONSENT_DECLINED } from '../utils/constants';
|
|
3
|
+
import { isBoolean } from '../utils/lang';
|
|
4
|
+
// Extend client-side factory instances with user consent getter/setter
|
|
5
|
+
export function userConsentProps(settings, syncManager) {
|
|
6
|
+
var log = settings.log;
|
|
7
|
+
return {
|
|
8
|
+
setUserConsent: function (consent) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
// validate input param
|
|
11
|
+
if (!isBoolean(consent)) {
|
|
12
|
+
log.warn(ERROR_NOT_BOOLEAN, ['setUserConsent']);
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
var newConsentStatus = consent ? CONSENT_GRANTED : CONSENT_DECLINED;
|
|
16
|
+
if (settings.userConsent !== newConsentStatus) { // @ts-ignore, modify readonly prop
|
|
17
|
+
settings.userConsent = newConsentStatus;
|
|
18
|
+
if (consent)
|
|
19
|
+
(_a = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _a === void 0 ? void 0 : _a.start(); // resumes submitters if transitioning to GRANTED
|
|
20
|
+
else
|
|
21
|
+
(_b = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _b === void 0 ? void 0 : _b.stop(); // pauses submitters if transitioning to DECLINED
|
|
22
|
+
log.info(USER_CONSENT_UPDATED, [settings.userConsent, newConsentStatus]);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
log.info(USER_CONSENT_NOT_UPDATED, [newConsentStatus]);
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
},
|
|
29
|
+
getUserConsent: function () {
|
|
30
|
+
return settings.userConsent;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { startsWith } from '../utils/lang';
|
|
2
2
|
var everythingAtTheEnd = /[^.]+$/;
|
|
3
3
|
var DEFAULT_PREFIX = 'SPLITIO';
|
|
4
4
|
export function validatePrefix(prefix) {
|
|
5
|
-
return prefix
|
|
6
|
-
endsWith(prefix, '.' + DEFAULT_PREFIX) ?
|
|
7
|
-
prefix : // suffix already appended
|
|
8
|
-
prefix + '.' + DEFAULT_PREFIX : // append suffix
|
|
9
|
-
DEFAULT_PREFIX; // use default prefix if none is provided
|
|
5
|
+
return prefix ? prefix + '.SPLITIO' : 'SPLITIO';
|
|
10
6
|
}
|
|
11
7
|
var KeyBuilder = /** @class */ (function () {
|
|
12
8
|
function KeyBuilder(prefix) {
|
|
@@ -13,9 +13,19 @@ var KeyBuilderCS = /** @class */ (function (_super) {
|
|
|
13
13
|
* @override
|
|
14
14
|
*/
|
|
15
15
|
KeyBuilderCS.prototype.buildSegmentNameKey = function (segmentName) {
|
|
16
|
-
return this.
|
|
16
|
+
return this.prefix + "." + this.matchingKey + ".segment." + segmentName;
|
|
17
17
|
};
|
|
18
18
|
KeyBuilderCS.prototype.extractSegmentName = function (builtSegmentKeyName) {
|
|
19
|
+
var prefix = this.prefix + "." + this.matchingKey + ".segment.";
|
|
20
|
+
if (startsWith(builtSegmentKeyName, prefix))
|
|
21
|
+
return builtSegmentKeyName.substr(prefix.length);
|
|
22
|
+
};
|
|
23
|
+
// @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
|
|
24
|
+
KeyBuilderCS.prototype.buildOldSegmentNameKey = function (segmentName) {
|
|
25
|
+
return this.matchingKey + "." + this.prefix + ".segment." + segmentName;
|
|
26
|
+
};
|
|
27
|
+
// @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
|
|
28
|
+
KeyBuilderCS.prototype.extractOldSegmentKey = function (builtSegmentKeyName) {
|
|
19
29
|
var prefix = this.matchingKey + "." + this.prefix + ".segment.";
|
|
20
30
|
if (startsWith(builtSegmentKeyName, prefix))
|
|
21
31
|
return builtSegmentKeyName.substr(prefix.length);
|
|
@@ -57,9 +57,29 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
|
57
57
|
var index;
|
|
58
58
|
// Scan current values from localStorage
|
|
59
59
|
var storedSegmentNames = Object.keys(localStorage).reduce(function (accum, key) {
|
|
60
|
-
var
|
|
61
|
-
if (
|
|
62
|
-
accum.push(
|
|
60
|
+
var segmentName = _this.keys.extractSegmentName(key);
|
|
61
|
+
if (segmentName) {
|
|
62
|
+
accum.push(segmentName);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// @BREAKING: This is only to clean up "old" keys. Remove this whole else code block.
|
|
66
|
+
segmentName = _this.keys.extractOldSegmentKey(key);
|
|
67
|
+
if (segmentName) { // this was an old segment key, let's clean up.
|
|
68
|
+
var newSegmentKey = _this.keys.buildSegmentNameKey(segmentName);
|
|
69
|
+
try {
|
|
70
|
+
// If the new format key is not there, create it.
|
|
71
|
+
if (!localStorage.getItem(newSegmentKey) && names.indexOf(segmentName) > -1) {
|
|
72
|
+
localStorage.setItem(newSegmentKey, DEFINED);
|
|
73
|
+
// we are migrating a segment, let's track it.
|
|
74
|
+
accum.push(segmentName);
|
|
75
|
+
}
|
|
76
|
+
localStorage.removeItem(key); // we migrated the current key, let's delete it.
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
_this.log.error(e);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
63
83
|
return accum;
|
|
64
84
|
}, []);
|
|
65
85
|
// Extreme fast => everything is empty
|
|
@@ -30,7 +30,7 @@ export function InLocalStorage(options) {
|
|
|
30
30
|
return {
|
|
31
31
|
splits: new SplitsCacheInLocal(log, keys, expirationTimestamp, params.splitFiltersValidation),
|
|
32
32
|
segments: new MySegmentsCacheInLocal(log, keys),
|
|
33
|
-
impressions: new ImpressionsCacheInMemory(),
|
|
33
|
+
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
34
34
|
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
35
35
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
36
36
|
destroy: function () {
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
var ImpressionsCacheInMemory = /** @class */ (function () {
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param impressionsQueueSize number of queued impressions to call onFullQueueCb.
|
|
5
|
+
* Default value is 0, that means no maximum value, in case we want to avoid this being triggered.
|
|
6
|
+
*/
|
|
7
|
+
function ImpressionsCacheInMemory(impressionsQueueSize) {
|
|
8
|
+
if (impressionsQueueSize === void 0) { impressionsQueueSize = 0; }
|
|
9
|
+
this.maxQueue = impressionsQueueSize;
|
|
3
10
|
this.queue = [];
|
|
4
11
|
}
|
|
12
|
+
ImpressionsCacheInMemory.prototype.setOnFullQueueCb = function (cb) {
|
|
13
|
+
this.onFullQueue = cb;
|
|
14
|
+
};
|
|
5
15
|
/**
|
|
6
16
|
* Store impressions in sequential order
|
|
7
17
|
*/
|
|
8
18
|
ImpressionsCacheInMemory.prototype.track = function (data) {
|
|
9
19
|
var _a;
|
|
10
20
|
(_a = this.queue).push.apply(_a, data);
|
|
21
|
+
// Check if the cache queue is full and we need to flush it.
|
|
22
|
+
if (this.maxQueue > 0 && this.queue.length >= this.maxQueue && this.onFullQueue) {
|
|
23
|
+
this.onFullQueue();
|
|
24
|
+
}
|
|
11
25
|
};
|
|
12
26
|
/**
|
|
13
27
|
* Clear the data stored on the cache.
|
|
@@ -13,7 +13,7 @@ export function InMemoryStorageFactory(params) {
|
|
|
13
13
|
return {
|
|
14
14
|
splits: new SplitsCacheInMemory(),
|
|
15
15
|
segments: new SegmentsCacheInMemory(),
|
|
16
|
-
impressions: new ImpressionsCacheInMemory(),
|
|
16
|
+
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
17
17
|
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
18
18
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
19
19
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
@@ -13,7 +13,7 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
13
13
|
return {
|
|
14
14
|
splits: new SplitsCacheInMemory(),
|
|
15
15
|
segments: new MySegmentsCacheInMemory(),
|
|
16
|
-
impressions: new ImpressionsCacheInMemory(),
|
|
16
|
+
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
17
17
|
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
18
18
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
19
19
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
@@ -51,7 +51,7 @@ export function PluggableStorage(options) {
|
|
|
51
51
|
validatePluggableStorageOptions(options);
|
|
52
52
|
var prefix = validatePrefix(options.prefix);
|
|
53
53
|
function PluggableStorageFactory(_a) {
|
|
54
|
-
var log = _a.log, metadata = _a.metadata, onReadyCb = _a.onReadyCb, mode = _a.mode, eventsQueueSize = _a.eventsQueueSize, optimize = _a.optimize;
|
|
54
|
+
var log = _a.log, metadata = _a.metadata, onReadyCb = _a.onReadyCb, mode = _a.mode, eventsQueueSize = _a.eventsQueueSize, impressionsQueueSize = _a.impressionsQueueSize, optimize = _a.optimize;
|
|
55
55
|
var keys = new KeyBuilderSS(prefix, metadata);
|
|
56
56
|
var wrapper = wrapperAdapter(log, options.wrapper);
|
|
57
57
|
var isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
|
|
@@ -60,7 +60,7 @@ export function PluggableStorage(options) {
|
|
|
60
60
|
return {
|
|
61
61
|
splits: new SplitsCachePluggable(log, keys, wrapper),
|
|
62
62
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
63
|
-
impressions: isPartialConsumer ? new ImpressionsCacheInMemory() : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
63
|
+
impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
64
64
|
impressionCounts: optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
65
65
|
events: isPartialConsumer ? promisifyEventsTrack(new EventsCacheInMemory(eventsQueueSize)) : new EventsCachePluggable(log, keys.buildEventsKey(), wrapper, metadata),
|
|
66
66
|
// @TODO add telemetry cache when required
|
|
@@ -1,28 +1,40 @@
|
|
|
1
1
|
import { submitterSyncTaskFactory } from './submitterSyncTask';
|
|
2
|
-
import {
|
|
2
|
+
import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
3
|
+
var DATA_NAME = 'events';
|
|
3
4
|
/**
|
|
4
5
|
* Sync task that periodically posts tracked events
|
|
5
6
|
*/
|
|
6
7
|
export function eventsSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, eventsFirstPushWindow, latencyTracker) {
|
|
7
8
|
// don't retry events.
|
|
8
|
-
var syncTask = submitterSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate,
|
|
9
|
-
// Set a timer for the first push of events
|
|
9
|
+
var syncTask = submitterSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, DATA_NAME, latencyTracker);
|
|
10
|
+
// Set a timer for the first push window of events.
|
|
11
|
+
// Not implemented in the base submitter or sync task, since this feature is only used by the events submitter.
|
|
10
12
|
if (eventsFirstPushWindow > 0) {
|
|
13
|
+
var running_1 = false;
|
|
11
14
|
var stopEventPublisherTimeout_1;
|
|
12
15
|
var originalStart_1 = syncTask.start;
|
|
13
16
|
syncTask.start = function () {
|
|
17
|
+
running_1 = true;
|
|
14
18
|
stopEventPublisherTimeout_1 = setTimeout(originalStart_1, eventsFirstPushWindow);
|
|
15
19
|
};
|
|
16
20
|
var originalStop_1 = syncTask.stop;
|
|
17
21
|
syncTask.stop = function () {
|
|
22
|
+
running_1 = false;
|
|
18
23
|
clearTimeout(stopEventPublisherTimeout_1);
|
|
19
24
|
originalStop_1();
|
|
20
25
|
};
|
|
26
|
+
syncTask.isRunning = function () {
|
|
27
|
+
return running_1;
|
|
28
|
+
};
|
|
21
29
|
}
|
|
22
|
-
// register
|
|
30
|
+
// register events submitter to be executed when events cache is full
|
|
23
31
|
eventsCache.setOnFullQueueCb(function () {
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
if (syncTask.isRunning()) {
|
|
33
|
+
log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
|
|
34
|
+
syncTask.execute();
|
|
35
|
+
}
|
|
36
|
+
// If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
|
|
37
|
+
// Data will be sent when submitter is resumed.
|
|
26
38
|
});
|
|
27
39
|
return syncTask;
|
|
28
40
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { groupBy, forOwn } from '../../utils/lang';
|
|
2
2
|
import { submitterSyncTaskFactory } from './submitterSyncTask';
|
|
3
|
+
import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
4
|
+
var DATA_NAME = 'impressions';
|
|
3
5
|
/**
|
|
4
6
|
* Converts `impressions` data from cache into request payload.
|
|
5
7
|
*/
|
|
@@ -32,5 +34,15 @@ export function fromImpressionsCollector(sendLabels, data) {
|
|
|
32
34
|
export function impressionsSyncTaskFactory(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, sendLabels, latencyTracker) {
|
|
33
35
|
if (sendLabels === void 0) { sendLabels = false; }
|
|
34
36
|
// retry impressions only once.
|
|
35
|
-
|
|
37
|
+
var syncTask = submitterSyncTaskFactory(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, DATA_NAME, latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1);
|
|
38
|
+
// register impressions submitter to be executed when impressions cache is full
|
|
39
|
+
impressionsCache.setOnFullQueueCb(function () {
|
|
40
|
+
if (syncTask.isRunning()) {
|
|
41
|
+
log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
|
|
42
|
+
syncTask.execute();
|
|
43
|
+
}
|
|
44
|
+
// If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
|
|
45
|
+
// Data will be sent when submitter is resumed.
|
|
46
|
+
});
|
|
47
|
+
return syncTask;
|
|
36
48
|
}
|