@splitsoftware/splitio-commons 1.8.2-rc.1 → 1.8.2-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 +23 -21
- package/cjs/services/splitApi.js +1 -0
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +6 -10
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +8 -16
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +18 -21
- package/cjs/storages/pluggable/SplitsCachePluggable.js +17 -17
- package/esm/services/splitApi.js +1 -0
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +6 -10
- package/esm/storages/inMemory/SplitsCacheInMemory.js +8 -16
- package/esm/storages/inRedis/SplitsCacheInRedis.js +18 -21
- package/esm/storages/pluggable/SplitsCachePluggable.js +17 -17
- package/package.json +1 -1
- package/src/services/splitApi.ts +1 -0
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +6 -10
- package/src/storages/inMemory/SplitsCacheInMemory.ts +6 -14
- package/src/storages/inRedis/SplitsCacheInRedis.ts +17 -18
- package/src/storages/pluggable/SplitsCachePluggable.ts +16 -17
package/CHANGES.txt
CHANGED
|
@@ -1,42 +1,44 @@
|
|
|
1
|
-
1.8.2 (May
|
|
2
|
-
- Updated
|
|
1
|
+
1.8.2 (May 15, 2023)
|
|
2
|
+
- Updated terminology on the SDKs codebase to be more aligned with current standard without causing a breaking change. The core change is the term split for feature flag on things like logs and intensense comments.
|
|
3
|
+
- Updated split storage modules to optimize some operations when using Redis and pluggable storages.
|
|
4
|
+
- Updated some transitive dependencies for vulnerability fixes.
|
|
3
5
|
|
|
4
6
|
1.8.1 (February 7, 2023)
|
|
5
|
-
- Updated a module import to remove a trailing comma that can cause issues with some bundlers.
|
|
7
|
+
- Updated a module import to remove a trailing comma that can cause issues with some bundlers.
|
|
6
8
|
|
|
7
9
|
1.8.0 (February 3, 2023)
|
|
8
|
-
- Added flush data method to client
|
|
10
|
+
- Added flush data method to client.
|
|
9
11
|
|
|
10
12
|
1.7.3 (December 16, 2022)
|
|
11
|
-
- Updated unique keys cache for Redis and Pluggable storages to optimize the usage of the underlying storage.
|
|
12
|
-
- Updated some transitive dependencies for vulnerability fixes.
|
|
13
|
-
- Bugfixing - Updated events and impressions cache in localhost mode in order to avoid memory leaks (Related to issue https://github.com/splitio/javascript-commons/issues/181).
|
|
13
|
+
- Updated unique keys cache for Redis and Pluggable storages to optimize the usage of the underlying storage.
|
|
14
|
+
- Updated some transitive dependencies for vulnerability fixes.
|
|
15
|
+
- Bugfixing - Updated events and impressions cache in localhost mode in order to avoid memory leaks (Related to issue https://github.com/splitio/javascript-commons/issues/181).
|
|
14
16
|
|
|
15
17
|
1.7.2 (October 14, 2022)
|
|
16
|
-
- Bugfixing - Handle `Navigator.sendBeacon` API exceptions in the browser, and fallback to regular Fetch/XHR transport in case of error.
|
|
18
|
+
- Bugfixing - Handle `Navigator.sendBeacon` API exceptions in the browser, and fallback to regular Fetch/XHR transport in case of error.
|
|
17
19
|
|
|
18
20
|
1.7.1 (October 5, 2022)
|
|
19
|
-
- Updated default value of `scheduler.featuresRefreshRate` config parameter to 60 seconds.
|
|
21
|
+
- Updated default value of `scheduler.featuresRefreshRate` config parameter to 60 seconds.
|
|
20
22
|
|
|
21
23
|
1.7.0 (October 4, 2022)
|
|
22
|
-
- Added a new impressions mode for the SDK called NONE, to be used in factory when there is no desire to capture impressions on an SDK factory to feed Split's analytics engine. Running NONE mode, the SDK will only capture unique keys evaluated for a particular feature flag instead of full blown impressions.
|
|
23
|
-
- Updated SDK telemetry to support pluggable storage, partial consumer mode, and synchronizer.
|
|
24
|
-
- Updated storage implementations to improve the performance of feature flag evaluations (i.e., `getTreatment(s)` method calls) when using the default storage in memory.
|
|
25
|
-
- Updated evaluation flow to avoid unnecessarily storage calls when the SDK is not ready.
|
|
24
|
+
- Added a new impressions mode for the SDK called NONE, to be used in factory when there is no desire to capture impressions on an SDK factory to feed Split's analytics engine. Running NONE mode, the SDK will only capture unique keys evaluated for a particular feature flag instead of full blown impressions.
|
|
25
|
+
- Updated SDK telemetry to support pluggable storage, partial consumer mode, and synchronizer.
|
|
26
|
+
- Updated storage implementations to improve the performance of feature flag evaluations (i.e., `getTreatment(s)` method calls) when using the default storage in memory.
|
|
27
|
+
- Updated evaluation flow to avoid unnecessarily storage calls when the SDK is not ready.
|
|
26
28
|
|
|
27
29
|
1.6.1 (July 22, 2022)
|
|
28
|
-
- Updated GoogleAnalyticsToSplit integration to validate `autoRequire` config parameter and avoid some wrong warning logs when mapping GA hit fields to Split event properties.
|
|
30
|
+
- Updated GoogleAnalyticsToSplit integration to validate `autoRequire` config parameter and avoid some wrong warning logs when mapping GA hit fields to Split event properties.
|
|
29
31
|
|
|
30
32
|
1.6.0 (July 21, 2022)
|
|
31
|
-
- Added `autoRequire` configuration option to the Google Analytics to Split integration, which takes care of requiring the splitTracker plugin on trackers dynamically created by Google tag managers (See https://help.split.io/hc/en-us/articles/360040838752#set-up-with-gtm-and-gtag.js).
|
|
32
|
-
- Updated browser listener to push remaining impressions and events on 'visibilitychange' and 'pagehide' DOM events, instead of 'unload', which is not reliable in modern mobile and desktop Web browsers.
|
|
33
|
-
- Updated the synchronization flow to be more reliable in the event of an edge case generating delay in cache purge propagation, keeping the SDK cache properly synced.
|
|
34
|
-
- Bugfixing - Removed js-yaml dependency to avoid resolution to an incompatible version on certain npm versions when installing third-party dependencies that also define js-yaml as transitive dependency (Related to issue https://github.com/splitio/javascript-client/issues/662).
|
|
33
|
+
- Added `autoRequire` configuration option to the Google Analytics to Split integration, which takes care of requiring the splitTracker plugin on trackers dynamically created by Google tag managers (See https://help.split.io/hc/en-us/articles/360040838752#set-up-with-gtm-and-gtag.js).
|
|
34
|
+
- Updated browser listener to push remaining impressions and events on 'visibilitychange' and 'pagehide' DOM events, instead of 'unload', which is not reliable in modern mobile and desktop Web browsers.
|
|
35
|
+
- Updated the synchronization flow to be more reliable in the event of an edge case generating delay in cache purge propagation, keeping the SDK cache properly synced.
|
|
36
|
+
- Bugfixing - Removed js-yaml dependency to avoid resolution to an incompatible version on certain npm versions when installing third-party dependencies that also define js-yaml as transitive dependency (Related to issue https://github.com/splitio/javascript-client/issues/662).
|
|
35
37
|
|
|
36
38
|
1.5.0 (June 29, 2022)
|
|
37
|
-
- 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 SDK 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.
|
|
38
|
-
- Updated telemetry logic to track the anonymous config for user consent flag set to declined or unknown.
|
|
39
|
-
- 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.
|
|
39
|
+
- 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 SDK 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.
|
|
40
|
+
- Updated telemetry logic to track the anonymous config for user consent flag set to declined or unknown.
|
|
41
|
+
- 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.
|
|
40
42
|
|
|
41
43
|
1.4.1 (June 13, 2022)
|
|
42
44
|
- Bugfixing - Updated submitters logic, to avoid dropping impressions and events that are being tracked while POST request is pending.
|
package/cjs/services/splitApi.js
CHANGED
|
@@ -20,6 +20,7 @@ function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
20
20
|
var SplitSDKImpressionsMode = settings.sync.impressionsMode;
|
|
21
21
|
var splitHttpClient = (0, splitHttpClient_1.splitHttpClientFactory)(settings, platform.getFetch, platform.getOptions);
|
|
22
22
|
return {
|
|
23
|
+
// @TODO throw errors if health check requests fail, to log them in the Synchronizer
|
|
23
24
|
getSdkAPIHealthCheck: function () {
|
|
24
25
|
var url = urls.sdk + "/version";
|
|
25
26
|
return splitHttpClient(url).then(function () { return true; }).catch(function () { return false; });
|
|
@@ -37,10 +37,8 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
37
37
|
SplitsCacheInLocal.prototype._decrementCounts = function (split) {
|
|
38
38
|
try {
|
|
39
39
|
if (split) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this._decrementCount(ttKey);
|
|
43
|
-
}
|
|
40
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
41
|
+
this._decrementCount(ttKey);
|
|
44
42
|
if ((0, AbstractSplitsCacheSync_1.usesSegments)(split)) {
|
|
45
43
|
var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
46
44
|
this._decrementCount(segmentsCountKey);
|
|
@@ -54,11 +52,9 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
54
52
|
SplitsCacheInLocal.prototype._incrementCounts = function (split) {
|
|
55
53
|
try {
|
|
56
54
|
if (split) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
localStorage.setItem(ttKey, (0, lang_1.toNumber)(localStorage.getItem(ttKey)) + 1);
|
|
61
|
-
}
|
|
55
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
56
|
+
// @ts-expect-error
|
|
57
|
+
localStorage.setItem(ttKey, (0, lang_1.toNumber)(localStorage.getItem(ttKey)) + 1);
|
|
62
58
|
if ((0, AbstractSplitsCacheSync_1.usesSegments)(split)) {
|
|
63
59
|
var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
64
60
|
// @ts-expect-error
|
|
@@ -95,9 +91,9 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
95
91
|
var splitKey = this.keys.buildSplitKey(name);
|
|
96
92
|
var splitFromLocalStorage = localStorage.getItem(splitKey);
|
|
97
93
|
var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
|
|
98
|
-
this._decrementCounts(previousSplit);
|
|
99
94
|
localStorage.setItem(splitKey, JSON.stringify(split));
|
|
100
95
|
this._incrementCounts(split);
|
|
96
|
+
this._decrementCounts(previousSplit);
|
|
101
97
|
return true;
|
|
102
98
|
}
|
|
103
99
|
catch (e) {
|
|
@@ -27,12 +27,10 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
27
27
|
SplitsCacheInMemory.prototype.addSplit = function (name, split) {
|
|
28
28
|
var previousSplit = this.getSplit(name);
|
|
29
29
|
if (previousSplit) { // We had this Split already
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
delete this.ttCache[previousTtName];
|
|
35
|
-
}
|
|
30
|
+
var previousTtName = previousSplit.trafficTypeName;
|
|
31
|
+
this.ttCache[previousTtName]--;
|
|
32
|
+
if (!this.ttCache[previousTtName])
|
|
33
|
+
delete this.ttCache[previousTtName];
|
|
36
34
|
if ((0, AbstractSplitsCacheSync_1.usesSegments)(previousSplit)) { // Substract from segments count for the previous version of this Split.
|
|
37
35
|
this.splitsWithSegmentsCount--;
|
|
38
36
|
}
|
|
@@ -42,11 +40,7 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
42
40
|
this.splitsCache[name] = split;
|
|
43
41
|
// Update TT cache
|
|
44
42
|
var ttName = split.trafficTypeName;
|
|
45
|
-
|
|
46
|
-
if (!this.ttCache[ttName])
|
|
47
|
-
this.ttCache[ttName] = 0;
|
|
48
|
-
this.ttCache[ttName]++;
|
|
49
|
-
}
|
|
43
|
+
this.ttCache[ttName] = (this.ttCache[ttName] || 0) + 1;
|
|
50
44
|
// Add to segments count for the new version of the Split
|
|
51
45
|
if ((0, AbstractSplitsCacheSync_1.usesSegments)(split))
|
|
52
46
|
this.splitsWithSegmentsCount++;
|
|
@@ -62,11 +56,9 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
62
56
|
// Delete the Split
|
|
63
57
|
delete this.splitsCache[name];
|
|
64
58
|
var ttName = split.trafficTypeName;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
delete this.ttCache[ttName];
|
|
69
|
-
}
|
|
59
|
+
this.ttCache[ttName]--; // Update tt cache
|
|
60
|
+
if (!this.ttCache[ttName])
|
|
61
|
+
delete this.ttCache[ttName];
|
|
70
62
|
// Update the segments count.
|
|
71
63
|
if ((0, AbstractSplitsCacheSync_1.usesSegments)(split))
|
|
72
64
|
this.splitsWithSegmentsCount--;
|
|
@@ -38,19 +38,15 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
38
38
|
}
|
|
39
39
|
SplitsCacheInRedis.prototype._decrementCounts = function (split) {
|
|
40
40
|
var _this = this;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
47
|
-
}
|
|
41
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
42
|
+
return this.redis.decr(ttKey).then(function (count) {
|
|
43
|
+
if (count === 0)
|
|
44
|
+
return _this.redis.del(ttKey);
|
|
45
|
+
});
|
|
48
46
|
};
|
|
49
47
|
SplitsCacheInRedis.prototype._incrementCounts = function (split) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return this.redis.incr(ttKey);
|
|
53
|
-
}
|
|
48
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
49
|
+
return this.redis.incr(ttKey);
|
|
54
50
|
};
|
|
55
51
|
/**
|
|
56
52
|
* Add a given split.
|
|
@@ -70,16 +66,17 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
70
66
|
catch (e) {
|
|
71
67
|
throw new Error('Error parsing feature flag definition: ' + e);
|
|
72
68
|
}
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
return _this.redis.set(splitKey, newStringifiedSplit).then(function () {
|
|
70
|
+
// avoid unnecessary increment/decrement operations
|
|
71
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
|
|
72
|
+
return;
|
|
73
|
+
// update traffic type counts
|
|
74
|
+
return _this._incrementCounts(split).then(function () {
|
|
75
|
+
if (parsedPreviousSplit)
|
|
76
|
+
return _this._decrementCounts(parsedPreviousSplit);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}).then(function () { return true; });
|
|
83
80
|
};
|
|
84
81
|
/**
|
|
85
82
|
* Add a list of splits.
|
|
@@ -25,19 +25,15 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
25
25
|
}
|
|
26
26
|
SplitsCachePluggable.prototype._decrementCounts = function (split) {
|
|
27
27
|
var _this = this;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
}
|
|
28
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
29
|
+
return this.wrapper.decr(ttKey).then(function (count) {
|
|
30
|
+
if (count === 0)
|
|
31
|
+
return _this.wrapper.del(ttKey);
|
|
32
|
+
});
|
|
35
33
|
};
|
|
36
34
|
SplitsCachePluggable.prototype._incrementCounts = function (split) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return this.wrapper.incr(ttKey);
|
|
40
|
-
}
|
|
35
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
36
|
+
return this.wrapper.incr(ttKey);
|
|
41
37
|
};
|
|
42
38
|
/**
|
|
43
39
|
* Add a given split.
|
|
@@ -57,12 +53,16 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
57
53
|
catch (e) {
|
|
58
54
|
throw new Error('Error parsing feature flag definition: ' + e);
|
|
59
55
|
}
|
|
60
|
-
return
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
return _this.wrapper.set(splitKey, stringifiedNewSplit).then(function () {
|
|
57
|
+
// avoid unnecessary increment/decrement operations
|
|
58
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
|
|
59
|
+
return;
|
|
60
|
+
// update traffic type counts
|
|
61
|
+
return _this._incrementCounts(split).then(function () {
|
|
62
|
+
if (parsedPreviousSplit)
|
|
63
|
+
return _this._decrementCounts(parsedPreviousSplit);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
66
|
}).then(function () { return true; });
|
|
67
67
|
};
|
|
68
68
|
/**
|
package/esm/services/splitApi.js
CHANGED
|
@@ -17,6 +17,7 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
17
17
|
var SplitSDKImpressionsMode = settings.sync.impressionsMode;
|
|
18
18
|
var splitHttpClient = splitHttpClientFactory(settings, platform.getFetch, platform.getOptions);
|
|
19
19
|
return {
|
|
20
|
+
// @TODO throw errors if health check requests fail, to log them in the Synchronizer
|
|
20
21
|
getSdkAPIHealthCheck: function () {
|
|
21
22
|
var url = urls.sdk + "/version";
|
|
22
23
|
return splitHttpClient(url).then(function () { return true; }).catch(function () { return false; });
|
|
@@ -34,10 +34,8 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
34
34
|
SplitsCacheInLocal.prototype._decrementCounts = function (split) {
|
|
35
35
|
try {
|
|
36
36
|
if (split) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this._decrementCount(ttKey);
|
|
40
|
-
}
|
|
37
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
38
|
+
this._decrementCount(ttKey);
|
|
41
39
|
if (usesSegments(split)) {
|
|
42
40
|
var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
43
41
|
this._decrementCount(segmentsCountKey);
|
|
@@ -51,11 +49,9 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
51
49
|
SplitsCacheInLocal.prototype._incrementCounts = function (split) {
|
|
52
50
|
try {
|
|
53
51
|
if (split) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
|
|
58
|
-
}
|
|
52
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
53
|
+
// @ts-expect-error
|
|
54
|
+
localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
|
|
59
55
|
if (usesSegments(split)) {
|
|
60
56
|
var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
61
57
|
// @ts-expect-error
|
|
@@ -92,9 +88,9 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
92
88
|
var splitKey = this.keys.buildSplitKey(name);
|
|
93
89
|
var splitFromLocalStorage = localStorage.getItem(splitKey);
|
|
94
90
|
var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
|
|
95
|
-
this._decrementCounts(previousSplit);
|
|
96
91
|
localStorage.setItem(splitKey, JSON.stringify(split));
|
|
97
92
|
this._incrementCounts(split);
|
|
93
|
+
this._decrementCounts(previousSplit);
|
|
98
94
|
return true;
|
|
99
95
|
}
|
|
100
96
|
catch (e) {
|
|
@@ -24,12 +24,10 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
24
24
|
SplitsCacheInMemory.prototype.addSplit = function (name, split) {
|
|
25
25
|
var previousSplit = this.getSplit(name);
|
|
26
26
|
if (previousSplit) { // We had this Split already
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
delete this.ttCache[previousTtName];
|
|
32
|
-
}
|
|
27
|
+
var previousTtName = previousSplit.trafficTypeName;
|
|
28
|
+
this.ttCache[previousTtName]--;
|
|
29
|
+
if (!this.ttCache[previousTtName])
|
|
30
|
+
delete this.ttCache[previousTtName];
|
|
33
31
|
if (usesSegments(previousSplit)) { // Substract from segments count for the previous version of this Split.
|
|
34
32
|
this.splitsWithSegmentsCount--;
|
|
35
33
|
}
|
|
@@ -39,11 +37,7 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
39
37
|
this.splitsCache[name] = split;
|
|
40
38
|
// Update TT cache
|
|
41
39
|
var ttName = split.trafficTypeName;
|
|
42
|
-
|
|
43
|
-
if (!this.ttCache[ttName])
|
|
44
|
-
this.ttCache[ttName] = 0;
|
|
45
|
-
this.ttCache[ttName]++;
|
|
46
|
-
}
|
|
40
|
+
this.ttCache[ttName] = (this.ttCache[ttName] || 0) + 1;
|
|
47
41
|
// Add to segments count for the new version of the Split
|
|
48
42
|
if (usesSegments(split))
|
|
49
43
|
this.splitsWithSegmentsCount++;
|
|
@@ -59,11 +53,9 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
59
53
|
// Delete the Split
|
|
60
54
|
delete this.splitsCache[name];
|
|
61
55
|
var ttName = split.trafficTypeName;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
delete this.ttCache[ttName];
|
|
66
|
-
}
|
|
56
|
+
this.ttCache[ttName]--; // Update tt cache
|
|
57
|
+
if (!this.ttCache[ttName])
|
|
58
|
+
delete this.ttCache[ttName];
|
|
67
59
|
// Update the segments count.
|
|
68
60
|
if (usesSegments(split))
|
|
69
61
|
this.splitsWithSegmentsCount--;
|
|
@@ -35,19 +35,15 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
35
35
|
}
|
|
36
36
|
SplitsCacheInRedis.prototype._decrementCounts = function (split) {
|
|
37
37
|
var _this = this;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
}
|
|
38
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
39
|
+
return this.redis.decr(ttKey).then(function (count) {
|
|
40
|
+
if (count === 0)
|
|
41
|
+
return _this.redis.del(ttKey);
|
|
42
|
+
});
|
|
45
43
|
};
|
|
46
44
|
SplitsCacheInRedis.prototype._incrementCounts = function (split) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return this.redis.incr(ttKey);
|
|
50
|
-
}
|
|
45
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
46
|
+
return this.redis.incr(ttKey);
|
|
51
47
|
};
|
|
52
48
|
/**
|
|
53
49
|
* Add a given split.
|
|
@@ -67,16 +63,17 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
67
63
|
catch (e) {
|
|
68
64
|
throw new Error('Error parsing feature flag definition: ' + e);
|
|
69
65
|
}
|
|
70
|
-
return
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
66
|
+
return _this.redis.set(splitKey, newStringifiedSplit).then(function () {
|
|
67
|
+
// avoid unnecessary increment/decrement operations
|
|
68
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
|
|
69
|
+
return;
|
|
70
|
+
// update traffic type counts
|
|
71
|
+
return _this._incrementCounts(split).then(function () {
|
|
72
|
+
if (parsedPreviousSplit)
|
|
73
|
+
return _this._decrementCounts(parsedPreviousSplit);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}).then(function () { return true; });
|
|
80
77
|
};
|
|
81
78
|
/**
|
|
82
79
|
* Add a list of splits.
|
|
@@ -22,19 +22,15 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
22
22
|
}
|
|
23
23
|
SplitsCachePluggable.prototype._decrementCounts = function (split) {
|
|
24
24
|
var _this = this;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
}
|
|
25
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
26
|
+
return this.wrapper.decr(ttKey).then(function (count) {
|
|
27
|
+
if (count === 0)
|
|
28
|
+
return _this.wrapper.del(ttKey);
|
|
29
|
+
});
|
|
32
30
|
};
|
|
33
31
|
SplitsCachePluggable.prototype._incrementCounts = function (split) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return this.wrapper.incr(ttKey);
|
|
37
|
-
}
|
|
32
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
33
|
+
return this.wrapper.incr(ttKey);
|
|
38
34
|
};
|
|
39
35
|
/**
|
|
40
36
|
* Add a given split.
|
|
@@ -54,12 +50,16 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
54
50
|
catch (e) {
|
|
55
51
|
throw new Error('Error parsing feature flag definition: ' + e);
|
|
56
52
|
}
|
|
57
|
-
return
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
return _this.wrapper.set(splitKey, stringifiedNewSplit).then(function () {
|
|
54
|
+
// avoid unnecessary increment/decrement operations
|
|
55
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
|
|
56
|
+
return;
|
|
57
|
+
// update traffic type counts
|
|
58
|
+
return _this._incrementCounts(split).then(function () {
|
|
59
|
+
if (parsedPreviousSplit)
|
|
60
|
+
return _this._decrementCounts(parsedPreviousSplit);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
63
|
}).then(function () { return true; });
|
|
64
64
|
};
|
|
65
65
|
/**
|
package/package.json
CHANGED
package/src/services/splitApi.ts
CHANGED
|
@@ -30,6 +30,7 @@ export function splitApiFactory(
|
|
|
30
30
|
const splitHttpClient = splitHttpClientFactory(settings, platform.getFetch, platform.getOptions);
|
|
31
31
|
|
|
32
32
|
return {
|
|
33
|
+
// @TODO throw errors if health check requests fail, to log them in the Synchronizer
|
|
33
34
|
getSdkAPIHealthCheck() {
|
|
34
35
|
const url = `${urls.sdk}/version`;
|
|
35
36
|
return splitHttpClient(url).then(() => true).catch(() => false);
|
|
@@ -41,10 +41,8 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
41
41
|
private _decrementCounts(split: ISplit | null) {
|
|
42
42
|
try {
|
|
43
43
|
if (split) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this._decrementCount(ttKey);
|
|
47
|
-
}
|
|
44
|
+
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
45
|
+
this._decrementCount(ttKey);
|
|
48
46
|
|
|
49
47
|
if (usesSegments(split)) {
|
|
50
48
|
const segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
@@ -59,11 +57,9 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
59
57
|
private _incrementCounts(split: ISplit) {
|
|
60
58
|
try {
|
|
61
59
|
if (split) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
|
|
66
|
-
}
|
|
60
|
+
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
61
|
+
// @ts-expect-error
|
|
62
|
+
localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
|
|
67
63
|
|
|
68
64
|
if (usesSegments(split)) {
|
|
69
65
|
const segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
@@ -104,11 +100,11 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
104
100
|
const splitKey = this.keys.buildSplitKey(name);
|
|
105
101
|
const splitFromLocalStorage = localStorage.getItem(splitKey);
|
|
106
102
|
const previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
|
|
107
|
-
this._decrementCounts(previousSplit);
|
|
108
103
|
|
|
109
104
|
localStorage.setItem(splitKey, JSON.stringify(split));
|
|
110
105
|
|
|
111
106
|
this._incrementCounts(split);
|
|
107
|
+
this._decrementCounts(previousSplit);
|
|
112
108
|
|
|
113
109
|
return true;
|
|
114
110
|
} catch (e) {
|
|
@@ -24,11 +24,9 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
24
24
|
const previousSplit = this.getSplit(name);
|
|
25
25
|
if (previousSplit) { // We had this Split already
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (!this.ttCache[previousTtName]) delete this.ttCache[previousTtName];
|
|
31
|
-
}
|
|
27
|
+
const previousTtName = previousSplit.trafficTypeName;
|
|
28
|
+
this.ttCache[previousTtName]--;
|
|
29
|
+
if (!this.ttCache[previousTtName]) delete this.ttCache[previousTtName];
|
|
32
30
|
|
|
33
31
|
if (usesSegments(previousSplit)) { // Substract from segments count for the previous version of this Split.
|
|
34
32
|
this.splitsWithSegmentsCount--;
|
|
@@ -40,10 +38,7 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
40
38
|
this.splitsCache[name] = split;
|
|
41
39
|
// Update TT cache
|
|
42
40
|
const ttName = split.trafficTypeName;
|
|
43
|
-
|
|
44
|
-
if (!this.ttCache[ttName]) this.ttCache[ttName] = 0;
|
|
45
|
-
this.ttCache[ttName]++;
|
|
46
|
-
}
|
|
41
|
+
this.ttCache[ttName] = (this.ttCache[ttName] || 0) + 1;
|
|
47
42
|
|
|
48
43
|
// Add to segments count for the new version of the Split
|
|
49
44
|
if (usesSegments(split)) this.splitsWithSegmentsCount++;
|
|
@@ -61,11 +56,8 @@ export class SplitsCacheInMemory extends AbstractSplitsCacheSync {
|
|
|
61
56
|
delete this.splitsCache[name];
|
|
62
57
|
|
|
63
58
|
const ttName = split.trafficTypeName;
|
|
64
|
-
|
|
65
|
-
if (ttName)
|
|
66
|
-
this.ttCache[ttName]--; // Update tt cache
|
|
67
|
-
if (!this.ttCache[ttName]) delete this.ttCache[ttName];
|
|
68
|
-
}
|
|
59
|
+
this.ttCache[ttName]--; // Update tt cache
|
|
60
|
+
if (!this.ttCache[ttName]) delete this.ttCache[ttName];
|
|
69
61
|
|
|
70
62
|
// Update the segments count.
|
|
71
63
|
if (usesSegments(split)) this.splitsWithSegmentsCount--;
|
|
@@ -45,19 +45,15 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
private _decrementCounts(split: ISplit) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return this.redis.
|
|
51
|
-
|
|
52
|
-
});
|
|
53
|
-
}
|
|
48
|
+
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
49
|
+
return this.redis.decr(ttKey).then(count => {
|
|
50
|
+
if (count === 0) return this.redis.del(ttKey);
|
|
51
|
+
});
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
private _incrementCounts(split: ISplit) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return this.redis.incr(ttKey);
|
|
60
|
-
}
|
|
55
|
+
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
56
|
+
return this.redis.incr(ttKey);
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
/**
|
|
@@ -70,7 +66,7 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
70
66
|
return this.redis.get(splitKey).then(splitFromStorage => {
|
|
71
67
|
|
|
72
68
|
// handling parsing errors
|
|
73
|
-
let parsedPreviousSplit, newStringifiedSplit;
|
|
69
|
+
let parsedPreviousSplit: ISplit, newStringifiedSplit;
|
|
74
70
|
try {
|
|
75
71
|
parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
|
|
76
72
|
newStringifiedSplit = JSON.stringify(split);
|
|
@@ -78,13 +74,16 @@ export class SplitsCacheInRedis extends AbstractSplitsCacheAsync {
|
|
|
78
74
|
throw new Error('Error parsing feature flag definition: ' + e);
|
|
79
75
|
}
|
|
80
76
|
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
77
|
+
return this.redis.set(splitKey, newStringifiedSplit).then(() => {
|
|
78
|
+
// avoid unnecessary increment/decrement operations
|
|
79
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName) return;
|
|
80
|
+
|
|
81
|
+
// update traffic type counts
|
|
82
|
+
return this._incrementCounts(split).then(() => {
|
|
83
|
+
if (parsedPreviousSplit) return this._decrementCounts(parsedPreviousSplit);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}).then(() => true);
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
/**
|
|
@@ -29,19 +29,15 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
private _decrementCounts(split: ISplit) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return this.wrapper.
|
|
35
|
-
|
|
36
|
-
});
|
|
37
|
-
}
|
|
32
|
+
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
33
|
+
return this.wrapper.decr(ttKey).then(count => {
|
|
34
|
+
if (count === 0) return this.wrapper.del(ttKey);
|
|
35
|
+
});
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
private _incrementCounts(split: ISplit) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return this.wrapper.incr(ttKey);
|
|
44
|
-
}
|
|
39
|
+
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
40
|
+
return this.wrapper.incr(ttKey);
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
/**
|
|
@@ -54,7 +50,7 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
|
|
|
54
50
|
return this.wrapper.get(splitKey).then(splitFromStorage => {
|
|
55
51
|
|
|
56
52
|
// handling parsing error
|
|
57
|
-
let parsedPreviousSplit, stringifiedNewSplit;
|
|
53
|
+
let parsedPreviousSplit: ISplit, stringifiedNewSplit;
|
|
58
54
|
try {
|
|
59
55
|
parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
|
|
60
56
|
stringifiedNewSplit = JSON.stringify(split);
|
|
@@ -62,12 +58,15 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
|
|
|
62
58
|
throw new Error('Error parsing feature flag definition: ' + e);
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
return
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
return this.wrapper.set(splitKey, stringifiedNewSplit).then(() => {
|
|
62
|
+
// avoid unnecessary increment/decrement operations
|
|
63
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName) return;
|
|
64
|
+
|
|
65
|
+
// update traffic type counts
|
|
66
|
+
return this._incrementCounts(split).then(() => {
|
|
67
|
+
if (parsedPreviousSplit) return this._decrementCounts(parsedPreviousSplit);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
71
70
|
}).then(() => true);
|
|
72
71
|
}
|
|
73
72
|
|