@splitsoftware/splitio-commons 2.1.0 → 2.1.1-rc.0
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/README.md +1 -0
- package/cjs/evaluator/combiners/and.js +2 -6
- package/cjs/evaluator/combiners/ifelseif.js +6 -6
- package/cjs/evaluator/condition/index.js +6 -5
- package/cjs/evaluator/index.js +7 -7
- package/cjs/evaluator/matchers/index.js +3 -1
- package/cjs/evaluator/matchers/matcherTypes.js +1 -0
- package/cjs/evaluator/matchers/rbsegment.js +43 -0
- package/cjs/evaluator/matchersTransform/index.js +4 -0
- package/cjs/evaluator/parser/index.js +2 -2
- package/cjs/evaluator/value/sanitize.js +1 -0
- package/cjs/logger/constants.js +5 -6
- package/cjs/logger/messages/debug.js +3 -4
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/services/splitApi.js +2 -2
- package/cjs/storages/AbstractSplitsCacheAsync.js +12 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +10 -9
- package/cjs/storages/KeyBuilder.js +8 -15
- package/cjs/storages/KeyBuilderCS.js +12 -3
- package/cjs/storages/KeyBuilderSS.js +3 -0
- package/cjs/storages/dataLoader.js +1 -2
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +117 -0
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +14 -16
- package/cjs/storages/inLocalStorage/index.js +4 -0
- package/cjs/storages/inMemory/InMemoryStorage.js +3 -0
- package/cjs/storages/inMemory/InMemoryStorageCS.js +4 -0
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +61 -0
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +24 -31
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +64 -0
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +4 -21
- package/cjs/storages/inRedis/index.js +2 -0
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +64 -0
- package/cjs/storages/pluggable/SplitsCachePluggable.js +2 -19
- package/cjs/storages/pluggable/index.js +2 -0
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +12 -13
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +2 -2
- package/cjs/sync/polling/pollingManagerCS.js +7 -7
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +53 -51
- package/cjs/sync/streaming/SSEHandler/index.js +1 -0
- package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +106 -77
- package/cjs/sync/streaming/constants.js +2 -1
- package/cjs/sync/streaming/pushManager.js +3 -16
- package/cjs/sync/syncManagerOnline.js +2 -2
- package/cjs/utils/constants/index.js +3 -2
- package/esm/evaluator/combiners/and.js +2 -6
- package/esm/evaluator/combiners/ifelseif.js +7 -7
- package/esm/evaluator/condition/index.js +6 -5
- package/esm/evaluator/index.js +7 -7
- package/esm/evaluator/matchers/index.js +3 -1
- package/esm/evaluator/matchers/matcherTypes.js +1 -0
- package/esm/evaluator/matchers/rbsegment.js +39 -0
- package/esm/evaluator/matchersTransform/index.js +4 -0
- package/esm/evaluator/parser/index.js +2 -2
- package/esm/evaluator/value/sanitize.js +1 -0
- package/esm/logger/constants.js +2 -3
- package/esm/logger/messages/debug.js +3 -4
- package/esm/logger/messages/warn.js +1 -1
- package/esm/services/splitApi.js +2 -2
- package/esm/storages/AbstractSplitsCacheAsync.js +12 -1
- package/esm/storages/AbstractSplitsCacheSync.js +10 -9
- package/esm/storages/KeyBuilder.js +8 -15
- package/esm/storages/KeyBuilderCS.js +12 -3
- package/esm/storages/KeyBuilderSS.js +3 -0
- package/esm/storages/dataLoader.js +1 -2
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +114 -0
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +14 -16
- package/esm/storages/inLocalStorage/index.js +4 -0
- package/esm/storages/inMemory/InMemoryStorage.js +3 -0
- package/esm/storages/inMemory/InMemoryStorageCS.js +4 -0
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +58 -0
- package/esm/storages/inMemory/SplitsCacheInMemory.js +24 -31
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +61 -0
- package/esm/storages/inRedis/SplitsCacheInRedis.js +4 -21
- package/esm/storages/inRedis/index.js +2 -0
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +61 -0
- package/esm/storages/pluggable/SplitsCachePluggable.js +2 -19
- package/esm/storages/pluggable/index.js +2 -0
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +12 -13
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +2 -2
- package/esm/sync/polling/pollingManagerCS.js +7 -7
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/esm/sync/polling/updaters/splitChangesUpdater.js +53 -51
- package/esm/sync/streaming/SSEHandler/index.js +2 -1
- package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +102 -73
- package/esm/sync/streaming/constants.js +1 -0
- package/esm/sync/streaming/pushManager.js +6 -19
- package/esm/sync/syncManagerOnline.js +2 -2
- package/esm/utils/constants/index.js +2 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +32 -8
- package/src/evaluator/Engine.ts +1 -1
- package/src/evaluator/combiners/and.ts +5 -4
- package/src/evaluator/combiners/ifelseif.ts +7 -9
- package/src/evaluator/condition/engineUtils.ts +1 -1
- package/src/evaluator/condition/index.ts +12 -12
- package/src/evaluator/index.ts +7 -7
- package/src/evaluator/matchers/index.ts +3 -1
- package/src/evaluator/matchers/matcherTypes.ts +1 -0
- package/src/evaluator/matchers/rbsegment.ts +61 -0
- package/src/evaluator/matchersTransform/index.ts +3 -0
- package/src/evaluator/parser/index.ts +3 -3
- package/src/evaluator/types.ts +2 -2
- package/src/evaluator/value/index.ts +2 -2
- package/src/evaluator/value/sanitize.ts +5 -4
- package/src/logger/constants.ts +2 -3
- package/src/logger/messages/debug.ts +3 -4
- package/src/logger/messages/warn.ts +1 -1
- package/src/sdkManager/index.ts +1 -1
- package/src/services/splitApi.ts +2 -2
- package/src/services/types.ts +1 -1
- package/src/storages/AbstractSplitsCacheAsync.ts +15 -5
- package/src/storages/AbstractSplitsCacheSync.ts +14 -15
- package/src/storages/KeyBuilder.ts +9 -17
- package/src/storages/KeyBuilderCS.ts +15 -4
- package/src/storages/KeyBuilderSS.ts +4 -0
- package/src/storages/dataLoader.ts +1 -2
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +136 -0
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +15 -16
- package/src/storages/inLocalStorage/index.ts +4 -0
- package/src/storages/inMemory/InMemoryStorage.ts +3 -0
- package/src/storages/inMemory/InMemoryStorageCS.ts +4 -0
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +68 -0
- package/src/storages/inMemory/SplitsCacheInMemory.ts +22 -27
- package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +79 -0
- package/src/storages/inRedis/SplitsCacheInRedis.ts +4 -21
- package/src/storages/inRedis/index.ts +2 -0
- package/src/storages/pluggable/RBSegmentsCachePluggable.ts +76 -0
- package/src/storages/pluggable/SplitsCachePluggable.ts +2 -19
- package/src/storages/pluggable/index.ts +2 -0
- package/src/storages/types.ts +43 -17
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +14 -15
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +2 -1
- package/src/sync/polling/fetchers/types.ts +1 -0
- package/src/sync/polling/pollingManagerCS.ts +7 -7
- package/src/sync/polling/syncTasks/splitsSyncTask.ts +1 -2
- package/src/sync/polling/types.ts +2 -2
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -2
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
- package/src/sync/polling/updaters/splitChangesUpdater.ts +64 -62
- package/src/sync/streaming/SSEHandler/index.ts +2 -1
- package/src/sync/streaming/SSEHandler/types.ts +2 -2
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +98 -68
- package/src/sync/streaming/constants.ts +1 -0
- package/src/sync/streaming/parseUtils.ts +2 -2
- package/src/sync/streaming/pushManager.ts +6 -18
- package/src/sync/streaming/types.ts +3 -2
- package/src/sync/syncManagerOnline.ts +2 -2
- package/src/utils/constants/index.ts +2 -1
- package/src/utils/lang/index.ts +1 -1
|
@@ -22,7 +22,8 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
22
22
|
this.changeNumber = -1;
|
|
23
23
|
this.segmentsCount = 0;
|
|
24
24
|
};
|
|
25
|
-
SplitsCacheInMemory.prototype.addSplit = function (
|
|
25
|
+
SplitsCacheInMemory.prototype.addSplit = function (split) {
|
|
26
|
+
var name = split.name;
|
|
26
27
|
var previousSplit = this.getSplit(name);
|
|
27
28
|
if (previousSplit) { // We had this Split already
|
|
28
29
|
var previousTtName = previousSplit.trafficTypeName;
|
|
@@ -34,40 +35,32 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
34
35
|
if (usesSegments(previousSplit))
|
|
35
36
|
this.segmentsCount--;
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
38
|
+
// Store the Split.
|
|
39
|
+
this.splitsCache[name] = split;
|
|
40
|
+
// Update TT cache
|
|
41
|
+
var ttName = split.trafficTypeName;
|
|
42
|
+
this.ttCache[ttName] = (this.ttCache[ttName] || 0) + 1;
|
|
43
|
+
this.addToFlagSets(split);
|
|
44
|
+
// Add to segments count for the new version of the Split
|
|
45
|
+
if (usesSegments(split))
|
|
46
|
+
this.segmentsCount++;
|
|
47
|
+
return true;
|
|
52
48
|
};
|
|
53
49
|
SplitsCacheInMemory.prototype.removeSplit = function (name) {
|
|
54
50
|
var split = this.getSplit(name);
|
|
55
|
-
if (split)
|
|
56
|
-
// Delete the Split
|
|
57
|
-
delete this.splitsCache[name];
|
|
58
|
-
var ttName = split.trafficTypeName;
|
|
59
|
-
this.ttCache[ttName]--; // Update tt cache
|
|
60
|
-
if (!this.ttCache[ttName])
|
|
61
|
-
delete this.ttCache[ttName];
|
|
62
|
-
this.removeFromFlagSets(split.name, split.sets);
|
|
63
|
-
// Update the segments count.
|
|
64
|
-
if (usesSegments(split))
|
|
65
|
-
this.segmentsCount--;
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
51
|
+
if (!split)
|
|
69
52
|
return false;
|
|
70
|
-
|
|
53
|
+
// Delete the Split
|
|
54
|
+
delete this.splitsCache[name];
|
|
55
|
+
var ttName = split.trafficTypeName;
|
|
56
|
+
this.ttCache[ttName]--; // Update tt cache
|
|
57
|
+
if (!this.ttCache[ttName])
|
|
58
|
+
delete this.ttCache[ttName];
|
|
59
|
+
this.removeFromFlagSets(split.name, split.sets);
|
|
60
|
+
// Update the segments count.
|
|
61
|
+
if (usesSegments(split))
|
|
62
|
+
this.segmentsCount--;
|
|
63
|
+
return true;
|
|
71
64
|
};
|
|
72
65
|
SplitsCacheInMemory.prototype.getSplit = function (name) {
|
|
73
66
|
return this.splitsCache[name] || null;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { isNaNNumber } from '../../utils/lang';
|
|
2
|
+
import { LOG_PREFIX } from './constants';
|
|
3
|
+
import { setToArray } from '../../utils/lang/sets';
|
|
4
|
+
var RBSegmentsCacheInRedis = /** @class */ (function () {
|
|
5
|
+
function RBSegmentsCacheInRedis(log, keys, redis) {
|
|
6
|
+
this.log = log;
|
|
7
|
+
this.keys = keys;
|
|
8
|
+
this.redis = redis;
|
|
9
|
+
}
|
|
10
|
+
RBSegmentsCacheInRedis.prototype.get = function (name) {
|
|
11
|
+
return this.redis.get(this.keys.buildRBSegmentKey(name))
|
|
12
|
+
.then(function (maybeRBSegment) { return maybeRBSegment && JSON.parse(maybeRBSegment); });
|
|
13
|
+
};
|
|
14
|
+
RBSegmentsCacheInRedis.prototype.getNames = function () {
|
|
15
|
+
var _this = this;
|
|
16
|
+
return this.redis.keys(this.keys.searchPatternForRBSegmentKeys()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
|
|
17
|
+
};
|
|
18
|
+
RBSegmentsCacheInRedis.prototype.contains = function (names) {
|
|
19
|
+
var namesArray = setToArray(names);
|
|
20
|
+
return this.getNames().then(function (namesInStorage) {
|
|
21
|
+
return namesArray.every(function (name) { return namesInStorage.includes(name); });
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
RBSegmentsCacheInRedis.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
25
|
+
var _this = this;
|
|
26
|
+
return Promise.all([
|
|
27
|
+
this.setChangeNumber(changeNumber),
|
|
28
|
+
Promise.all(toAdd.map(function (toAdd) {
|
|
29
|
+
var key = _this.keys.buildRBSegmentKey(toAdd.name);
|
|
30
|
+
var stringifiedNewRBSegment = JSON.stringify(toAdd);
|
|
31
|
+
return _this.redis.set(key, stringifiedNewRBSegment).then(function () { return true; });
|
|
32
|
+
})),
|
|
33
|
+
Promise.all(toRemove.map(function (toRemove) {
|
|
34
|
+
var key = _this.keys.buildRBSegmentKey(toRemove.name);
|
|
35
|
+
return _this.redis.del(key).then(function (status) { return status === 1; });
|
|
36
|
+
}))
|
|
37
|
+
]).then(function (_a) {
|
|
38
|
+
var added = _a[1], removed = _a[2];
|
|
39
|
+
return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
RBSegmentsCacheInRedis.prototype.setChangeNumber = function (changeNumber) {
|
|
43
|
+
return this.redis.set(this.keys.buildRBSegmentsTillKey(), changeNumber + '').then(function (status) { return status === 'OK'; });
|
|
44
|
+
};
|
|
45
|
+
RBSegmentsCacheInRedis.prototype.getChangeNumber = function () {
|
|
46
|
+
var _this = this;
|
|
47
|
+
return this.redis.get(this.keys.buildRBSegmentsTillKey()).then(function (value) {
|
|
48
|
+
var i = parseInt(value, 10);
|
|
49
|
+
return isNaNNumber(i) ? -1 : i;
|
|
50
|
+
}).catch(function (e) {
|
|
51
|
+
_this.log.error(LOG_PREFIX + 'Could not retrieve changeNumber from storage. Error: ' + e);
|
|
52
|
+
return -1;
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
// @TODO implement if required by DataLoader or producer mode
|
|
56
|
+
RBSegmentsCacheInRedis.prototype.clear = function () {
|
|
57
|
+
return Promise.resolve();
|
|
58
|
+
};
|
|
59
|
+
return RBSegmentsCacheInRedis;
|
|
60
|
+
}());
|
|
61
|
+
export { RBSegmentsCacheInRedis };
|
|
@@ -64,8 +64,9 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
64
64
|
* The returned promise is resolved when the operation success
|
|
65
65
|
* or rejected if it fails (e.g., redis operation fails)
|
|
66
66
|
*/
|
|
67
|
-
SplitsCacheInRedis.prototype.addSplit = function (
|
|
67
|
+
SplitsCacheInRedis.prototype.addSplit = function (split) {
|
|
68
68
|
var _this = this;
|
|
69
|
+
var name = split.name;
|
|
69
70
|
var splitKey = this.keys.buildSplitKey(name);
|
|
70
71
|
return this.redis.get(splitKey).then(function (splitFromStorage) {
|
|
71
72
|
// handling parsing error
|
|
@@ -89,18 +90,9 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
89
90
|
}).then(function () { return _this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets); });
|
|
90
91
|
}).then(function () { return true; });
|
|
91
92
|
};
|
|
92
|
-
/**
|
|
93
|
-
* Add a list of splits.
|
|
94
|
-
* The returned promise is resolved when the operation success
|
|
95
|
-
* or rejected if it fails (e.g., redis operation fails)
|
|
96
|
-
*/
|
|
97
|
-
SplitsCacheInRedis.prototype.addSplits = function (entries) {
|
|
98
|
-
var _this = this;
|
|
99
|
-
return Promise.all(entries.map(function (keyValuePair) { return _this.addSplit(keyValuePair[0], keyValuePair[1]); }));
|
|
100
|
-
};
|
|
101
93
|
/**
|
|
102
94
|
* Remove a given split.
|
|
103
|
-
* The returned promise is resolved when the operation success, with
|
|
95
|
+
* The returned promise is resolved when the operation success, with true or false indicating if the split existed (and was removed) or not.
|
|
104
96
|
* or rejected if it fails (e.g., redis operation fails).
|
|
105
97
|
*/
|
|
106
98
|
SplitsCacheInRedis.prototype.removeSplit = function (name) {
|
|
@@ -110,18 +102,9 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
110
102
|
return _this._decrementCounts(split).then(function () { return _this._updateFlagSets(name, split.sets); });
|
|
111
103
|
}
|
|
112
104
|
}).then(function () {
|
|
113
|
-
return _this.redis.del(_this.keys.buildSplitKey(name));
|
|
105
|
+
return _this.redis.del(_this.keys.buildSplitKey(name)).then(function (status) { return status === 1; });
|
|
114
106
|
});
|
|
115
107
|
};
|
|
116
|
-
/**
|
|
117
|
-
* Remove a list of splits.
|
|
118
|
-
* The returned promise is resolved when the operation success,
|
|
119
|
-
* or rejected if it fails (e.g., redis operation fails).
|
|
120
|
-
*/
|
|
121
|
-
SplitsCacheInRedis.prototype.removeSplits = function (names) {
|
|
122
|
-
var _this = this;
|
|
123
|
-
return Promise.all(names.map(function (name) { return _this.removeSplit(name); }));
|
|
124
|
-
};
|
|
125
108
|
/**
|
|
126
109
|
* Get split definition or null if it's not defined.
|
|
127
110
|
* Returned promise is rejected if redis operation fails.
|
|
@@ -9,6 +9,7 @@ import { TelemetryCacheInRedis } from './TelemetryCacheInRedis';
|
|
|
9
9
|
import { UniqueKeysCacheInRedis } from './UniqueKeysCacheInRedis';
|
|
10
10
|
import { ImpressionCountsCacheInRedis } from './ImpressionCountsCacheInRedis';
|
|
11
11
|
import { metadataBuilder } from '../utils';
|
|
12
|
+
import { RBSegmentsCacheInRedis } from './RBSegmentsCacheInRedis';
|
|
12
13
|
/**
|
|
13
14
|
* InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node.js
|
|
14
15
|
* @see {@link https://www.npmjs.com/package/ioredis}
|
|
@@ -37,6 +38,7 @@ export function InRedisStorage(options) {
|
|
|
37
38
|
});
|
|
38
39
|
return {
|
|
39
40
|
splits: new SplitsCacheInRedis(log, keys, redisClient, settings.sync.__splitFiltersValidation),
|
|
41
|
+
rbSegments: new RBSegmentsCacheInRedis(log, keys, redisClient),
|
|
40
42
|
segments: new SegmentsCacheInRedis(log, keys, redisClient),
|
|
41
43
|
impressions: new ImpressionsCacheInRedis(log, keys.buildImpressionsKey(), redisClient, metadata),
|
|
42
44
|
impressionCounts: impressionCountsCache,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { isNaNNumber } from '../../utils/lang';
|
|
2
|
+
import { LOG_PREFIX } from './constants';
|
|
3
|
+
import { setToArray } from '../../utils/lang/sets';
|
|
4
|
+
var RBSegmentsCachePluggable = /** @class */ (function () {
|
|
5
|
+
function RBSegmentsCachePluggable(log, keys, wrapper) {
|
|
6
|
+
this.log = log;
|
|
7
|
+
this.keys = keys;
|
|
8
|
+
this.wrapper = wrapper;
|
|
9
|
+
}
|
|
10
|
+
RBSegmentsCachePluggable.prototype.get = function (name) {
|
|
11
|
+
return this.wrapper.get(this.keys.buildRBSegmentKey(name))
|
|
12
|
+
.then(function (maybeRBSegment) { return maybeRBSegment && JSON.parse(maybeRBSegment); });
|
|
13
|
+
};
|
|
14
|
+
RBSegmentsCachePluggable.prototype.getNames = function () {
|
|
15
|
+
var _this = this;
|
|
16
|
+
return this.wrapper.getKeysByPrefix(this.keys.buildRBSegmentKeyPrefix()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
|
|
17
|
+
};
|
|
18
|
+
RBSegmentsCachePluggable.prototype.contains = function (names) {
|
|
19
|
+
var namesArray = setToArray(names);
|
|
20
|
+
return this.getNames().then(function (namesInStorage) {
|
|
21
|
+
return namesArray.every(function (name) { return namesInStorage.includes(name); });
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
RBSegmentsCachePluggable.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
25
|
+
var _this = this;
|
|
26
|
+
return Promise.all([
|
|
27
|
+
this.setChangeNumber(changeNumber),
|
|
28
|
+
Promise.all(toAdd.map(function (toAdd) {
|
|
29
|
+
var key = _this.keys.buildRBSegmentKey(toAdd.name);
|
|
30
|
+
var stringifiedNewRBSegment = JSON.stringify(toAdd);
|
|
31
|
+
return _this.wrapper.set(key, stringifiedNewRBSegment).then(function () { return true; });
|
|
32
|
+
})),
|
|
33
|
+
Promise.all(toRemove.map(function (toRemove) {
|
|
34
|
+
var key = _this.keys.buildRBSegmentKey(toRemove.name);
|
|
35
|
+
return _this.wrapper.del(key);
|
|
36
|
+
}))
|
|
37
|
+
]).then(function (_a) {
|
|
38
|
+
var added = _a[1], removed = _a[2];
|
|
39
|
+
return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
RBSegmentsCachePluggable.prototype.setChangeNumber = function (changeNumber) {
|
|
43
|
+
return this.wrapper.set(this.keys.buildRBSegmentsTillKey(), changeNumber + '');
|
|
44
|
+
};
|
|
45
|
+
RBSegmentsCachePluggable.prototype.getChangeNumber = function () {
|
|
46
|
+
var _this = this;
|
|
47
|
+
return this.wrapper.get(this.keys.buildRBSegmentsTillKey()).then(function (value) {
|
|
48
|
+
var i = parseInt(value, 10);
|
|
49
|
+
return isNaNNumber(i) ? -1 : i;
|
|
50
|
+
}).catch(function (e) {
|
|
51
|
+
_this.log.error(LOG_PREFIX + 'Could not retrieve changeNumber from storage. Error: ' + e);
|
|
52
|
+
return -1;
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
// @TODO implement if required by DataLoader or producer mode
|
|
56
|
+
RBSegmentsCachePluggable.prototype.clear = function () {
|
|
57
|
+
return Promise.resolve();
|
|
58
|
+
};
|
|
59
|
+
return RBSegmentsCachePluggable;
|
|
60
|
+
}());
|
|
61
|
+
export { RBSegmentsCachePluggable };
|
|
@@ -51,8 +51,9 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
51
51
|
* The returned promise is resolved when the operation success
|
|
52
52
|
* or rejected if it fails (e.g., wrapper operation fails)
|
|
53
53
|
*/
|
|
54
|
-
SplitsCachePluggable.prototype.addSplit = function (
|
|
54
|
+
SplitsCachePluggable.prototype.addSplit = function (split) {
|
|
55
55
|
var _this = this;
|
|
56
|
+
var name = split.name;
|
|
56
57
|
var splitKey = this.keys.buildSplitKey(name);
|
|
57
58
|
return this.wrapper.get(splitKey).then(function (splitFromStorage) {
|
|
58
59
|
// handling parsing error
|
|
@@ -76,15 +77,6 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
76
77
|
}).then(function () { return _this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets); });
|
|
77
78
|
}).then(function () { return true; });
|
|
78
79
|
};
|
|
79
|
-
/**
|
|
80
|
-
* Add a list of splits.
|
|
81
|
-
* The returned promise is resolved when the operation success
|
|
82
|
-
* or rejected if it fails (e.g., wrapper operation fails)
|
|
83
|
-
*/
|
|
84
|
-
SplitsCachePluggable.prototype.addSplits = function (entries) {
|
|
85
|
-
var _this = this;
|
|
86
|
-
return Promise.all(entries.map(function (keyValuePair) { return _this.addSplit(keyValuePair[0], keyValuePair[1]); }));
|
|
87
|
-
};
|
|
88
80
|
/**
|
|
89
81
|
* Remove a given split.
|
|
90
82
|
* The returned promise is resolved when the operation success, with a boolean indicating if the split existed or not.
|
|
@@ -100,15 +92,6 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
100
92
|
return _this.wrapper.del(_this.keys.buildSplitKey(name));
|
|
101
93
|
});
|
|
102
94
|
};
|
|
103
|
-
/**
|
|
104
|
-
* Remove a list of splits.
|
|
105
|
-
* The returned promise is resolved when the operation success, with a boolean array indicating if the splits existed or not.
|
|
106
|
-
* or rejected if it fails (e.g., wrapper operation fails).
|
|
107
|
-
*/
|
|
108
|
-
SplitsCachePluggable.prototype.removeSplits = function (names) {
|
|
109
|
-
var _this = this;
|
|
110
|
-
return Promise.all(names.map(function (name) { return _this.removeSplit(name); }));
|
|
111
|
-
};
|
|
112
95
|
/**
|
|
113
96
|
* Get split.
|
|
114
97
|
* The returned promise is resolved with the split definition or null if it's not defined,
|
|
@@ -19,6 +19,7 @@ import { UniqueKeysCacheInMemory } from '../inMemory/UniqueKeysCacheInMemory';
|
|
|
19
19
|
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
20
20
|
import { metadataBuilder } from '../utils';
|
|
21
21
|
import { LOG_PREFIX } from '../pluggable/constants';
|
|
22
|
+
import { RBSegmentsCachePluggable } from './RBSegmentsCachePluggable';
|
|
22
23
|
var NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
|
|
23
24
|
var NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';
|
|
24
25
|
/**
|
|
@@ -101,6 +102,7 @@ export function PluggableStorage(options) {
|
|
|
101
102
|
});
|
|
102
103
|
return {
|
|
103
104
|
splits: new SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
105
|
+
rbSegments: new RBSegmentsCachePluggable(log, keys, wrapper),
|
|
104
106
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
105
107
|
impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
106
108
|
impressionCounts: impressionCountsCache,
|
|
@@ -23,22 +23,21 @@ export function fromObjectUpdaterFactory(splitsParser, storage, readiness, setti
|
|
|
23
23
|
if (!loadError && splitsMock) {
|
|
24
24
|
log.debug(SYNC_OFFLINE_DATA, [JSON.stringify(splitsMock)]);
|
|
25
25
|
forOwn(splitsMock, function (val, name) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
]);
|
|
26
|
+
// @ts-ignore Split changeNumber and seed is undefined in localhost mode
|
|
27
|
+
splits.push({
|
|
28
|
+
name: name,
|
|
29
|
+
status: 'ACTIVE',
|
|
30
|
+
killed: false,
|
|
31
|
+
trafficAllocation: 100,
|
|
32
|
+
defaultTreatment: CONTROL,
|
|
33
|
+
conditions: val.conditions || [],
|
|
34
|
+
configurations: val.configurations,
|
|
35
|
+
trafficTypeName: val.trafficTypeName
|
|
36
|
+
});
|
|
38
37
|
});
|
|
39
38
|
return Promise.all([
|
|
40
39
|
splitsCache.clear(),
|
|
41
|
-
splitsCache.
|
|
40
|
+
splitsCache.update(splits, [], Date.now())
|
|
42
41
|
]).then(function () {
|
|
43
42
|
readiness.splits.emit(SDK_SPLITS_ARRIVED);
|
|
44
43
|
if (startingUp) {
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* SplitChanges fetcher is a wrapper around `splitChanges` API service that parses the response and handle errors.
|
|
4
4
|
*/
|
|
5
5
|
export function splitChangesFetcherFactory(fetchSplitChanges) {
|
|
6
|
-
return function splitChangesFetcher(since, noCache, till,
|
|
6
|
+
return function splitChangesFetcher(since, noCache, till, rbSince,
|
|
7
7
|
// Optional decorator for `fetchSplitChanges` promise, such as timeout or time tracker
|
|
8
8
|
decorator) {
|
|
9
|
-
var splitsPromise = fetchSplitChanges(since, noCache, till);
|
|
9
|
+
var splitsPromise = fetchSplitChanges(since, noCache, till, rbSince);
|
|
10
10
|
if (decorator)
|
|
11
11
|
splitsPromise = decorator(splitsPromise);
|
|
12
12
|
return splitsPromise.then(function (resp) { return resp.json(); });
|
|
@@ -31,10 +31,10 @@ export function pollingManagerCSFactory(params) {
|
|
|
31
31
|
readiness.splits.on(SDK_SPLITS_ARRIVED, function () {
|
|
32
32
|
if (!splitsSyncTask.isRunning())
|
|
33
33
|
return; // noop if not doing polling
|
|
34
|
-
var
|
|
35
|
-
if (
|
|
36
|
-
log.info(POLLING_SMART_PAUSING, [
|
|
37
|
-
if (
|
|
34
|
+
var usingSegments = storage.splits.usesSegments() || storage.rbSegments.usesSegments();
|
|
35
|
+
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
36
|
+
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
37
|
+
if (usingSegments) {
|
|
38
38
|
startMySegmentsSyncTasks();
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
@@ -46,10 +46,10 @@ export function pollingManagerCSFactory(params) {
|
|
|
46
46
|
var mySegmentsSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
47
47
|
// smart ready
|
|
48
48
|
function smartReady() {
|
|
49
|
-
if (!readiness.isReady() && !storage.splits.usesSegments())
|
|
49
|
+
if (!readiness.isReady() && !storage.splits.usesSegments() && !storage.rbSegments.usesSegments())
|
|
50
50
|
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
51
51
|
}
|
|
52
|
-
if (!storage.splits.usesSegments())
|
|
52
|
+
if (!storage.splits.usesSegments() && !storage.rbSegments.usesSegments())
|
|
53
53
|
setTimeout(smartReady, 0);
|
|
54
54
|
else
|
|
55
55
|
readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
|
|
@@ -63,7 +63,7 @@ export function pollingManagerCSFactory(params) {
|
|
|
63
63
|
start: function () {
|
|
64
64
|
log.info(POLLING_START);
|
|
65
65
|
splitsSyncTask.start();
|
|
66
|
-
if (storage.splits.usesSegments())
|
|
66
|
+
if (storage.splits.usesSegments() || storage.rbSegments.usesSegments())
|
|
67
67
|
startMySegmentsSyncTasks();
|
|
68
68
|
},
|
|
69
69
|
// Stop periodic fetching (polling)
|
|
@@ -5,5 +5,5 @@ import { splitChangesUpdaterFactory } from '../updaters/splitChangesUpdater';
|
|
|
5
5
|
* Creates a sync task that periodically executes a `splitChangesUpdater` task
|
|
6
6
|
*/
|
|
7
7
|
export function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings, isClientSide) {
|
|
8
|
-
return syncTaskFactory(settings.log, splitChangesUpdaterFactory(settings.log, splitChangesFetcherFactory(fetchSplitChanges), storage
|
|
8
|
+
return syncTaskFactory(settings.log, splitChangesUpdaterFactory(settings.log, splitChangesFetcherFactory(fetchSplitChanges), storage, settings.sync.__splitFiltersValidation, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, isClientSide), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
|
|
9
9
|
}
|
|
@@ -9,7 +9,7 @@ import { MEMBERSHIPS_LS_UPDATE } from '../../streaming/constants';
|
|
|
9
9
|
* - uses `segmentsEventEmitter` to emit events related to segments data updates
|
|
10
10
|
*/
|
|
11
11
|
export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
|
|
12
|
-
var splits = storage.splits, segments = storage.segments, largeSegments = storage.largeSegments;
|
|
12
|
+
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments, largeSegments = storage.largeSegments;
|
|
13
13
|
var readyOnAlreadyExistentState = true;
|
|
14
14
|
var startingUp = true;
|
|
15
15
|
/** timeout and telemetry decorator for `splitChangesFetcher` promise */
|
|
@@ -31,7 +31,7 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmen
|
|
|
31
31
|
shouldNotifyUpdate = largeSegments.resetSegments(segmentsData.ls || {}) || shouldNotifyUpdate;
|
|
32
32
|
}
|
|
33
33
|
// Notify update if required
|
|
34
|
-
if (splits.usesSegments() && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
|
|
34
|
+
if ((splits.usesSegments() || rbSegments.usesSegments()) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
|
|
35
35
|
readyOnAlreadyExistentState = false;
|
|
36
36
|
segmentsEventEmitter.emit(SDK_SEGMENTS_ARRIVED);
|
|
37
37
|
}
|
|
@@ -36,7 +36,7 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
36
36
|
* Returned promise will not be rejected.
|
|
37
37
|
*
|
|
38
38
|
* @param fetchOnlyNew - if true, only fetch the segments that not exists, i.e., which `changeNumber` is equal to -1.
|
|
39
|
-
* This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_UPDATE notifications.
|
|
39
|
+
* This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_UPDATE or RB_SEGMENT_UPDATE notifications.
|
|
40
40
|
* @param segmentName - segment name to fetch. By passing `undefined` it fetches the list of segments registered at the storage
|
|
41
41
|
* @param noCache - true to revalidate data to fetch on a SEGMENT_UPDATE notifications.
|
|
42
42
|
* @param till - till target for the provided segmentName, for CDN bypass.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { timeout } from '../../../utils/promise/timeout';
|
|
2
2
|
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
|
|
3
|
-
import { SYNC_SPLITS_FETCH,
|
|
3
|
+
import { SYNC_SPLITS_FETCH, SYNC_SPLITS_UPDATE, SYNC_RBS_UPDATE, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
|
|
4
4
|
import { startsWith } from '../../../utils/lang';
|
|
5
|
-
import { IN_SEGMENT } from '../../../utils/constants';
|
|
5
|
+
import { IN_RULE_BASED_SEGMENT, IN_SEGMENT } from '../../../utils/constants';
|
|
6
6
|
import { setToArray } from '../../../utils/lang/sets';
|
|
7
|
+
import { SPLIT_UPDATE } from '../../streaming/constants';
|
|
7
8
|
// Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
|
|
8
9
|
// Returns a promise that could be rejected.
|
|
9
10
|
// @TODO review together with Segments and MySegments storage APIs
|
|
@@ -18,13 +19,14 @@ function checkAllSegmentsExist(segments) {
|
|
|
18
19
|
* Collect segments from a raw split definition.
|
|
19
20
|
* Exported for testing purposes.
|
|
20
21
|
*/
|
|
21
|
-
export function parseSegments(
|
|
22
|
-
|
|
23
|
-
var
|
|
22
|
+
export function parseSegments(ruleEntity, matcherType) {
|
|
23
|
+
if (matcherType === void 0) { matcherType = IN_SEGMENT; }
|
|
24
|
+
var _a = ruleEntity, conditions = _a.conditions, excluded = _a.excluded;
|
|
25
|
+
var segments = new Set(excluded && excluded.segments);
|
|
24
26
|
for (var i = 0; i < conditions.length; i++) {
|
|
25
27
|
var matchers = conditions[i].matcherGroup.matchers;
|
|
26
28
|
matchers.forEach(function (matcher) {
|
|
27
|
-
if (matcher.matcherType ===
|
|
29
|
+
if (matcher.matcherType === matcherType)
|
|
28
30
|
segments.add(matcher.userDefinedSegmentMatcherData.segmentName);
|
|
29
31
|
});
|
|
30
32
|
}
|
|
@@ -54,22 +56,19 @@ function matchFilters(featureFlag, filters) {
|
|
|
54
56
|
* i.e., an object with added splits, removed splits and used segments.
|
|
55
57
|
* Exported for testing purposes.
|
|
56
58
|
*/
|
|
57
|
-
export function
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
parseSegments(split).forEach(function (segmentName) {
|
|
59
|
+
export function computeMutation(rules, segments, filters) {
|
|
60
|
+
return rules.reduce(function (accum, ruleEntity) {
|
|
61
|
+
if (ruleEntity.status === 'ACTIVE' && (!filters || matchFilters(ruleEntity, filters))) {
|
|
62
|
+
accum.added.push(ruleEntity);
|
|
63
|
+
parseSegments(ruleEntity).forEach(function (segmentName) {
|
|
63
64
|
segments.add(segmentName);
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
else {
|
|
67
|
-
accum.removed.push(
|
|
68
|
+
accum.removed.push(ruleEntity);
|
|
68
69
|
}
|
|
69
70
|
return accum;
|
|
70
|
-
}, { added: [], removed: []
|
|
71
|
-
computed.segments = setToArray(segments);
|
|
72
|
-
return computed;
|
|
71
|
+
}, { added: [], removed: [] });
|
|
73
72
|
}
|
|
74
73
|
/**
|
|
75
74
|
* factory of SplitChanges updater, a task that:
|
|
@@ -85,9 +84,10 @@ export function computeSplitsMutation(entries, filters) {
|
|
|
85
84
|
* @param requestTimeoutBeforeReady - How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
|
|
86
85
|
* @param retriesOnFailureBeforeReady - How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
|
|
87
86
|
*/
|
|
88
|
-
export function splitChangesUpdaterFactory(log, splitChangesFetcher,
|
|
87
|
+
export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, splitFiltersValidation, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, isClientSide) {
|
|
89
88
|
if (requestTimeoutBeforeReady === void 0) { requestTimeoutBeforeReady = 0; }
|
|
90
89
|
if (retriesOnFailureBeforeReady === void 0) { retriesOnFailureBeforeReady = 0; }
|
|
90
|
+
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments;
|
|
91
91
|
var startingUp = true;
|
|
92
92
|
/** timeout decorator for `splitChangesFetcher` promise */
|
|
93
93
|
function _promiseDecorator(promise) {
|
|
@@ -95,17 +95,6 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, seg
|
|
|
95
95
|
promise = timeout(requestTimeoutBeforeReady, promise);
|
|
96
96
|
return promise;
|
|
97
97
|
}
|
|
98
|
-
/** Returns true if at least one split was updated */
|
|
99
|
-
function isThereUpdate(flagsChange) {
|
|
100
|
-
var added = flagsChange[1], removed = flagsChange[2];
|
|
101
|
-
// There is at least one added or modified feature flag
|
|
102
|
-
if (added && added.some(function (update) { return update; }))
|
|
103
|
-
return true;
|
|
104
|
-
// There is at least one removed feature flag
|
|
105
|
-
if (removed && removed.some(function (update) { return update; }))
|
|
106
|
-
return true;
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
98
|
/**
|
|
110
99
|
* SplitChanges updater returns a promise that resolves with a `false` boolean value if it fails to fetch splits or synchronize them with the storage.
|
|
111
100
|
* Returned promise will not be rejected.
|
|
@@ -113,35 +102,48 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, seg
|
|
|
113
102
|
* @param noCache - true to revalidate data to fetch
|
|
114
103
|
* @param till - query param to bypass CDN requests
|
|
115
104
|
*/
|
|
116
|
-
return function splitChangesUpdater(noCache, till,
|
|
105
|
+
return function splitChangesUpdater(noCache, till, instantUpdate) {
|
|
117
106
|
/**
|
|
118
107
|
* @param since - current changeNumber at splitsCache
|
|
119
108
|
* @param retry - current number of retry attempts
|
|
120
109
|
*/
|
|
121
|
-
function _splitChangesUpdater(
|
|
110
|
+
function _splitChangesUpdater(sinces, retry) {
|
|
122
111
|
if (retry === void 0) { retry = 0; }
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
112
|
+
var since = sinces[0], rbSince = sinces[1];
|
|
113
|
+
log.debug(SYNC_SPLITS_FETCH, sinces);
|
|
114
|
+
var fetcherPromise = Promise.resolve(instantUpdate ?
|
|
115
|
+
instantUpdate.type === SPLIT_UPDATE ?
|
|
116
|
+
// IFFU edge case: a change to a flag that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
|
|
117
|
+
Promise.resolve(rbSegments.contains(parseSegments(instantUpdate.payload, IN_RULE_BASED_SEGMENT))).then(function (contains) {
|
|
118
|
+
return contains ?
|
|
119
|
+
{ ff: { d: [instantUpdate.payload], t: instantUpdate.changeNumber } } :
|
|
120
|
+
splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
|
|
121
|
+
}) :
|
|
122
|
+
{ rbs: { d: [instantUpdate.payload], t: instantUpdate.changeNumber } } :
|
|
123
|
+
splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator))
|
|
127
124
|
.then(function (splitChanges) {
|
|
128
125
|
startingUp = false;
|
|
129
|
-
var
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
126
|
+
var usedSegments = new Set();
|
|
127
|
+
var ffUpdate = false;
|
|
128
|
+
if (splitChanges.ff) {
|
|
129
|
+
var _a = computeMutation(splitChanges.ff.d, usedSegments, splitFiltersValidation), added = _a.added, removed = _a.removed;
|
|
130
|
+
log.debug(SYNC_SPLITS_UPDATE, [added.length, removed.length]);
|
|
131
|
+
ffUpdate = splits.update(added, removed, splitChanges.ff.t);
|
|
132
|
+
}
|
|
133
|
+
var rbsUpdate = false;
|
|
134
|
+
if (splitChanges.rbs) {
|
|
135
|
+
var _b = computeMutation(splitChanges.rbs.d, usedSegments), added = _b.added, removed = _b.removed;
|
|
136
|
+
log.debug(SYNC_RBS_UPDATE, [added.length, removed.length]);
|
|
137
|
+
rbsUpdate = rbSegments.update(added, removed, splitChanges.rbs.t);
|
|
138
|
+
}
|
|
139
|
+
return Promise.all([ffUpdate, rbsUpdate,
|
|
140
|
+
// @TODO if at least 1 segment fetch fails due to 404 and other segments are updated in the storage, SDK_UPDATE is not emitted
|
|
141
|
+
segments.registerSegments(setToArray(usedSegments))
|
|
142
|
+
]).then(function (_a) {
|
|
143
|
+
var ffChanged = _a[0], rbsChanged = _a[1];
|
|
142
144
|
if (splitsEventEmitter) {
|
|
143
145
|
// To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
|
|
144
|
-
return Promise.resolve(!splitsEventEmitter.splitsArrived || (
|
|
146
|
+
return Promise.resolve(!splitsEventEmitter.splitsArrived || ((ffChanged || rbsChanged) && (isClientSide || checkAllSegmentsExist(segments))))
|
|
145
147
|
.catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
|
|
146
148
|
.then(function (emitSplitsArrivedEvent) {
|
|
147
149
|
// emit SDK events
|
|
@@ -158,7 +160,7 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, seg
|
|
|
158
160
|
if (startingUp && retriesOnFailureBeforeReady > retry) {
|
|
159
161
|
retry += 1;
|
|
160
162
|
log.info(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
|
|
161
|
-
return _splitChangesUpdater(
|
|
163
|
+
return _splitChangesUpdater(sinces, retry);
|
|
162
164
|
}
|
|
163
165
|
else {
|
|
164
166
|
startingUp = false;
|
|
@@ -175,7 +177,7 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, seg
|
|
|
175
177
|
}
|
|
176
178
|
return fetcherPromise;
|
|
177
179
|
}
|
|
178
|
-
|
|
179
|
-
return
|
|
180
|
+
// `getChangeNumber` never rejects or throws error
|
|
181
|
+
return Promise.all([splits.getChangeNumber(), rbSegments.getChangeNumber()]).then(_splitChangesUpdater);
|
|
180
182
|
};
|
|
181
183
|
}
|