@splitsoftware/splitio-commons 1.4.2-rc.0 → 1.4.2-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +4 -3
- package/cjs/integrations/ga/GaToSplit.js +11 -12
- package/cjs/sync/syncManagerOnline.js +34 -19
- package/cjs/sync/syncTask.js +15 -10
- package/cjs/utils/settingsValidation/index.js +6 -1
- package/esm/integrations/ga/GaToSplit.js +11 -12
- package/esm/sync/syncManagerOnline.js +34 -19
- package/esm/sync/syncTask.js +15 -10
- package/esm/utils/settingsValidation/index.js +6 -1
- package/package.json +1 -1
- package/src/integrations/ga/GaToSplit.ts +8 -14
- package/src/integrations/ga/types.ts +2 -13
- package/src/sdkClient/clientAttributesDecoration.ts +9 -9
- package/src/sync/syncManagerOnline.ts +29 -16
- package/src/sync/syncTask.ts +17 -11
- package/src/types.ts +7 -1
- package/src/utils/settingsValidation/index.ts +7 -1
- package/types/integrations/ga/types.d.ts +2 -13
- 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/sync/syncTask.d.ts +2 -2
- package/types/types.d.ts +6 -0
- package/types/utils/settingsValidation/index.d.ts +1 -0
- package/types/utils/timeTracker/index.d.ts +70 -1
- package/cjs/integrations/ga/autoRequire.js +0 -34
- package/esm/integrations/ga/autoRequire.js +0 -30
- package/src/integrations/ga/autoRequire.ts +0 -35
- package/src/logger/.DS_Store +0 -0
- 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
package/CHANGES.txt
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
1.
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
1.5.0 (June 24, 2022)
|
|
2
|
+
- Added a new config option to control the tasks that listen or poll for updates on feature flags and segments, via the new config sync.enabled . Running online Split will always pull the most recent updates upon initialization, this only affects updates fetching on a running instance. Useful when a consistent session experience is a must or to save resources when updates are not being used.
|
|
3
|
+
- Updated telemetry logic to track the anonymous config for user consent flag set to declined or unknown.
|
|
4
|
+
- Updated submitters logic, to avoid duplicating the post of impressions to Split cloud when the SDK is destroyed while its periodic post of impressions is running.
|
|
4
5
|
|
|
5
6
|
1.4.1 (June 13, 2022)
|
|
6
7
|
- Bugfixing - Updated submitters logic, to avoid dropping impressions and events that are being tracked while POST request is pending.
|
|
@@ -10,24 +10,23 @@ var logNameMapper = 'ga-to-split:mapper';
|
|
|
10
10
|
/**
|
|
11
11
|
* Provides a plugin to use with analytics.js, accounting for the possibility
|
|
12
12
|
* that the global command queue has been renamed or not yet defined.
|
|
13
|
-
* @param
|
|
14
|
-
* @param
|
|
15
|
-
* @param pluginConstructor The plugin constructor function.
|
|
16
|
-
* @param log Logger instance.
|
|
17
|
-
* @param autoRequire If true, log error when auto-require script is not detected
|
|
13
|
+
* @param {string} pluginName The plugin name identifier.
|
|
14
|
+
* @param {Function} pluginConstructor The plugin constructor function.
|
|
18
15
|
*/
|
|
19
|
-
function providePlugin(
|
|
16
|
+
function providePlugin(pluginName, pluginConstructor) {
|
|
20
17
|
// get reference to global command queue. Init it if not defined yet.
|
|
18
|
+
// @ts-expect-error
|
|
21
19
|
var gaAlias = window.GoogleAnalyticsObject || 'ga';
|
|
22
20
|
window[gaAlias] = window[gaAlias] || function () {
|
|
23
|
-
|
|
21
|
+
var args = [];
|
|
22
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
23
|
+
args[_i] = arguments[_i];
|
|
24
|
+
}
|
|
25
|
+
(window[gaAlias].q = window[gaAlias].q || []).push(args);
|
|
24
26
|
};
|
|
25
27
|
// provides the plugin for use with analytics.js.
|
|
28
|
+
// @ts-expect-error
|
|
26
29
|
window[gaAlias]('provide', pluginName, pluginConstructor);
|
|
27
|
-
if (autoRequire && (!window[gaAlias].q || window[gaAlias].q.push === [].push)) {
|
|
28
|
-
// Expecting spy on ga.q push method but not found
|
|
29
|
-
log.error('Auto-require script was expected but not provided.');
|
|
30
|
-
}
|
|
31
30
|
}
|
|
32
31
|
// Default mapping: object used for building the default mapper from hits to Split events
|
|
33
32
|
var defaultMapping = {
|
|
@@ -247,6 +246,6 @@ function GaToSplit(sdkOptions, params) {
|
|
|
247
246
|
return SplitTracker;
|
|
248
247
|
}());
|
|
249
248
|
// Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
|
|
250
|
-
providePlugin(
|
|
249
|
+
providePlugin('splitTracker', SplitTracker);
|
|
251
250
|
}
|
|
252
251
|
exports.GaToSplit = GaToSplit;
|
|
@@ -19,11 +19,11 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
19
19
|
* SyncManager factory for modular SDK
|
|
20
20
|
*/
|
|
21
21
|
return function (params) {
|
|
22
|
-
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, telemetryTracker = params.telemetryTracker;
|
|
22
|
+
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker;
|
|
23
23
|
/** Polling Manager */
|
|
24
24
|
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
25
25
|
/** Push Manager */
|
|
26
|
-
var pushManager = streamingEnabled && pollingManager && pushManagerFactory ?
|
|
26
|
+
var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
27
27
|
pushManagerFactory(params, pollingManager) :
|
|
28
28
|
undefined;
|
|
29
29
|
/** Submitter Manager */
|
|
@@ -69,16 +69,25 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
69
69
|
running = true;
|
|
70
70
|
// start syncing splits and segments
|
|
71
71
|
if (pollingManager) {
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
// If synchronization is disabled pushManager and pollingManager should not start
|
|
73
|
+
if (syncEnabled) {
|
|
74
|
+
if (pushManager) {
|
|
75
|
+
// Doesn't call `syncAll` when the syncManager is resuming
|
|
76
|
+
if (startFirstTime) {
|
|
77
|
+
pollingManager.syncAll();
|
|
78
|
+
startFirstTime = false;
|
|
79
|
+
}
|
|
80
|
+
pushManager.start();
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
pollingManager.start();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
74
87
|
if (startFirstTime) {
|
|
75
88
|
pollingManager.syncAll();
|
|
76
89
|
startFirstTime = false;
|
|
77
90
|
}
|
|
78
|
-
pushManager.start();
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
pollingManager.start();
|
|
82
91
|
}
|
|
83
92
|
}
|
|
84
93
|
// start periodic data recording (events, impressions, telemetry).
|
|
@@ -112,22 +121,28 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
112
121
|
return {
|
|
113
122
|
isRunning: mySegmentsSyncTask.isRunning,
|
|
114
123
|
start: function () {
|
|
115
|
-
if (
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
if (syncEnabled) {
|
|
125
|
+
if (pushManager) {
|
|
126
|
+
if (pollingManager.isRunning()) {
|
|
127
|
+
// if doing polling, we must start the periodic fetch of data
|
|
128
|
+
if (storage.splits.usesSegments())
|
|
129
|
+
mySegmentsSyncTask.start();
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// if not polling, we must execute the sync task for the initial fetch
|
|
133
|
+
// of segments since `syncAll` was already executed when starting the main client
|
|
134
|
+
mySegmentsSyncTask.execute();
|
|
135
|
+
}
|
|
136
|
+
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
120
137
|
}
|
|
121
138
|
else {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
mySegmentsSyncTask.execute();
|
|
139
|
+
if (storage.splits.usesSegments())
|
|
140
|
+
mySegmentsSyncTask.start();
|
|
125
141
|
}
|
|
126
|
-
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
127
142
|
}
|
|
128
143
|
else {
|
|
129
|
-
if (
|
|
130
|
-
mySegmentsSyncTask.
|
|
144
|
+
if (!readinessManager.isReady())
|
|
145
|
+
mySegmentsSyncTask.execute();
|
|
131
146
|
}
|
|
132
147
|
},
|
|
133
148
|
stop: function () {
|
package/cjs/sync/syncTask.js
CHANGED
|
@@ -4,8 +4,8 @@ exports.syncTaskFactory = void 0;
|
|
|
4
4
|
var constants_1 = require("../logger/constants");
|
|
5
5
|
/**
|
|
6
6
|
* Creates a syncTask that handles the periodic execution of a given task ("start" and "stop" methods).
|
|
7
|
-
* The task can be executed
|
|
8
|
-
*
|
|
7
|
+
* The task can be also executed by calling the "execute" method. Multiple execute calls are chained to run secuentially and avoid race conditions.
|
|
8
|
+
* For example, submitters executed on SDK destroy or full queue, while periodic execution is pending.
|
|
9
9
|
*
|
|
10
10
|
* @param log Logger instance.
|
|
11
11
|
* @param task Task to execute that returns a promise that NEVER REJECTS. Otherwise, periodic execution can result in Unhandled Promise Rejections.
|
|
@@ -15,8 +15,8 @@ var constants_1 = require("../logger/constants");
|
|
|
15
15
|
*/
|
|
16
16
|
function syncTaskFactory(log, task, period, taskName) {
|
|
17
17
|
if (taskName === void 0) { taskName = 'task'; }
|
|
18
|
-
//
|
|
19
|
-
var
|
|
18
|
+
// Task promise while it is pending. Undefined once the promise is resolved
|
|
19
|
+
var pendingTask;
|
|
20
20
|
// flag that indicates if the task periodic execution has been started/stopped.
|
|
21
21
|
var running = false;
|
|
22
22
|
// Auxiliar counter used to avoid race condition when calling `start` & `stop` intermittently
|
|
@@ -30,13 +30,19 @@ function syncTaskFactory(log, task, period, taskName) {
|
|
|
30
30
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
31
31
|
args[_i] = arguments[_i];
|
|
32
32
|
}
|
|
33
|
-
executing
|
|
33
|
+
// If task is executing, chain the new execution
|
|
34
|
+
if (pendingTask) {
|
|
35
|
+
return pendingTask.then(function () {
|
|
36
|
+
return execute.apply(void 0, args);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// Execute task
|
|
34
40
|
log.debug(constants_1.SYNC_TASK_EXECUTE, [taskName]);
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
pendingTask = task.apply(void 0, args).then(function (result) {
|
|
42
|
+
pendingTask = undefined;
|
|
37
43
|
return result;
|
|
38
44
|
});
|
|
39
|
-
|
|
45
|
+
return pendingTask;
|
|
40
46
|
}
|
|
41
47
|
function periodicExecute(currentRunningId) {
|
|
42
48
|
return execute.apply(void 0, runningArgs).then(function (result) {
|
|
@@ -48,10 +54,9 @@ function syncTaskFactory(log, task, period, taskName) {
|
|
|
48
54
|
});
|
|
49
55
|
}
|
|
50
56
|
return {
|
|
51
|
-
// @TODO check if we need to queued `execute` calls, to avoid possible race conditions on submitters and updaters with streaming.
|
|
52
57
|
execute: execute,
|
|
53
58
|
isExecuting: function () {
|
|
54
|
-
return
|
|
59
|
+
return pendingTask !== undefined;
|
|
55
60
|
},
|
|
56
61
|
start: function () {
|
|
57
62
|
var args = [];
|
|
@@ -73,7 +73,8 @@ exports.base = {
|
|
|
73
73
|
splitFilters: undefined,
|
|
74
74
|
// impressions collection mode
|
|
75
75
|
impressionsMode: constants_1.OPTIMIZED,
|
|
76
|
-
localhostMode: undefined
|
|
76
|
+
localhostMode: undefined,
|
|
77
|
+
enabled: true
|
|
77
78
|
},
|
|
78
79
|
// Logger
|
|
79
80
|
log: undefined
|
|
@@ -167,6 +168,10 @@ function settingsValidation(config, validationParams) {
|
|
|
167
168
|
// We are not checking if bases are positive numbers. Thus, we might be reauthenticating immediately (`setTimeout` with NaN or negative number)
|
|
168
169
|
scheduler.pushRetryBackoffBase = fromSecondsToMillis(scheduler.pushRetryBackoffBase);
|
|
169
170
|
}
|
|
171
|
+
// validate sync enabled
|
|
172
|
+
if (withDefaults.sync.enabled !== false) { // @ts-ignore, modify readonly prop
|
|
173
|
+
withDefaults.sync.enabled = true;
|
|
174
|
+
}
|
|
170
175
|
// validate the `splitFilters` settings and parse splits query
|
|
171
176
|
var splitFiltersValidation = (0, splitFilters_1.validateSplitFilters)(log, withDefaults.sync.splitFilters, withDefaults.mode);
|
|
172
177
|
withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
|
|
@@ -7,24 +7,23 @@ var logNameMapper = 'ga-to-split:mapper';
|
|
|
7
7
|
/**
|
|
8
8
|
* Provides a plugin to use with analytics.js, accounting for the possibility
|
|
9
9
|
* that the global command queue has been renamed or not yet defined.
|
|
10
|
-
* @param
|
|
11
|
-
* @param
|
|
12
|
-
* @param pluginConstructor The plugin constructor function.
|
|
13
|
-
* @param log Logger instance.
|
|
14
|
-
* @param autoRequire If true, log error when auto-require script is not detected
|
|
10
|
+
* @param {string} pluginName The plugin name identifier.
|
|
11
|
+
* @param {Function} pluginConstructor The plugin constructor function.
|
|
15
12
|
*/
|
|
16
|
-
function providePlugin(
|
|
13
|
+
function providePlugin(pluginName, pluginConstructor) {
|
|
17
14
|
// get reference to global command queue. Init it if not defined yet.
|
|
15
|
+
// @ts-expect-error
|
|
18
16
|
var gaAlias = window.GoogleAnalyticsObject || 'ga';
|
|
19
17
|
window[gaAlias] = window[gaAlias] || function () {
|
|
20
|
-
|
|
18
|
+
var args = [];
|
|
19
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
20
|
+
args[_i] = arguments[_i];
|
|
21
|
+
}
|
|
22
|
+
(window[gaAlias].q = window[gaAlias].q || []).push(args);
|
|
21
23
|
};
|
|
22
24
|
// provides the plugin for use with analytics.js.
|
|
25
|
+
// @ts-expect-error
|
|
23
26
|
window[gaAlias]('provide', pluginName, pluginConstructor);
|
|
24
|
-
if (autoRequire && (!window[gaAlias].q || window[gaAlias].q.push === [].push)) {
|
|
25
|
-
// Expecting spy on ga.q push method but not found
|
|
26
|
-
log.error('Auto-require script was expected but not provided.');
|
|
27
|
-
}
|
|
28
27
|
}
|
|
29
28
|
// Default mapping: object used for building the default mapper from hits to Split events
|
|
30
29
|
var defaultMapping = {
|
|
@@ -241,5 +240,5 @@ export function GaToSplit(sdkOptions, params) {
|
|
|
241
240
|
return SplitTracker;
|
|
242
241
|
}());
|
|
243
242
|
// Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
|
|
244
|
-
providePlugin(
|
|
243
|
+
providePlugin('splitTracker', SplitTracker);
|
|
245
244
|
}
|
|
@@ -16,11 +16,11 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
|
|
|
16
16
|
* SyncManager factory for modular SDK
|
|
17
17
|
*/
|
|
18
18
|
return function (params) {
|
|
19
|
-
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, telemetryTracker = params.telemetryTracker;
|
|
19
|
+
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker;
|
|
20
20
|
/** Polling Manager */
|
|
21
21
|
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
22
22
|
/** Push Manager */
|
|
23
|
-
var pushManager = streamingEnabled && pollingManager && pushManagerFactory ?
|
|
23
|
+
var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
24
24
|
pushManagerFactory(params, pollingManager) :
|
|
25
25
|
undefined;
|
|
26
26
|
/** Submitter Manager */
|
|
@@ -66,16 +66,25 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
|
|
|
66
66
|
running = true;
|
|
67
67
|
// start syncing splits and segments
|
|
68
68
|
if (pollingManager) {
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
// If synchronization is disabled pushManager and pollingManager should not start
|
|
70
|
+
if (syncEnabled) {
|
|
71
|
+
if (pushManager) {
|
|
72
|
+
// Doesn't call `syncAll` when the syncManager is resuming
|
|
73
|
+
if (startFirstTime) {
|
|
74
|
+
pollingManager.syncAll();
|
|
75
|
+
startFirstTime = false;
|
|
76
|
+
}
|
|
77
|
+
pushManager.start();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
pollingManager.start();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
71
84
|
if (startFirstTime) {
|
|
72
85
|
pollingManager.syncAll();
|
|
73
86
|
startFirstTime = false;
|
|
74
87
|
}
|
|
75
|
-
pushManager.start();
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
pollingManager.start();
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
// start periodic data recording (events, impressions, telemetry).
|
|
@@ -109,22 +118,28 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
|
|
|
109
118
|
return {
|
|
110
119
|
isRunning: mySegmentsSyncTask.isRunning,
|
|
111
120
|
start: function () {
|
|
112
|
-
if (
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
121
|
+
if (syncEnabled) {
|
|
122
|
+
if (pushManager) {
|
|
123
|
+
if (pollingManager.isRunning()) {
|
|
124
|
+
// if doing polling, we must start the periodic fetch of data
|
|
125
|
+
if (storage.splits.usesSegments())
|
|
126
|
+
mySegmentsSyncTask.start();
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// if not polling, we must execute the sync task for the initial fetch
|
|
130
|
+
// of segments since `syncAll` was already executed when starting the main client
|
|
131
|
+
mySegmentsSyncTask.execute();
|
|
132
|
+
}
|
|
133
|
+
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
117
134
|
}
|
|
118
135
|
else {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
mySegmentsSyncTask.execute();
|
|
136
|
+
if (storage.splits.usesSegments())
|
|
137
|
+
mySegmentsSyncTask.start();
|
|
122
138
|
}
|
|
123
|
-
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
124
139
|
}
|
|
125
140
|
else {
|
|
126
|
-
if (
|
|
127
|
-
mySegmentsSyncTask.
|
|
141
|
+
if (!readinessManager.isReady())
|
|
142
|
+
mySegmentsSyncTask.execute();
|
|
128
143
|
}
|
|
129
144
|
},
|
|
130
145
|
stop: function () {
|
package/esm/sync/syncTask.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SYNC_TASK_EXECUTE, SYNC_TASK_START, SYNC_TASK_STOP } from '../logger/constants';
|
|
2
2
|
/**
|
|
3
3
|
* Creates a syncTask that handles the periodic execution of a given task ("start" and "stop" methods).
|
|
4
|
-
* The task can be executed
|
|
5
|
-
*
|
|
4
|
+
* The task can be also executed by calling the "execute" method. Multiple execute calls are chained to run secuentially and avoid race conditions.
|
|
5
|
+
* For example, submitters executed on SDK destroy or full queue, while periodic execution is pending.
|
|
6
6
|
*
|
|
7
7
|
* @param log Logger instance.
|
|
8
8
|
* @param task Task to execute that returns a promise that NEVER REJECTS. Otherwise, periodic execution can result in Unhandled Promise Rejections.
|
|
@@ -12,8 +12,8 @@ import { SYNC_TASK_EXECUTE, SYNC_TASK_START, SYNC_TASK_STOP } from '../logger/co
|
|
|
12
12
|
*/
|
|
13
13
|
export function syncTaskFactory(log, task, period, taskName) {
|
|
14
14
|
if (taskName === void 0) { taskName = 'task'; }
|
|
15
|
-
//
|
|
16
|
-
var
|
|
15
|
+
// Task promise while it is pending. Undefined once the promise is resolved
|
|
16
|
+
var pendingTask;
|
|
17
17
|
// flag that indicates if the task periodic execution has been started/stopped.
|
|
18
18
|
var running = false;
|
|
19
19
|
// Auxiliar counter used to avoid race condition when calling `start` & `stop` intermittently
|
|
@@ -27,13 +27,19 @@ export function syncTaskFactory(log, task, period, taskName) {
|
|
|
27
27
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
28
28
|
args[_i] = arguments[_i];
|
|
29
29
|
}
|
|
30
|
-
executing
|
|
30
|
+
// If task is executing, chain the new execution
|
|
31
|
+
if (pendingTask) {
|
|
32
|
+
return pendingTask.then(function () {
|
|
33
|
+
return execute.apply(void 0, args);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// Execute task
|
|
31
37
|
log.debug(SYNC_TASK_EXECUTE, [taskName]);
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
pendingTask = task.apply(void 0, args).then(function (result) {
|
|
39
|
+
pendingTask = undefined;
|
|
34
40
|
return result;
|
|
35
41
|
});
|
|
36
|
-
|
|
42
|
+
return pendingTask;
|
|
37
43
|
}
|
|
38
44
|
function periodicExecute(currentRunningId) {
|
|
39
45
|
return execute.apply(void 0, runningArgs).then(function (result) {
|
|
@@ -45,10 +51,9 @@ export function syncTaskFactory(log, task, period, taskName) {
|
|
|
45
51
|
});
|
|
46
52
|
}
|
|
47
53
|
return {
|
|
48
|
-
// @TODO check if we need to queued `execute` calls, to avoid possible race conditions on submitters and updaters with streaming.
|
|
49
54
|
execute: execute,
|
|
50
55
|
isExecuting: function () {
|
|
51
|
-
return
|
|
56
|
+
return pendingTask !== undefined;
|
|
52
57
|
},
|
|
53
58
|
start: function () {
|
|
54
59
|
var args = [];
|
|
@@ -70,7 +70,8 @@ export var base = {
|
|
|
70
70
|
splitFilters: undefined,
|
|
71
71
|
// impressions collection mode
|
|
72
72
|
impressionsMode: OPTIMIZED,
|
|
73
|
-
localhostMode: undefined
|
|
73
|
+
localhostMode: undefined,
|
|
74
|
+
enabled: true
|
|
74
75
|
},
|
|
75
76
|
// Logger
|
|
76
77
|
log: undefined
|
|
@@ -164,6 +165,10 @@ export function settingsValidation(config, validationParams) {
|
|
|
164
165
|
// We are not checking if bases are positive numbers. Thus, we might be reauthenticating immediately (`setTimeout` with NaN or negative number)
|
|
165
166
|
scheduler.pushRetryBackoffBase = fromSecondsToMillis(scheduler.pushRetryBackoffBase);
|
|
166
167
|
}
|
|
168
|
+
// validate sync enabled
|
|
169
|
+
if (withDefaults.sync.enabled !== false) { // @ts-ignore, modify readonly prop
|
|
170
|
+
withDefaults.sync.enabled = true;
|
|
171
|
+
}
|
|
167
172
|
// validate the `splitFilters` settings and parse splits query
|
|
168
173
|
var splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode);
|
|
169
174
|
withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
|
package/package.json
CHANGED
|
@@ -19,26 +19,20 @@ const logNameMapper = 'ga-to-split:mapper';
|
|
|
19
19
|
/**
|
|
20
20
|
* Provides a plugin to use with analytics.js, accounting for the possibility
|
|
21
21
|
* that the global command queue has been renamed or not yet defined.
|
|
22
|
-
* @param
|
|
23
|
-
* @param
|
|
24
|
-
* @param pluginConstructor The plugin constructor function.
|
|
25
|
-
* @param log Logger instance.
|
|
26
|
-
* @param autoRequire If true, log error when auto-require script is not detected
|
|
22
|
+
* @param {string} pluginName The plugin name identifier.
|
|
23
|
+
* @param {Function} pluginConstructor The plugin constructor function.
|
|
27
24
|
*/
|
|
28
|
-
function providePlugin(
|
|
25
|
+
function providePlugin(pluginName: string, pluginConstructor: Function) {
|
|
29
26
|
// get reference to global command queue. Init it if not defined yet.
|
|
27
|
+
// @ts-expect-error
|
|
30
28
|
const gaAlias = window.GoogleAnalyticsObject || 'ga';
|
|
31
|
-
window[gaAlias] = window[gaAlias] || function () {
|
|
32
|
-
(window[gaAlias].q = window[gaAlias].q || []).push(
|
|
29
|
+
window[gaAlias] = window[gaAlias] || function (...args: any[]) { // @ts-expect-error
|
|
30
|
+
(window[gaAlias].q = window[gaAlias].q || []).push(args);
|
|
33
31
|
};
|
|
34
32
|
|
|
35
33
|
// provides the plugin for use with analytics.js.
|
|
34
|
+
// @ts-expect-error
|
|
36
35
|
window[gaAlias]('provide', pluginName, pluginConstructor);
|
|
37
|
-
|
|
38
|
-
if (autoRequire && (!window[gaAlias].q || window[gaAlias].q.push === [].push)) {
|
|
39
|
-
// Expecting spy on ga.q push method but not found
|
|
40
|
-
log.error('Auto-require script was expected but not provided.');
|
|
41
|
-
}
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
// Default mapping: object used for building the default mapper from hits to Split events
|
|
@@ -290,5 +284,5 @@ export function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, params: IIn
|
|
|
290
284
|
}
|
|
291
285
|
|
|
292
286
|
// Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
|
|
293
|
-
providePlugin(
|
|
287
|
+
providePlugin('splitTracker', SplitTracker);
|
|
294
288
|
}
|
|
@@ -53,24 +53,13 @@ export interface GoogleAnalyticsToSplitOptions {
|
|
|
53
53
|
* If not provided, events are sent using the key and traffic type provided at SDK config
|
|
54
54
|
*/
|
|
55
55
|
identities?: Identity[],
|
|
56
|
-
/**
|
|
57
|
-
* Optional flag to log an error if the `auto-require` script is not detected.
|
|
58
|
-
* The auto-require script automatically requires the `splitTracker` plugin for created trackers,
|
|
59
|
-
* and should be placed right after your Google Analytics, GTM or gtag.js script tag.
|
|
60
|
-
*
|
|
61
|
-
* @see {@link https://help.split.io/hc/en-us/articles/360040838752#google-tag-manager}
|
|
62
|
-
*
|
|
63
|
-
* @property {boolean} autoRequire
|
|
64
|
-
* @default false
|
|
65
|
-
*/
|
|
66
|
-
autoRequire?: boolean,
|
|
67
56
|
}
|
|
68
57
|
|
|
69
58
|
/**
|
|
70
59
|
* Enable 'Google Analytics to Split' integration, to track Google Analytics hits as Split events.
|
|
71
60
|
* Used by the browser variant of the isomorphic JS SDK.
|
|
72
61
|
*
|
|
73
|
-
* @see {@link https://help.split.io/hc/en-us/articles/
|
|
62
|
+
* @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#google-analytics-to-split}
|
|
74
63
|
*/
|
|
75
64
|
export interface IGoogleAnalyticsToSplitConfig extends GoogleAnalyticsToSplitOptions {
|
|
76
65
|
type: 'GOOGLE_ANALYTICS_TO_SPLIT'
|
|
@@ -140,7 +129,7 @@ export interface SplitToGoogleAnalyticsOptions {
|
|
|
140
129
|
* Enable 'Split to Google Analytics' integration, to track Split impressions and events as Google Analytics hits.
|
|
141
130
|
* Used by the browser variant of the isomorphic JS SDK.
|
|
142
131
|
*
|
|
143
|
-
* @see {@link https://help.split.io/hc/en-us/articles/
|
|
132
|
+
* @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#split-to-google-analytics}
|
|
144
133
|
*/
|
|
145
134
|
export interface ISplitToGoogleAnalyticsConfig extends SplitToGoogleAnalyticsOptions {
|
|
146
135
|
type: 'SPLIT_TO_GOOGLE_ANALYTICS'
|
|
@@ -5,7 +5,7 @@ import { ILogger } from '../logger/types';
|
|
|
5
5
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Add in memory attributes storage methods and combine them with any attribute received from the getTreatment/s call
|
|
8
|
+
* Add in memory attributes storage methods and combine them with any attribute received from the getTreatment/s call
|
|
9
9
|
*/
|
|
10
10
|
export function clientAttributesDecoration<TClient extends SplitIO.IClient | SplitIO.IAsyncClient>(log: ILogger, client: TClient) {
|
|
11
11
|
|
|
@@ -52,10 +52,10 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
|
|
|
52
52
|
getTreatments: getTreatments,
|
|
53
53
|
getTreatmentsWithConfig: getTreatmentsWithConfig,
|
|
54
54
|
track: track,
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
/**
|
|
57
57
|
* Add an attribute to client's in memory attributes storage
|
|
58
|
-
*
|
|
58
|
+
*
|
|
59
59
|
* @param {string} attributeName Attrinute name
|
|
60
60
|
* @param {string, number, boolean, list} attributeValue Attribute value
|
|
61
61
|
* @returns {boolean} true if the attribute was stored and false otherways
|
|
@@ -70,7 +70,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
|
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Returns the attribute with the given key
|
|
73
|
-
*
|
|
73
|
+
*
|
|
74
74
|
* @param {string} attributeName Attribute name
|
|
75
75
|
* @returns {Object} Attribute with the given key
|
|
76
76
|
*/
|
|
@@ -81,7 +81,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
|
|
|
81
81
|
|
|
82
82
|
/**
|
|
83
83
|
* Add to client's in memory attributes storage the attributes in 'attributes'
|
|
84
|
-
*
|
|
84
|
+
*
|
|
85
85
|
* @param {Object} attributes Object with attributes to store
|
|
86
86
|
* @returns true if attributes were stored an false otherways
|
|
87
87
|
*/
|
|
@@ -92,7 +92,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
|
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* Return all the attributes stored in client's in memory attributes storage
|
|
95
|
-
*
|
|
95
|
+
*
|
|
96
96
|
* @returns {Object} returns all the stored attributes
|
|
97
97
|
*/
|
|
98
98
|
getAttributes(): Record<string, Object> {
|
|
@@ -101,8 +101,8 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
|
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
* Removes from client's in memory attributes storage the attribute with the given key
|
|
104
|
-
*
|
|
105
|
-
* @param {string} attributeName
|
|
104
|
+
*
|
|
105
|
+
* @param {string} attributeName
|
|
106
106
|
* @returns {boolean} true if attribute was removed and false otherways
|
|
107
107
|
*/
|
|
108
108
|
removeAttribute(attributeName: string) {
|
|
@@ -116,7 +116,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
|
|
|
116
116
|
clearAttributes() {
|
|
117
117
|
return attributeStorage.clear();
|
|
118
118
|
}
|
|
119
|
-
|
|
119
|
+
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
}
|