@splitsoftware/splitio-commons 2.7.9-rc.0 → 2.7.9-rc.2
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 +9 -3
- package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +8 -4
- package/cjs/logger/constants.js +2 -2
- package/cjs/logger/index.js +0 -3
- package/cjs/logger/messages/info.js +1 -1
- package/cjs/logger/messages/warn.js +3 -3
- package/cjs/readiness/readinessManager.js +3 -5
- package/cjs/readiness/sdkReadinessManager.js +46 -10
- package/cjs/sdkClient/client.js +4 -4
- package/cjs/sdkClient/clientInputValidation.js +1 -1
- package/cjs/sdkManager/index.js +3 -3
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +2 -1
- package/cjs/storages/pluggable/index.js +2 -1
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +2 -1
- package/cjs/sync/streaming/SSEClient/index.js +2 -1
- package/cjs/sync/streaming/SSEHandler/index.js +1 -1
- package/cjs/sync/streaming/pushManager.js +1 -1
- package/cjs/sync/submitters/telemetrySubmitter.js +7 -6
- package/cjs/trackers/telemetryTracker.js +6 -6
- package/cjs/utils/inputValidation/index.js +2 -1
- package/cjs/utils/inputValidation/isOperational.js +9 -4
- package/cjs/utils/inputValidation/splitExistence.js +3 -3
- package/cjs/utils/key/index.js +5 -1
- package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -1
- package/esm/logger/constants.js +1 -1
- package/esm/logger/index.js +0 -3
- package/esm/logger/messages/info.js +1 -1
- package/esm/logger/messages/warn.js +3 -3
- package/esm/readiness/readinessManager.js +3 -5
- package/esm/readiness/sdkReadinessManager.js +46 -10
- package/esm/sdkClient/client.js +4 -4
- package/esm/sdkClient/clientInputValidation.js +2 -2
- package/esm/sdkManager/index.js +4 -4
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +2 -1
- package/esm/storages/pluggable/index.js +2 -1
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +2 -1
- package/esm/sync/streaming/SSEClient/index.js +2 -1
- package/esm/sync/streaming/SSEHandler/index.js +1 -1
- package/esm/sync/streaming/pushManager.js +2 -2
- package/esm/sync/submitters/telemetrySubmitter.js +7 -6
- package/esm/trackers/telemetryTracker.js +6 -6
- package/esm/utils/inputValidation/index.js +1 -1
- package/esm/utils/inputValidation/isOperational.js +8 -4
- package/esm/utils/inputValidation/splitExistence.js +3 -3
- package/esm/utils/key/index.js +3 -0
- package/package.json +1 -1
- package/src/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.ts +4 -1
- package/src/logger/constants.ts +1 -1
- package/src/logger/index.ts +0 -2
- package/src/logger/messages/info.ts +1 -1
- package/src/logger/messages/warn.ts +3 -3
- package/src/readiness/readinessManager.ts +3 -4
- package/src/readiness/sdkReadinessManager.ts +43 -10
- package/src/readiness/types.ts +1 -2
- package/src/sdkClient/client.ts +4 -4
- package/src/sdkClient/clientInputValidation.ts +3 -3
- package/src/sdkManager/index.ts +4 -4
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +2 -1
- package/src/storages/pluggable/index.ts +2 -1
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +2 -1
- package/src/sync/streaming/SSEClient/index.ts +2 -1
- package/src/sync/streaming/SSEHandler/index.ts +1 -1
- package/src/sync/streaming/pushManager.ts +2 -2
- package/src/sync/submitters/telemetrySubmitter.ts +7 -6
- package/src/trackers/telemetryTracker.ts +6 -6
- package/src/types.ts +0 -15
- package/src/utils/inputValidation/index.ts +1 -1
- package/src/utils/inputValidation/isOperational.ts +9 -4
- package/src/utils/inputValidation/splitExistence.ts +3 -3
- package/src/utils/key/index.ts +5 -0
- package/types/splitio.d.ts +77 -10
- package/cjs/evaluator/fallbackTreatmentsCalculator/constants.js +0 -8
- package/esm/evaluator/fallbackTreatmentsCalculator/constants.js +0 -5
- package/src/evaluator/fallbackTreatmentsCalculator/constants.ts +0 -4
|
@@ -19,7 +19,7 @@ export var codesInfo = codesWarn.concat([
|
|
|
19
19
|
[c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
|
|
20
20
|
[c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
|
|
21
21
|
[c.POLLING_STOP, c.LOG_PREFIX_SYNC_POLLING + 'Stopping polling'],
|
|
22
|
-
[c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying
|
|
22
|
+
[c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying fetch of feature flags (attempt #%s). Reason: %s'],
|
|
23
23
|
[c.SUBMITTERS_PUSH_FULL_QUEUE, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing full %s queue and resetting timer.'],
|
|
24
24
|
[c.SUBMITTERS_PUSH, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Pushing %s.'],
|
|
25
25
|
[c.SUBMITTERS_PUSH_PAGE_HIDDEN, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing %s because page became hidden.'],
|
|
@@ -5,7 +5,7 @@ export var codesWarn = codesError.concat([
|
|
|
5
5
|
[c.ENGINE_VALUE_INVALID, c.LOG_PREFIX_ENGINE_VALUE + 'Value %s doesn\'t match with expected type.'],
|
|
6
6
|
[c.ENGINE_VALUE_NO_ATTRIBUTES, c.LOG_PREFIX_ENGINE_VALUE + 'Defined attribute `%s`. No attributes received.'],
|
|
7
7
|
// synchronizer
|
|
8
|
-
[c.SYNC_MYSEGMENTS_FETCH_RETRY, c.LOG_PREFIX_SYNC_MYSEGMENTS + 'Retrying
|
|
8
|
+
[c.SYNC_MYSEGMENTS_FETCH_RETRY, c.LOG_PREFIX_SYNC_MYSEGMENTS + 'Retrying fetch of memberships (attempt #%s). Reason: %s'],
|
|
9
9
|
[c.SYNC_SPLITS_FETCH_FAILS, c.LOG_PREFIX_SYNC_SPLITS + 'Error while doing fetch of feature flags. %s'],
|
|
10
10
|
[c.STREAMING_PARSING_ERROR_FAILS, c.LOG_PREFIX_SYNC_STREAMING + 'Error parsing SSE error notification: %s'],
|
|
11
11
|
[c.STREAMING_PARSING_MESSAGE_FAILS, c.LOG_PREFIX_SYNC_STREAMING + 'Error parsing SSE message notification: %s'],
|
|
@@ -13,8 +13,8 @@ export var codesWarn = codesError.concat([
|
|
|
13
13
|
[c.SUBMITTERS_PUSH_FAILS, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Dropping %s after retry. Reason: %s.'],
|
|
14
14
|
[c.SUBMITTERS_PUSH_RETRY, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Failed to push %s, keeping data to retry on next iteration. Reason: %s.'],
|
|
15
15
|
// client status
|
|
16
|
-
[c.
|
|
17
|
-
[c.CLIENT_NO_LISTENER, 'No listeners for
|
|
16
|
+
[c.CLIENT_NOT_READY_FROM_CACHE, '%s: the SDK is not ready to evaluate. Results may be incorrect%s. Make sure to wait for SDK readiness before using this method.'],
|
|
17
|
+
[c.CLIENT_NO_LISTENER, 'No listeners for SDK_READY event detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet synchronized with the backend.'],
|
|
18
18
|
// input validation
|
|
19
19
|
[c.WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'],
|
|
20
20
|
[c.WARN_TRIMMING_PROPERTIES, '%s: more than 300 properties were provided. Some of them will be trimmed when processed.'],
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED, SDK_SEGMENTS_ARRIVED, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE, SDK_READY } from './constants';
|
|
3
|
-
import { STORAGE_LOCALSTORAGE } from '../utils/constants';
|
|
4
3
|
function splitsEventEmitterFactory(EventEmitter) {
|
|
5
4
|
var splitsEventEmitter = objectAssign(new EventEmitter(), {
|
|
6
5
|
splitsArrived: false,
|
|
@@ -72,7 +71,7 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
72
71
|
if (!isReady && !isDestroyed) {
|
|
73
72
|
try {
|
|
74
73
|
syncLastUpdate();
|
|
75
|
-
gate.emit(SDK_READY_FROM_CACHE);
|
|
74
|
+
gate.emit(SDK_READY_FROM_CACHE, isReady);
|
|
76
75
|
}
|
|
77
76
|
catch (e) {
|
|
78
77
|
// throws user callback exceptions in next tick
|
|
@@ -81,7 +80,6 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
function checkIsReadyOrUpdate(diff) {
|
|
84
|
-
var _a;
|
|
85
83
|
if (isDestroyed)
|
|
86
84
|
return;
|
|
87
85
|
if (isReady) {
|
|
@@ -100,9 +98,9 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
100
98
|
isReady = true;
|
|
101
99
|
try {
|
|
102
100
|
syncLastUpdate();
|
|
103
|
-
if (!isReadyFromCache
|
|
101
|
+
if (!isReadyFromCache) {
|
|
104
102
|
isReadyFromCache = true;
|
|
105
|
-
gate.emit(SDK_READY_FROM_CACHE);
|
|
103
|
+
gate.emit(SDK_READY_FROM_CACHE, isReady);
|
|
106
104
|
}
|
|
107
105
|
gate.emit(SDK_READY);
|
|
108
106
|
}
|
|
@@ -5,6 +5,7 @@ import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from
|
|
|
5
5
|
import { ERROR_CLIENT_LISTENER, CLIENT_READY_FROM_CACHE, CLIENT_READY, CLIENT_NO_LISTENER } from '../logger/constants';
|
|
6
6
|
var NEW_LISTENER_EVENT = 'newListener';
|
|
7
7
|
var REMOVE_LISTENER_EVENT = 'removeListener';
|
|
8
|
+
var TIMEOUT_ERROR = new Error(SDK_READY_TIMED_OUT);
|
|
8
9
|
/**
|
|
9
10
|
* SdkReadinessManager factory, which provides the public status API of SDK clients and manager: ready promise, readiness event emitter and constants (SDK_READY, etc).
|
|
10
11
|
* It also updates logs related warnings and errors.
|
|
@@ -31,6 +32,9 @@ export function sdkReadinessManagerFactory(EventEmitter, settings, readinessMana
|
|
|
31
32
|
readyCbCount++;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
35
|
+
else if (event === SDK_READY_FROM_CACHE && readinessManager.isReadyFromCache()) {
|
|
36
|
+
log.error(ERROR_CLIENT_LISTENER, ['SDK_READY_FROM_CACHE']);
|
|
37
|
+
}
|
|
34
38
|
});
|
|
35
39
|
/** Ready promise */
|
|
36
40
|
var readyPromise = generateReadyPromise();
|
|
@@ -55,6 +59,17 @@ export function sdkReadinessManagerFactory(EventEmitter, settings, readinessMana
|
|
|
55
59
|
}), defaultOnRejected);
|
|
56
60
|
return promise;
|
|
57
61
|
}
|
|
62
|
+
function getStatus() {
|
|
63
|
+
return {
|
|
64
|
+
isReady: readinessManager.isReady(),
|
|
65
|
+
isReadyFromCache: readinessManager.isReadyFromCache(),
|
|
66
|
+
isTimedout: readinessManager.isTimedout(),
|
|
67
|
+
hasTimedout: readinessManager.hasTimedout(),
|
|
68
|
+
isDestroyed: readinessManager.isDestroyed(),
|
|
69
|
+
isOperational: readinessManager.isOperational(),
|
|
70
|
+
lastUpdate: readinessManager.lastUpdate(),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
58
73
|
return {
|
|
59
74
|
readinessManager: readinessManager,
|
|
60
75
|
shared: function () {
|
|
@@ -73,6 +88,7 @@ export function sdkReadinessManagerFactory(EventEmitter, settings, readinessMana
|
|
|
73
88
|
SDK_UPDATE: SDK_UPDATE,
|
|
74
89
|
SDK_READY_TIMED_OUT: SDK_READY_TIMED_OUT,
|
|
75
90
|
},
|
|
91
|
+
// @TODO: remove in next major
|
|
76
92
|
ready: function () {
|
|
77
93
|
if (readinessManager.hasTimedout()) {
|
|
78
94
|
if (!readinessManager.isReady()) {
|
|
@@ -84,17 +100,37 @@ export function sdkReadinessManagerFactory(EventEmitter, settings, readinessMana
|
|
|
84
100
|
}
|
|
85
101
|
return readyPromise;
|
|
86
102
|
},
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
whenReady: function () {
|
|
104
|
+
return new Promise(function (resolve, reject) {
|
|
105
|
+
if (readinessManager.isReady()) {
|
|
106
|
+
resolve();
|
|
107
|
+
}
|
|
108
|
+
else if (readinessManager.hasTimedout()) {
|
|
109
|
+
reject(TIMEOUT_ERROR);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
readinessManager.gate.once(SDK_READY, resolve);
|
|
113
|
+
readinessManager.gate.once(SDK_READY_TIMED_OUT, function () { return reject(TIMEOUT_ERROR); });
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
whenReadyFromCache: function () {
|
|
118
|
+
return new Promise(function (resolve, reject) {
|
|
119
|
+
if (readinessManager.isReadyFromCache()) {
|
|
120
|
+
resolve(readinessManager.isReady());
|
|
121
|
+
}
|
|
122
|
+
else if (readinessManager.hasTimedout()) {
|
|
123
|
+
reject(TIMEOUT_ERROR);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
readinessManager.gate.once(SDK_READY_FROM_CACHE, function () { return resolve(readinessManager.isReady()); });
|
|
127
|
+
readinessManager.gate.once(SDK_READY_TIMED_OUT, function () { return reject(TIMEOUT_ERROR); });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
97
130
|
},
|
|
131
|
+
getStatus: getStatus,
|
|
132
|
+
// @TODO: remove in next major
|
|
133
|
+
__getStatus: getStatus
|
|
98
134
|
})
|
|
99
135
|
};
|
|
100
136
|
}
|
package/esm/sdkClient/client.js
CHANGED
|
@@ -41,7 +41,7 @@ export function clientFactory(params) {
|
|
|
41
41
|
stopTelemetryTracker(queue[0] && queue[0].imp.label);
|
|
42
42
|
return treatment;
|
|
43
43
|
};
|
|
44
|
-
var evaluation = readinessManager.
|
|
44
|
+
var evaluation = readinessManager.isReadyFromCache() ?
|
|
45
45
|
evaluateFeature(log, key, featureFlagName, attributes, storage) :
|
|
46
46
|
isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
|
|
47
47
|
Promise.resolve(treatmentNotReady) :
|
|
@@ -66,7 +66,7 @@ export function clientFactory(params) {
|
|
|
66
66
|
stopTelemetryTracker(queue[0] && queue[0].imp.label);
|
|
67
67
|
return treatments;
|
|
68
68
|
};
|
|
69
|
-
var evaluations = readinessManager.
|
|
69
|
+
var evaluations = readinessManager.isReadyFromCache() ?
|
|
70
70
|
evaluateFeatures(log, key, featureFlagNames, attributes, storage) :
|
|
71
71
|
isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
|
|
72
72
|
Promise.resolve(treatmentsNotReady(featureFlagNames)) :
|
|
@@ -92,7 +92,7 @@ export function clientFactory(params) {
|
|
|
92
92
|
stopTelemetryTracker(queue[0] && queue[0].imp.label);
|
|
93
93
|
return treatments;
|
|
94
94
|
};
|
|
95
|
-
var evaluations = readinessManager.
|
|
95
|
+
var evaluations = readinessManager.isReadyFromCache() ?
|
|
96
96
|
evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, methodName) :
|
|
97
97
|
isAsync ?
|
|
98
98
|
Promise.resolve({}) :
|
|
@@ -117,7 +117,7 @@ export function clientFactory(params) {
|
|
|
117
117
|
if (treatment === CONTROL) {
|
|
118
118
|
var fallbackTreatment = fallbackTreatmentsCalculator.resolve(featureFlagName, label);
|
|
119
119
|
treatment = fallbackTreatment.treatment;
|
|
120
|
-
label = fallbackTreatment.label
|
|
120
|
+
label = fallbackTreatment.label;
|
|
121
121
|
config = fallbackTreatment.config;
|
|
122
122
|
}
|
|
123
123
|
log.info(IMPRESSION, [featureFlagName, matchingKey, treatment, label]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { validateAttributes, validateEvent, validateEventValue, validateEventProperties, validateKey, validateSplit, validateSplits, validateTrafficType, validateIfNotDestroyed,
|
|
1
|
+
import { validateAttributes, validateEvent, validateEventValue, validateEventProperties, validateKey, validateSplit, validateSplits, validateTrafficType, validateIfNotDestroyed, validateIfReadyFromCache, validateEvaluationOptions } from '../utils/inputValidation';
|
|
2
2
|
import { startsWith } from '../utils/lang';
|
|
3
3
|
import { GET_TREATMENT, GET_TREATMENTS, GET_TREATMENTS_BY_FLAG_SET, GET_TREATMENTS_BY_FLAG_SETS, GET_TREATMENTS_WITH_CONFIG, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, GET_TREATMENT_WITH_CONFIG, TRACK_FN_LABEL } from '../utils/constants';
|
|
4
4
|
import { isConsumerMode } from '../utils/settingsValidation/mode';
|
|
@@ -23,7 +23,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
23
23
|
var attributes = validateAttributes(log, maybeAttributes, methodName);
|
|
24
24
|
var isNotDestroyed = validateIfNotDestroyed(log, readinessManager, methodName);
|
|
25
25
|
var options = validateEvaluationOptions(log, maybeOptions, methodName);
|
|
26
|
-
|
|
26
|
+
validateIfReadyFromCache(log, readinessManager, methodName, nameOrNames);
|
|
27
27
|
var valid = isNotDestroyed && key && nameOrNames && attributes !== false;
|
|
28
28
|
return {
|
|
29
29
|
valid: valid,
|
package/esm/sdkManager/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
3
|
import { find } from '../utils/lang';
|
|
4
|
-
import { validateSplit, validateSplitExistence,
|
|
4
|
+
import { validateSplit, validateSplitExistence, validateIfOperational } from '../utils/inputValidation';
|
|
5
5
|
import { isConsumerMode } from '../utils/settingsValidation/mode';
|
|
6
6
|
import { SPLIT_FN_LABEL, SPLITS_FN_LABEL, NAMES_FN_LABEL } from '../utils/constants';
|
|
7
7
|
function collectTreatments(splitObject) {
|
|
@@ -51,7 +51,7 @@ export function sdkManagerFactory(settings, splits, _a) {
|
|
|
51
51
|
*/
|
|
52
52
|
split: function (featureFlagName) {
|
|
53
53
|
var splitName = validateSplit(log, featureFlagName, SPLIT_FN_LABEL);
|
|
54
|
-
if (!
|
|
54
|
+
if (!validateIfOperational(log, readinessManager, SPLIT_FN_LABEL) || !splitName) {
|
|
55
55
|
return isAsync ? Promise.resolve(null) : null;
|
|
56
56
|
}
|
|
57
57
|
var split = splits.getSplit(splitName);
|
|
@@ -68,7 +68,7 @@ export function sdkManagerFactory(settings, splits, _a) {
|
|
|
68
68
|
* Get the feature flag objects present on the factory storage
|
|
69
69
|
*/
|
|
70
70
|
splits: function () {
|
|
71
|
-
if (!
|
|
71
|
+
if (!validateIfOperational(log, readinessManager, SPLITS_FN_LABEL)) {
|
|
72
72
|
return isAsync ? Promise.resolve([]) : [];
|
|
73
73
|
}
|
|
74
74
|
var currentSplits = splits.getAll();
|
|
@@ -80,7 +80,7 @@ export function sdkManagerFactory(settings, splits, _a) {
|
|
|
80
80
|
* Get the feature flag names present on the factory storage
|
|
81
81
|
*/
|
|
82
82
|
names: function () {
|
|
83
|
-
if (!
|
|
83
|
+
if (!validateIfOperational(log, readinessManager, NAMES_FN_LABEL)) {
|
|
84
84
|
return isAsync ? Promise.resolve([]) : [];
|
|
85
85
|
}
|
|
86
86
|
var splitNames = splits.getSplitNames();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEDUPED, DROPPED, LOCALHOST_MODE, QUEUED } from '../../utils/constants';
|
|
2
|
+
import { checkIfServerSide } from '../../utils/key';
|
|
2
3
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
3
4
|
var MAX_STREAMING_EVENTS = 20;
|
|
4
5
|
var MAX_TAGS = 10;
|
|
@@ -15,7 +16,7 @@ var ACCEPTANCE_RANGE = 0.001;
|
|
|
15
16
|
*/
|
|
16
17
|
export function shouldRecordTelemetry(_a) {
|
|
17
18
|
var settings = _a.settings;
|
|
18
|
-
return settings.mode !== LOCALHOST_MODE && (settings
|
|
19
|
+
return settings.mode !== LOCALHOST_MODE && (checkIfServerSide(settings) || Math.random() <= ACCEPTANCE_RANGE);
|
|
19
20
|
}
|
|
20
21
|
var TelemetryCacheInMemory = /** @class */ (function () {
|
|
21
22
|
function TelemetryCacheInMemory(splits, segments, largeSegments) {
|
|
@@ -20,6 +20,7 @@ import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS
|
|
|
20
20
|
import { metadataBuilder } from '../utils';
|
|
21
21
|
import { LOG_PREFIX } from '../pluggable/constants';
|
|
22
22
|
import { RBSegmentsCachePluggable } from './RBSegmentsCachePluggable';
|
|
23
|
+
import { checkIfServerSide } from '../../utils/key';
|
|
23
24
|
var NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
|
|
24
25
|
var NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';
|
|
25
26
|
/**
|
|
@@ -67,7 +68,7 @@ export function PluggableStorage(options) {
|
|
|
67
68
|
new ImpressionCountsCacheInMemory() :
|
|
68
69
|
new ImpressionCountsCachePluggable(log, keys.buildImpressionsCountKey(), wrapper);
|
|
69
70
|
var uniqueKeysCache = isPartialConsumer ?
|
|
70
|
-
settings
|
|
71
|
+
checkIfServerSide(settings) ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
|
|
71
72
|
new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper);
|
|
72
73
|
// Connects to wrapper and emits SDK_READY event on main client
|
|
73
74
|
var connectPromise = wrapper.connect().then(function () {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FLAG_SPEC_VERSION } from '../../../utils/constants';
|
|
2
2
|
import { base } from '../../../utils/settingsValidation';
|
|
3
3
|
import { LOG_PREFIX_SYNC_SPLITS } from '../../../logger/constants';
|
|
4
|
+
import { checkIfServerSide } from '../../../utils/key';
|
|
4
5
|
var PROXY_CHECK_INTERVAL_MILLIS_CS = 60 * 60 * 1000; // 1 hour in Client Side
|
|
5
6
|
var PROXY_CHECK_INTERVAL_MILLIS_SS = 24 * PROXY_CHECK_INTERVAL_MILLIS_CS; // 24 hours in Server Side
|
|
6
7
|
function sdkEndpointOverridden(settings) {
|
|
@@ -13,7 +14,7 @@ function sdkEndpointOverridden(settings) {
|
|
|
13
14
|
// @TODO breaking: drop support for Split Proxy below v5.10.0 and simplify the implementation
|
|
14
15
|
export function splitChangesFetcherFactory(fetchSplitChanges, settings, storage) {
|
|
15
16
|
var log = settings.log;
|
|
16
|
-
var PROXY_CHECK_INTERVAL_MILLIS = settings
|
|
17
|
+
var PROXY_CHECK_INTERVAL_MILLIS = checkIfServerSide(settings) ? PROXY_CHECK_INTERVAL_MILLIS_SS : PROXY_CHECK_INTERVAL_MILLIS_CS;
|
|
17
18
|
var lastProxyCheckTimestamp;
|
|
18
19
|
return function splitChangesFetcher(since, noCache, till, rbSince,
|
|
19
20
|
// Optional decorator for `fetchSplitChanges` promise, such as timeout or time tracker
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { decorateHeaders } from '../../../services/decorateHeaders';
|
|
2
|
+
import { checkIfServerSide } from '../../../utils/key';
|
|
2
3
|
import { isString } from '../../../utils/lang';
|
|
3
4
|
import { objectAssign } from '../../../utils/lang/objectAssign';
|
|
4
5
|
var ABLY_API_VERSION = '1.1';
|
|
@@ -57,7 +58,7 @@ var SSEClient = /** @class */ (function () {
|
|
|
57
58
|
return encodeURIComponent(params + channel);
|
|
58
59
|
}).join(',');
|
|
59
60
|
var url = this.settings.urls.streaming + "/sse?channels=" + channelsQueryParam + "&accessToken=" + authToken.token + "&v=" + ABLY_API_VERSION + "&heartbeats=true"; // same results using `&heartbeats=false`
|
|
60
|
-
var isServerSide =
|
|
61
|
+
var isServerSide = checkIfServerSide(this.settings);
|
|
61
62
|
this.connection = new this.eventSource(
|
|
62
63
|
// For client-side SDKs, metadata is passed as query param to avoid CORS issues and because native EventSource implementations in browsers do not support headers
|
|
63
64
|
isServerSide ? url : url + ("&SplitSDKVersion=" + this.headers.SplitSDKVersion + "&SplitSDKClientKey=" + this.headers.SplitSDKClientKey),
|
|
@@ -16,7 +16,7 @@ export function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
|
|
|
16
16
|
// Ably error
|
|
17
17
|
var code = error.parsedData.code;
|
|
18
18
|
telemetryTracker.streamingEvent(ABLY_ERROR, code);
|
|
19
|
-
// 401 errors due to invalid or expired token (e.g., if refresh token
|
|
19
|
+
// 401 errors due to invalid or expired token (e.g., if refresh token couldn't be executed)
|
|
20
20
|
if (40140 <= code && code <= 40149)
|
|
21
21
|
return true;
|
|
22
22
|
// Others 4XX errors (e.g., bad request from the SDK)
|
|
@@ -7,7 +7,7 @@ import { SplitsUpdateWorker } from './UpdateWorkers/SplitsUpdateWorker';
|
|
|
7
7
|
import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
8
8
|
import { forOwn } from '../../utils/lang';
|
|
9
9
|
import { SSEClient } from './SSEClient';
|
|
10
|
-
import { getMatching } from '../../utils/key';
|
|
10
|
+
import { checkIfServerSide, getMatching } from '../../utils/key';
|
|
11
11
|
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
|
|
12
12
|
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
|
|
13
13
|
import { UpdateStrategy } from './SSEHandler/types';
|
|
@@ -23,7 +23,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
23
23
|
var settings = params.settings, storage = params.storage, splitApi = params.splitApi, readiness = params.readiness, platform = params.platform, telemetryTracker = params.telemetryTracker;
|
|
24
24
|
// `userKey` is the matching key of main client in client-side SDK.
|
|
25
25
|
// It can be used to check if running on client-side or server-side SDK.
|
|
26
|
-
var userKey = settings
|
|
26
|
+
var userKey = checkIfServerSide(settings) ? undefined : getMatching(settings.core.key);
|
|
27
27
|
var log = settings.log;
|
|
28
28
|
var sseClient;
|
|
29
29
|
try {
|
|
@@ -6,6 +6,7 @@ import { base } from '../../utils/settingsValidation';
|
|
|
6
6
|
import { usedKeysMap } from '../../utils/inputValidation/apiKey';
|
|
7
7
|
import { timer } from '../../utils/timeTracker/timer';
|
|
8
8
|
import { objectAssign } from '../../utils/lang/objectAssign';
|
|
9
|
+
import { checkIfServerSide } from '../../utils/key';
|
|
9
10
|
var OPERATION_MODE_MAP = (_a = {},
|
|
10
11
|
_a[STANDALONE_MODE] = STANDALONE_ENUM,
|
|
11
12
|
_a[CONSUMER_MODE] = CONSUMER_ENUM,
|
|
@@ -58,14 +59,14 @@ export function telemetryCacheConfigAdapter(telemetry, settings) {
|
|
|
58
59
|
clear: function () { },
|
|
59
60
|
pop: function () {
|
|
60
61
|
var urls = settings.urls, scheduler = settings.scheduler;
|
|
61
|
-
var
|
|
62
|
+
var isServerSide = checkIfServerSide(settings);
|
|
62
63
|
var _a = getTelemetryFlagSetsStats(settings.sync.__splitFiltersValidation), flagSetsTotal = _a.flagSetsTotal, flagSetsIgnored = _a.flagSetsIgnored;
|
|
63
64
|
return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
|
|
64
65
|
sE: settings.streamingEnabled,
|
|
65
66
|
rR: {
|
|
66
67
|
sp: scheduler.featuresRefreshRate / 1000,
|
|
67
|
-
se:
|
|
68
|
-
ms:
|
|
68
|
+
se: isServerSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
|
|
69
|
+
ms: isServerSide ? undefined : scheduler.segmentsRefreshRate / 1000,
|
|
69
70
|
im: scheduler.impressionsRefreshRate / 1000,
|
|
70
71
|
ev: scheduler.eventsPushRate / 1000,
|
|
71
72
|
te: scheduler.telemetryRefreshRate / 1000,
|
|
@@ -102,14 +103,14 @@ export function telemetrySubmitterFactory(params) {
|
|
|
102
103
|
if (!telemetry || !now)
|
|
103
104
|
return; // No submitter created if telemetry cache is not defined
|
|
104
105
|
var settings = params.settings, _a = params.settings, log = _a.log, telemetryRefreshRate = _a.scheduler.telemetryRefreshRate, splitApi = params.splitApi, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
|
|
105
|
-
var
|
|
106
|
+
var stopTimer = timer(now);
|
|
106
107
|
var submitter = firstPushWindowDecorator(submitterFactory(log, splitApi.postMetricsUsage, telemetry, telemetryRefreshRate, undefined, 0, true), telemetryRefreshRate);
|
|
107
108
|
readiness.gate.once(SDK_READY_FROM_CACHE, function () {
|
|
108
|
-
telemetry.recordTimeUntilReadyFromCache(
|
|
109
|
+
telemetry.recordTimeUntilReadyFromCache(stopTimer());
|
|
109
110
|
});
|
|
110
111
|
sdkReadinessManager.incInternalReadyCbCount();
|
|
111
112
|
readiness.gate.once(SDK_READY, function () {
|
|
112
|
-
telemetry.recordTimeUntilReady(
|
|
113
|
+
telemetry.recordTimeUntilReady(stopTimer());
|
|
113
114
|
// Post config data when the SDK is ready and if the telemetry submitter was started
|
|
114
115
|
if (submitter.isRunning()) {
|
|
115
116
|
var postMetricsConfigTask = submitterFactory(log, splitApi.postMetricsConfig, telemetryCacheConfigAdapter(telemetry, settings), 0, undefined, 0, true);
|
|
@@ -3,10 +3,10 @@ import { timer } from '../utils/timeTracker/timer';
|
|
|
3
3
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../utils/constants';
|
|
4
4
|
export function telemetryTrackerFactory(telemetryCache, now) {
|
|
5
5
|
if (telemetryCache && now) {
|
|
6
|
-
var
|
|
6
|
+
var sessionTimer_1 = timer(now);
|
|
7
7
|
return {
|
|
8
8
|
trackEval: function (method) {
|
|
9
|
-
var
|
|
9
|
+
var evalTimer = timer(now);
|
|
10
10
|
return function (label) {
|
|
11
11
|
switch (label) {
|
|
12
12
|
case EXCEPTION:
|
|
@@ -16,13 +16,13 @@ export function telemetryTrackerFactory(telemetryCache, now) {
|
|
|
16
16
|
if (telemetryCache.recordNonReadyUsage)
|
|
17
17
|
telemetryCache.recordNonReadyUsage();
|
|
18
18
|
}
|
|
19
|
-
telemetryCache.recordLatency(method,
|
|
19
|
+
telemetryCache.recordLatency(method, evalTimer());
|
|
20
20
|
};
|
|
21
21
|
},
|
|
22
22
|
trackHttp: function (operation) {
|
|
23
|
-
var
|
|
23
|
+
var httpTimer = timer(now);
|
|
24
24
|
return function (error) {
|
|
25
|
-
telemetryCache.recordHttpLatency(operation,
|
|
25
|
+
telemetryCache.recordHttpLatency(operation, httpTimer());
|
|
26
26
|
if (error && error.statusCode)
|
|
27
27
|
telemetryCache.recordHttpError(operation, error.statusCode);
|
|
28
28
|
else
|
|
@@ -31,7 +31,7 @@ export function telemetryTrackerFactory(telemetryCache, now) {
|
|
|
31
31
|
},
|
|
32
32
|
sessionLength: function () {
|
|
33
33
|
if (telemetryCache.recordSessionLength)
|
|
34
|
-
telemetryCache.recordSessionLength(
|
|
34
|
+
telemetryCache.recordSessionLength(sessionTimer_1());
|
|
35
35
|
},
|
|
36
36
|
streamingEvent: function (e, d) {
|
|
37
37
|
if (e === AUTH_REJECTION) {
|
|
@@ -7,7 +7,7 @@ export { validateKey } from './key';
|
|
|
7
7
|
export { validateSplit } from './split';
|
|
8
8
|
export { validateSplits } from './splits';
|
|
9
9
|
export { validateTrafficType } from './trafficType';
|
|
10
|
-
export { validateIfNotDestroyed, validateIfOperational } from './isOperational';
|
|
10
|
+
export { validateIfNotDestroyed, validateIfReadyFromCache, validateIfOperational } from './isOperational';
|
|
11
11
|
export { validateSplitExistence } from './splitExistence';
|
|
12
12
|
export { validateTrafficTypeExistence } from './trafficTypeExistence';
|
|
13
13
|
export { validateEvaluationOptions } from './eventProperties';
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { ERROR_CLIENT_DESTROYED,
|
|
1
|
+
import { ERROR_CLIENT_DESTROYED, CLIENT_NOT_READY_FROM_CACHE } from '../../logger/constants';
|
|
2
2
|
export function validateIfNotDestroyed(log, readinessManager, method) {
|
|
3
3
|
if (!readinessManager.isDestroyed())
|
|
4
4
|
return true;
|
|
5
5
|
log.error(ERROR_CLIENT_DESTROYED, [method]);
|
|
6
6
|
return false;
|
|
7
7
|
}
|
|
8
|
-
export function
|
|
9
|
-
if (readinessManager.
|
|
8
|
+
export function validateIfReadyFromCache(log, readinessManager, method, featureFlagNameOrNames) {
|
|
9
|
+
if (readinessManager.isReadyFromCache())
|
|
10
10
|
return true;
|
|
11
|
-
log.warn(
|
|
11
|
+
log.warn(CLIENT_NOT_READY_FROM_CACHE, [method, featureFlagNameOrNames ? " for feature flag " + featureFlagNameOrNames.toString() : '']);
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
|
+
// Operational means that the SDK is ready to evaluate (not destroyed and ready from cache)
|
|
15
|
+
export function validateIfOperational(log, readinessManager, method, featureFlagNameOrNames) {
|
|
16
|
+
return validateIfNotDestroyed(log, readinessManager, method) && validateIfReadyFromCache(log, readinessManager, method, featureFlagNameOrNames);
|
|
17
|
+
}
|
|
@@ -2,11 +2,11 @@ import { FALLBACK_SPLIT_NOT_FOUND, SPLIT_NOT_FOUND } from '../labels';
|
|
|
2
2
|
import { WARN_NOT_EXISTENT_SPLIT } from '../../logger/constants';
|
|
3
3
|
/**
|
|
4
4
|
* This is defined here and in this format mostly because of the logger and the fact that it's considered a validation at product level.
|
|
5
|
-
* But it's not going to run on the input validation layer. In any case, the most
|
|
5
|
+
* But it's not going to run on the input validation layer. In any case, the most compelling reason to use it as we do is to avoid going to Redis and get a split twice.
|
|
6
6
|
*/
|
|
7
7
|
export function validateSplitExistence(log, readinessManager, splitName, labelOrSplitObj, method) {
|
|
8
|
-
if (readinessManager.isReady()) { // Only if it's ready we validate this, otherwise it may just be that the SDK is
|
|
9
|
-
if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj
|
|
8
|
+
if (readinessManager.isReady()) { // Only if it's ready (synced with BE) we validate this, otherwise it may just be that the SDK is still syncing
|
|
9
|
+
if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj === FALLBACK_SPLIT_NOT_FOUND || labelOrSplitObj == null) {
|
|
10
10
|
log.warn(WARN_NOT_EXISTENT_SPLIT, [method, splitName]);
|
|
11
11
|
return false;
|
|
12
12
|
}
|
package/esm/utils/key/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Treatment, TreatmentWithConfig } from '../../../../types/splitio';
|
|
2
2
|
import { ILogger } from '../../../logger/types';
|
|
3
3
|
import { isObject, isString } from '../../../utils/lang';
|
|
4
|
-
import { FallbackDiscardReason } from '../constants';
|
|
5
4
|
|
|
5
|
+
enum FallbackDiscardReason {
|
|
6
|
+
FlagName = 'Invalid flag name (max 100 chars, no spaces)',
|
|
7
|
+
Treatment = 'Invalid treatment (max 100 chars and must match pattern)',
|
|
8
|
+
}
|
|
6
9
|
|
|
7
10
|
export class FallbacksSanitizer {
|
|
8
11
|
|
package/src/logger/constants.ts
CHANGED
|
@@ -60,7 +60,7 @@ export const SUBMITTERS_PUSH_PAGE_HIDDEN = 125;
|
|
|
60
60
|
export const ENGINE_VALUE_INVALID = 200;
|
|
61
61
|
export const ENGINE_VALUE_NO_ATTRIBUTES = 201;
|
|
62
62
|
export const CLIENT_NO_LISTENER = 202;
|
|
63
|
-
export const
|
|
63
|
+
export const CLIENT_NOT_READY_FROM_CACHE = 203;
|
|
64
64
|
export const SYNC_MYSEGMENTS_FETCH_RETRY = 204;
|
|
65
65
|
export const SYNC_SPLITS_FETCH_FAILS = 205;
|
|
66
66
|
export const STREAMING_PARSING_ERROR_FAILS = 206;
|
package/src/logger/index.ts
CHANGED
|
@@ -72,8 +72,6 @@ export class Logger implements ILogger {
|
|
|
72
72
|
if (logger) {
|
|
73
73
|
if (isLogger(logger)) {
|
|
74
74
|
this.logger = logger;
|
|
75
|
-
// If custom logger is set, all logs are either enabled or disabled
|
|
76
|
-
if (this.logLevel !== LogLevelIndexes.NONE) this.setLogLevel(LogLevels.DEBUG);
|
|
77
75
|
return;
|
|
78
76
|
} else {
|
|
79
77
|
this.error('Invalid `logger` instance. It must be an object with `debug`, `info`, `warn` and `error` methods. Defaulting to `console.log`');
|
|
@@ -22,7 +22,7 @@ export const codesInfo: [number, string][] = codesWarn.concat([
|
|
|
22
22
|
[c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
|
|
23
23
|
[c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
|
|
24
24
|
[c.POLLING_STOP, c.LOG_PREFIX_SYNC_POLLING + 'Stopping polling'],
|
|
25
|
-
[c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying
|
|
25
|
+
[c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying fetch of feature flags (attempt #%s). Reason: %s'],
|
|
26
26
|
[c.SUBMITTERS_PUSH_FULL_QUEUE, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing full %s queue and resetting timer.'],
|
|
27
27
|
[c.SUBMITTERS_PUSH, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Pushing %s.'],
|
|
28
28
|
[c.SUBMITTERS_PUSH_PAGE_HIDDEN, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing %s because page became hidden.'],
|
|
@@ -6,7 +6,7 @@ export const codesWarn: [number, string][] = codesError.concat([
|
|
|
6
6
|
[c.ENGINE_VALUE_INVALID, c.LOG_PREFIX_ENGINE_VALUE + 'Value %s doesn\'t match with expected type.'],
|
|
7
7
|
[c.ENGINE_VALUE_NO_ATTRIBUTES, c.LOG_PREFIX_ENGINE_VALUE + 'Defined attribute `%s`. No attributes received.'],
|
|
8
8
|
// synchronizer
|
|
9
|
-
[c.SYNC_MYSEGMENTS_FETCH_RETRY, c.LOG_PREFIX_SYNC_MYSEGMENTS + 'Retrying
|
|
9
|
+
[c.SYNC_MYSEGMENTS_FETCH_RETRY, c.LOG_PREFIX_SYNC_MYSEGMENTS + 'Retrying fetch of memberships (attempt #%s). Reason: %s'],
|
|
10
10
|
[c.SYNC_SPLITS_FETCH_FAILS, c.LOG_PREFIX_SYNC_SPLITS + 'Error while doing fetch of feature flags. %s'],
|
|
11
11
|
[c.STREAMING_PARSING_ERROR_FAILS, c.LOG_PREFIX_SYNC_STREAMING + 'Error parsing SSE error notification: %s'],
|
|
12
12
|
[c.STREAMING_PARSING_MESSAGE_FAILS, c.LOG_PREFIX_SYNC_STREAMING + 'Error parsing SSE message notification: %s'],
|
|
@@ -14,8 +14,8 @@ export const codesWarn: [number, string][] = codesError.concat([
|
|
|
14
14
|
[c.SUBMITTERS_PUSH_FAILS, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Dropping %s after retry. Reason: %s.'],
|
|
15
15
|
[c.SUBMITTERS_PUSH_RETRY, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Failed to push %s, keeping data to retry on next iteration. Reason: %s.'],
|
|
16
16
|
// client status
|
|
17
|
-
[c.
|
|
18
|
-
[c.CLIENT_NO_LISTENER, 'No listeners for
|
|
17
|
+
[c.CLIENT_NOT_READY_FROM_CACHE, '%s: the SDK is not ready to evaluate. Results may be incorrect%s. Make sure to wait for SDK readiness before using this method.'],
|
|
18
|
+
[c.CLIENT_NO_LISTENER, 'No listeners for SDK_READY event detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet synchronized with the backend.'],
|
|
19
19
|
// input validation
|
|
20
20
|
[c.WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'],
|
|
21
21
|
[c.WARN_TRIMMING_PROPERTIES, '%s: more than 300 properties were provided. Some of them will be trimmed when processed.'],
|
|
@@ -3,7 +3,6 @@ import { ISettings } from '../types';
|
|
|
3
3
|
import SplitIO from '../../types/splitio';
|
|
4
4
|
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED, SDK_SEGMENTS_ARRIVED, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE, SDK_READY } from './constants';
|
|
5
5
|
import { IReadinessEventEmitter, IReadinessManager, ISegmentsEventEmitter, ISplitsEventEmitter } from './types';
|
|
6
|
-
import { STORAGE_LOCALSTORAGE } from '../utils/constants';
|
|
7
6
|
|
|
8
7
|
function splitsEventEmitterFactory(EventEmitter: new () => SplitIO.IEventEmitter): ISplitsEventEmitter {
|
|
9
8
|
const splitsEventEmitter = objectAssign(new EventEmitter(), {
|
|
@@ -91,7 +90,7 @@ export function readinessManagerFactory(
|
|
|
91
90
|
if (!isReady && !isDestroyed) {
|
|
92
91
|
try {
|
|
93
92
|
syncLastUpdate();
|
|
94
|
-
gate.emit(SDK_READY_FROM_CACHE);
|
|
93
|
+
gate.emit(SDK_READY_FROM_CACHE, isReady);
|
|
95
94
|
} catch (e) {
|
|
96
95
|
// throws user callback exceptions in next tick
|
|
97
96
|
setTimeout(() => { throw e; }, 0);
|
|
@@ -115,9 +114,9 @@ export function readinessManagerFactory(
|
|
|
115
114
|
isReady = true;
|
|
116
115
|
try {
|
|
117
116
|
syncLastUpdate();
|
|
118
|
-
if (!isReadyFromCache
|
|
117
|
+
if (!isReadyFromCache) {
|
|
119
118
|
isReadyFromCache = true;
|
|
120
|
-
gate.emit(SDK_READY_FROM_CACHE);
|
|
119
|
+
gate.emit(SDK_READY_FROM_CACHE, isReady);
|
|
121
120
|
}
|
|
122
121
|
gate.emit(SDK_READY);
|
|
123
122
|
} catch (e) {
|