@splitsoftware/splitio-commons 2.2.1-rc.0 → 2.2.1-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 +2 -3
- package/README.md +0 -1
- package/cjs/evaluator/Engine.js +61 -40
- package/cjs/evaluator/combiners/and.js +6 -2
- package/cjs/evaluator/combiners/ifelseif.js +6 -6
- package/cjs/evaluator/condition/index.js +5 -6
- package/cjs/evaluator/index.js +11 -11
- package/cjs/evaluator/matchers/index.js +1 -3
- package/cjs/evaluator/matchers/matcherTypes.js +0 -1
- package/cjs/evaluator/matchersTransform/index.js +0 -4
- package/cjs/evaluator/parser/index.js +2 -2
- package/cjs/evaluator/value/sanitize.js +0 -1
- package/cjs/logger/constants.js +3 -5
- package/cjs/logger/messages/debug.js +2 -4
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/sdkManager/index.js +1 -2
- package/cjs/services/splitApi.js +4 -3
- package/cjs/storages/AbstractSplitsCacheSync.js +2 -5
- package/cjs/storages/KeyBuilder.js +0 -9
- package/cjs/storages/KeyBuilderCS.js +0 -3
- package/cjs/storages/KeyBuilderSS.js +0 -3
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +14 -9
- package/cjs/storages/inLocalStorage/index.js +1 -5
- package/cjs/storages/inLocalStorage/validateCache.js +1 -2
- package/cjs/storages/inMemory/InMemoryStorage.js +0 -3
- package/cjs/storages/inMemory/InMemoryStorageCS.js +0 -4
- package/cjs/storages/inRedis/index.js +9 -5
- package/cjs/storages/pluggable/index.js +0 -2
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +4 -51
- 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 +33 -51
- package/cjs/sync/streaming/SSEHandler/index.js +0 -1
- package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +77 -106
- package/cjs/sync/streaming/constants.js +1 -2
- package/cjs/sync/streaming/pushManager.js +16 -3
- package/cjs/sync/syncManagerOnline.js +2 -2
- package/cjs/utils/constants/index.js +2 -3
- package/cjs/utils/labels/index.js +1 -2
- package/esm/evaluator/Engine.js +62 -40
- package/esm/evaluator/combiners/and.js +6 -2
- package/esm/evaluator/combiners/ifelseif.js +7 -7
- package/esm/evaluator/condition/index.js +5 -6
- package/esm/evaluator/index.js +12 -12
- package/esm/evaluator/matchers/index.js +1 -3
- package/esm/evaluator/matchers/matcherTypes.js +0 -1
- package/esm/evaluator/matchersTransform/index.js +0 -4
- package/esm/evaluator/parser/index.js +2 -2
- package/esm/evaluator/value/sanitize.js +0 -1
- package/esm/logger/constants.js +0 -2
- package/esm/logger/messages/debug.js +2 -4
- package/esm/logger/messages/warn.js +1 -1
- package/esm/sdkManager/index.js +1 -2
- package/esm/services/splitApi.js +4 -3
- package/esm/storages/AbstractSplitsCacheSync.js +2 -5
- package/esm/storages/KeyBuilder.js +0 -9
- package/esm/storages/KeyBuilderCS.js +0 -3
- package/esm/storages/KeyBuilderSS.js +0 -3
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +14 -9
- package/esm/storages/inLocalStorage/index.js +1 -5
- package/esm/storages/inLocalStorage/validateCache.js +1 -2
- package/esm/storages/inMemory/InMemoryStorage.js +0 -3
- package/esm/storages/inMemory/InMemoryStorageCS.js +0 -4
- package/esm/storages/inRedis/index.js +9 -5
- package/esm/storages/pluggable/index.js +0 -2
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +4 -51
- 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 +33 -51
- package/esm/sync/streaming/SSEHandler/index.js +1 -2
- package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +73 -102
- package/esm/sync/streaming/constants.js +0 -1
- package/esm/sync/streaming/pushManager.js +19 -6
- package/esm/sync/syncManagerOnline.js +2 -2
- package/esm/utils/constants/index.js +1 -2
- package/esm/utils/labels/index.js +0 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +8 -36
- package/src/evaluator/Engine.ts +69 -42
- package/src/evaluator/combiners/and.ts +4 -5
- package/src/evaluator/combiners/ifelseif.ts +9 -7
- package/src/evaluator/condition/engineUtils.ts +1 -1
- package/src/evaluator/condition/index.ts +12 -12
- package/src/evaluator/index.ts +14 -12
- package/src/evaluator/matchers/index.ts +1 -3
- package/src/evaluator/matchers/matcherTypes.ts +0 -1
- package/src/evaluator/matchersTransform/index.ts +0 -3
- 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 +4 -5
- package/src/logger/constants.ts +0 -2
- package/src/logger/messages/debug.ts +2 -4
- package/src/logger/messages/warn.ts +1 -1
- package/src/sdkManager/index.ts +2 -3
- package/src/services/splitApi.ts +4 -3
- package/src/services/types.ts +1 -1
- package/src/storages/AbstractSplitsCacheSync.ts +3 -6
- package/src/storages/KeyBuilder.ts +0 -12
- package/src/storages/KeyBuilderCS.ts +0 -4
- package/src/storages/KeyBuilderSS.ts +0 -4
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +14 -10
- package/src/storages/inLocalStorage/index.ts +1 -5
- package/src/storages/inLocalStorage/validateCache.ts +1 -3
- package/src/storages/inMemory/InMemoryStorage.ts +0 -3
- package/src/storages/inMemory/InMemoryStorageCS.ts +0 -4
- package/src/storages/inRedis/index.ts +11 -7
- package/src/storages/pluggable/index.ts +0 -2
- package/src/storages/types.ts +1 -33
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +4 -62
- package/src/sync/polling/fetchers/types.ts +0 -1
- package/src/sync/polling/pollingManagerCS.ts +7 -7
- package/src/sync/polling/syncTasks/splitsSyncTask.ts +1 -1
- 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 +42 -61
- package/src/sync/streaming/SSEHandler/index.ts +1 -2
- package/src/sync/streaming/SSEHandler/types.ts +2 -2
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +68 -98
- package/src/sync/streaming/constants.ts +0 -1
- package/src/sync/streaming/parseUtils.ts +2 -2
- package/src/sync/streaming/pushManager.ts +18 -6
- package/src/sync/streaming/types.ts +2 -3
- package/src/sync/syncManagerOnline.ts +2 -2
- package/src/utils/constants/index.ts +1 -2
- package/src/utils/labels/index.ts +0 -1
- package/src/utils/lang/index.ts +1 -1
- package/types/splitio.d.ts +1 -5
- package/cjs/evaluator/matchers/prerequisites.js +0 -22
- package/cjs/evaluator/matchers/rbsegment.js +0 -44
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +0 -117
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +0 -61
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +0 -64
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +0 -64
- package/esm/evaluator/matchers/prerequisites.js +0 -18
- package/esm/evaluator/matchers/rbsegment.js +0 -40
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +0 -114
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +0 -58
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +0 -61
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +0 -61
- package/src/evaluator/matchers/prerequisites.ts +0 -24
- package/src/evaluator/matchers/rbsegment.ts +0 -62
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +0 -136
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +0 -68
- package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +0 -79
- package/src/storages/pluggable/RBSegmentsCachePluggable.ts +0 -76
|
@@ -5,7 +5,6 @@ import { validatePrefix } from '../KeyBuilder';
|
|
|
5
5
|
import { KeyBuilderCS, myLargeSegmentsKeyBuilder } from '../KeyBuilderCS';
|
|
6
6
|
import { isLocalStorageAvailable } from '../../utils/env/isLocalStorageAvailable';
|
|
7
7
|
import { SplitsCacheInLocal } from './SplitsCacheInLocal';
|
|
8
|
-
import { RBSegmentsCacheInLocal } from './RBSegmentsCacheInLocal';
|
|
9
8
|
import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
|
|
10
9
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
11
10
|
import { LOG_PREFIX } from './constants';
|
|
@@ -30,12 +29,10 @@ export function InLocalStorage(options) {
|
|
|
30
29
|
var matchingKey = getMatching(settings.core.key);
|
|
31
30
|
var keys = new KeyBuilderCS(prefix, matchingKey);
|
|
32
31
|
var splits = new SplitsCacheInLocal(settings, keys);
|
|
33
|
-
var rbSegments = new RBSegmentsCacheInLocal(settings, keys);
|
|
34
32
|
var segments = new MySegmentsCacheInLocal(log, keys);
|
|
35
33
|
var largeSegments = new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey));
|
|
36
34
|
return {
|
|
37
35
|
splits: splits,
|
|
38
|
-
rbSegments: rbSegments,
|
|
39
36
|
segments: segments,
|
|
40
37
|
largeSegments: largeSegments,
|
|
41
38
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
@@ -44,14 +41,13 @@ export function InLocalStorage(options) {
|
|
|
44
41
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
45
42
|
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
46
43
|
validateCache: function () {
|
|
47
|
-
return validateCache(options, settings, keys, splits,
|
|
44
|
+
return validateCache(options, settings, keys, splits, segments, largeSegments);
|
|
48
45
|
},
|
|
49
46
|
destroy: function () { },
|
|
50
47
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
|
|
51
48
|
shared: function (matchingKey) {
|
|
52
49
|
return {
|
|
53
50
|
splits: this.splits,
|
|
54
|
-
rbSegments: this.rbSegments,
|
|
55
51
|
segments: new MySegmentsCacheInLocal(log, new KeyBuilderCS(prefix, matchingKey)),
|
|
56
52
|
largeSegments: new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey)),
|
|
57
53
|
impressions: this.impressions,
|
|
@@ -54,12 +54,11 @@ function validateExpiration(options, settings, keys, currentTimestamp, isThereCa
|
|
|
54
54
|
*
|
|
55
55
|
* @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
|
|
56
56
|
*/
|
|
57
|
-
export function validateCache(options, settings, keys, splits,
|
|
57
|
+
export function validateCache(options, settings, keys, splits, segments, largeSegments) {
|
|
58
58
|
var currentTimestamp = Date.now();
|
|
59
59
|
var isThereCache = splits.getChangeNumber() > -1;
|
|
60
60
|
if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
|
|
61
61
|
splits.clear();
|
|
62
|
-
rbSegments.clear();
|
|
63
62
|
segments.clear();
|
|
64
63
|
largeSegments.clear();
|
|
65
64
|
// Update last clear timestamp
|
|
@@ -6,7 +6,6 @@ import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
|
6
6
|
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
8
|
import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
9
|
-
import { RBSegmentsCacheInMemory } from './RBSegmentsCacheInMemory';
|
|
10
9
|
/**
|
|
11
10
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
12
11
|
*
|
|
@@ -15,11 +14,9 @@ import { RBSegmentsCacheInMemory } from './RBSegmentsCacheInMemory';
|
|
|
15
14
|
export function InMemoryStorageFactory(params) {
|
|
16
15
|
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
|
|
17
16
|
var splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
18
|
-
var rbSegments = new RBSegmentsCacheInMemory();
|
|
19
17
|
var segments = new SegmentsCacheInMemory();
|
|
20
18
|
var storage = {
|
|
21
19
|
splits: splits,
|
|
22
|
-
rbSegments: rbSegments,
|
|
23
20
|
segments: segments,
|
|
24
21
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
25
22
|
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
@@ -6,7 +6,6 @@ import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
|
6
6
|
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
8
|
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
9
|
-
import { RBSegmentsCacheInMemory } from './RBSegmentsCacheInMemory';
|
|
10
9
|
/**
|
|
11
10
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
12
11
|
*
|
|
@@ -15,12 +14,10 @@ import { RBSegmentsCacheInMemory } from './RBSegmentsCacheInMemory';
|
|
|
15
14
|
export function InMemoryStorageCSFactory(params) {
|
|
16
15
|
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
|
|
17
16
|
var splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
18
|
-
var rbSegments = new RBSegmentsCacheInMemory();
|
|
19
17
|
var segments = new MySegmentsCacheInMemory();
|
|
20
18
|
var largeSegments = new MySegmentsCacheInMemory();
|
|
21
19
|
var storage = {
|
|
22
20
|
splits: splits,
|
|
23
|
-
rbSegments: rbSegments,
|
|
24
21
|
segments: segments,
|
|
25
22
|
largeSegments: largeSegments,
|
|
26
23
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
@@ -33,7 +30,6 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
33
30
|
shared: function () {
|
|
34
31
|
return {
|
|
35
32
|
splits: this.splits,
|
|
36
|
-
rbSegments: this.rbSegments,
|
|
37
33
|
segments: new MySegmentsCacheInMemory(),
|
|
38
34
|
largeSegments: new MySegmentsCacheInMemory(),
|
|
39
35
|
impressions: this.impressions,
|
|
@@ -9,18 +9,23 @@ import { TelemetryCacheInRedis } from './TelemetryCacheInRedis';
|
|
|
9
9
|
import { UniqueKeysCacheInRedis } from './UniqueKeysCacheInRedis';
|
|
10
10
|
import { ImpressionCountsCacheInRedis } from './ImpressionCountsCacheInRedis';
|
|
11
11
|
import { metadataBuilder } from '../utils';
|
|
12
|
-
|
|
12
|
+
var RD;
|
|
13
|
+
try {
|
|
14
|
+
// Using `require` to prevent error when bundling or importing the SDK in a .mjs file, since ioredis is a CommonJS module.
|
|
15
|
+
// Redis storage is not supported with .mjs files.
|
|
16
|
+
RD = require('./RedisAdapter').RedisAdapter;
|
|
17
|
+
}
|
|
18
|
+
catch (error) { /* empty */ }
|
|
13
19
|
/**
|
|
14
20
|
* InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node.js
|
|
15
21
|
* @see {@link https://www.npmjs.com/package/ioredis}
|
|
16
22
|
*/
|
|
17
23
|
export function InRedisStorage(options) {
|
|
18
24
|
if (options === void 0) { options = {}; }
|
|
19
|
-
// Lazy loading to prevent error when bundling or importing the SDK in a .mjs file, since ioredis is a CommonJS module.
|
|
20
|
-
// Redis storage is not supported with .mjs files.
|
|
21
|
-
var RD = require('./RedisAdapter').RedisAdapter;
|
|
22
25
|
var prefix = validatePrefix(options.prefix);
|
|
23
26
|
function InRedisStorageFactory(params) {
|
|
27
|
+
if (!RD)
|
|
28
|
+
throw new Error('The SDK Redis storage is not available. Your runtime environment must support CommonJS (`require`) to import the ioredis dependency.');
|
|
24
29
|
var onReadyCb = params.onReadyCb, settings = params.settings, log = params.settings.log;
|
|
25
30
|
var metadata = metadataBuilder(settings);
|
|
26
31
|
var keys = new KeyBuilderSS(prefix, metadata);
|
|
@@ -38,7 +43,6 @@ export function InRedisStorage(options) {
|
|
|
38
43
|
});
|
|
39
44
|
return {
|
|
40
45
|
splits: new SplitsCacheInRedis(log, keys, redisClient, settings.sync.__splitFiltersValidation),
|
|
41
|
-
rbSegments: new RBSegmentsCacheInRedis(log, keys, redisClient),
|
|
42
46
|
segments: new SegmentsCacheInRedis(log, keys, redisClient),
|
|
43
47
|
impressions: new ImpressionsCacheInRedis(log, keys.buildImpressionsKey(), redisClient, metadata),
|
|
44
48
|
impressionCounts: impressionCountsCache,
|
|
@@ -19,7 +19,6 @@ 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';
|
|
23
22
|
var NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
|
|
24
23
|
var NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';
|
|
25
24
|
/**
|
|
@@ -103,7 +102,6 @@ export function PluggableStorage(options) {
|
|
|
103
102
|
});
|
|
104
103
|
return {
|
|
105
104
|
splits: new SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
106
|
-
rbSegments: new RBSegmentsCachePluggable(log, keys, wrapper),
|
|
107
105
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
108
106
|
impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
109
107
|
impressionCounts: impressionCountsCache,
|
|
@@ -1,61 +1,14 @@
|
|
|
1
|
-
import { FLAG_SPEC_VERSION } from '../../../utils/constants';
|
|
2
|
-
import { base } from '../../../utils/settingsValidation';
|
|
3
|
-
import { LOG_PREFIX_SYNC_SPLITS } from '../../../logger/constants';
|
|
4
|
-
var PROXY_CHECK_INTERVAL_MILLIS_CS = 60 * 60 * 1000; // 1 hour in Client Side
|
|
5
|
-
var PROXY_CHECK_INTERVAL_MILLIS_SS = 24 * PROXY_CHECK_INTERVAL_MILLIS_CS; // 24 hours in Server Side
|
|
6
|
-
function sdkEndpointOverriden(settings) {
|
|
7
|
-
return settings.urls.sdk !== base.urls.sdk;
|
|
8
|
-
}
|
|
9
1
|
/**
|
|
10
2
|
* Factory of SplitChanges fetcher.
|
|
11
3
|
* SplitChanges fetcher is a wrapper around `splitChanges` API service that parses the response and handle errors.
|
|
12
4
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
var log = settings.log;
|
|
16
|
-
var PROXY_CHECK_INTERVAL_MILLIS = settings.core.key !== undefined ? PROXY_CHECK_INTERVAL_MILLIS_CS : PROXY_CHECK_INTERVAL_MILLIS_SS;
|
|
17
|
-
var lastProxyCheckTimestamp;
|
|
18
|
-
return function splitChangesFetcher(since, noCache, till, rbSince,
|
|
5
|
+
export function splitChangesFetcherFactory(fetchSplitChanges) {
|
|
6
|
+
return function splitChangesFetcher(since, noCache, till,
|
|
19
7
|
// Optional decorator for `fetchSplitChanges` promise, such as timeout or time tracker
|
|
20
8
|
decorator) {
|
|
21
|
-
|
|
22
|
-
if (lastProxyCheckTimestamp && (Date.now() - lastProxyCheckTimestamp) > PROXY_CHECK_INTERVAL_MILLIS) {
|
|
23
|
-
settings.sync.flagSpecVersion = FLAG_SPEC_VERSION;
|
|
24
|
-
}
|
|
25
|
-
var splitsPromise = fetchSplitChanges(since, noCache, till, settings.sync.flagSpecVersion === FLAG_SPEC_VERSION ? rbSince : undefined)
|
|
26
|
-
// Handle proxy error with spec 1.3
|
|
27
|
-
.catch(function (err) {
|
|
28
|
-
if (err.statusCode === 400 && sdkEndpointOverriden(settings) && settings.sync.flagSpecVersion === FLAG_SPEC_VERSION) {
|
|
29
|
-
log.error(LOG_PREFIX_SYNC_SPLITS + 'Proxy error detected. If you are using Split Proxy, please upgrade to latest version');
|
|
30
|
-
lastProxyCheckTimestamp = Date.now();
|
|
31
|
-
settings.sync.flagSpecVersion = '1.2'; // fallback to 1.2 spec
|
|
32
|
-
return fetchSplitChanges(since, noCache, till); // retry request without rbSince
|
|
33
|
-
}
|
|
34
|
-
throw err;
|
|
35
|
-
});
|
|
9
|
+
var splitsPromise = fetchSplitChanges(since, noCache, till);
|
|
36
10
|
if (decorator)
|
|
37
11
|
splitsPromise = decorator(splitsPromise);
|
|
38
|
-
return splitsPromise
|
|
39
|
-
.then(function (resp) { return resp.json(); })
|
|
40
|
-
.then(function (data) {
|
|
41
|
-
// Using flag spec version 1.2
|
|
42
|
-
if (data.splits) {
|
|
43
|
-
return {
|
|
44
|
-
ff: {
|
|
45
|
-
d: data.splits,
|
|
46
|
-
s: data.since,
|
|
47
|
-
t: data.till
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
// Proxy recovery
|
|
52
|
-
if (lastProxyCheckTimestamp) {
|
|
53
|
-
log.info(LOG_PREFIX_SYNC_SPLITS + 'Proxy error recovered');
|
|
54
|
-
lastProxyCheckTimestamp = undefined;
|
|
55
|
-
return Promise.all([storage.splits.clear(), storage.rbSegments.clear()])
|
|
56
|
-
.then(function () { return splitChangesFetcher(storage.splits.getChangeNumber(), undefined, undefined, storage.rbSegments.getChangeNumber()); });
|
|
57
|
-
}
|
|
58
|
-
return data;
|
|
59
|
-
});
|
|
12
|
+
return splitsPromise.then(function (resp) { return resp.json(); });
|
|
60
13
|
};
|
|
61
14
|
}
|
|
@@ -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 splitsHaveSegments = storage.splits.usesSegments();
|
|
35
|
+
if (splitsHaveSegments !== mySegmentsSyncTask.isRunning()) {
|
|
36
|
+
log.info(POLLING_SMART_PAUSING, [splitsHaveSegments ? 'ON' : 'OFF']);
|
|
37
|
+
if (splitsHaveSegments) {
|
|
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())
|
|
50
50
|
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
51
51
|
}
|
|
52
|
-
if (!storage.splits.usesSegments()
|
|
52
|
+
if (!storage.splits.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())
|
|
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
|
|
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,
|
|
12
|
+
var splits = storage.splits, 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 (
|
|
34
|
+
if (splits.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
|
|
39
|
+
* This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_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,10 +1,9 @@
|
|
|
1
1
|
import { timeout } from '../../../utils/promise/timeout';
|
|
2
2
|
import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
|
|
3
|
-
import { SYNC_SPLITS_FETCH, SYNC_SPLITS_UPDATE,
|
|
3
|
+
import { SYNC_SPLITS_FETCH, SYNC_SPLITS_UPDATE, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
|
|
4
4
|
import { startsWith } from '../../../utils/lang';
|
|
5
|
-
import {
|
|
5
|
+
import { IN_SEGMENT } from '../../../utils/constants';
|
|
6
6
|
import { setToArray } from '../../../utils/lang/sets';
|
|
7
|
-
import { SPLIT_UPDATE } from '../../streaming/constants';
|
|
8
7
|
// Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
|
|
9
8
|
// Returns a promise that could be rejected.
|
|
10
9
|
// @TODO review together with Segments and MySegments storage APIs
|
|
@@ -19,14 +18,13 @@ function checkAllSegmentsExist(segments) {
|
|
|
19
18
|
* Collect segments from a raw split definition.
|
|
20
19
|
* Exported for testing purposes.
|
|
21
20
|
*/
|
|
22
|
-
export function parseSegments(
|
|
23
|
-
|
|
24
|
-
var
|
|
25
|
-
var segments = new Set(excluded && excluded.segments);
|
|
21
|
+
export function parseSegments(_a) {
|
|
22
|
+
var conditions = _a.conditions;
|
|
23
|
+
var segments = new Set();
|
|
26
24
|
for (var i = 0; i < conditions.length; i++) {
|
|
27
25
|
var matchers = conditions[i].matcherGroup.matchers;
|
|
28
26
|
matchers.forEach(function (matcher) {
|
|
29
|
-
if (matcher.matcherType ===
|
|
27
|
+
if (matcher.matcherType === IN_SEGMENT)
|
|
30
28
|
segments.add(matcher.userDefinedSegmentMatcherData.segmentName);
|
|
31
29
|
});
|
|
32
30
|
}
|
|
@@ -56,19 +54,22 @@ function matchFilters(featureFlag, filters) {
|
|
|
56
54
|
* i.e., an object with added splits, removed splits and used segments.
|
|
57
55
|
* Exported for testing purposes.
|
|
58
56
|
*/
|
|
59
|
-
export function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
export function computeSplitsMutation(entries, filters) {
|
|
58
|
+
var segments = new Set();
|
|
59
|
+
var computed = entries.reduce(function (accum, split) {
|
|
60
|
+
if (split.status === 'ACTIVE' && matchFilters(split, filters)) {
|
|
61
|
+
accum.added.push(split);
|
|
62
|
+
parseSegments(split).forEach(function (segmentName) {
|
|
64
63
|
segments.add(segmentName);
|
|
65
64
|
});
|
|
66
65
|
}
|
|
67
66
|
else {
|
|
68
|
-
accum.removed.push(
|
|
67
|
+
accum.removed.push(split);
|
|
69
68
|
}
|
|
70
69
|
return accum;
|
|
71
|
-
}, { added: [], removed: [] });
|
|
70
|
+
}, { added: [], removed: [], segments: [] });
|
|
71
|
+
computed.segments = setToArray(segments);
|
|
72
|
+
return computed;
|
|
72
73
|
}
|
|
73
74
|
/**
|
|
74
75
|
* factory of SplitChanges updater, a task that:
|
|
@@ -87,7 +88,7 @@ export function computeMutation(rules, segments, filters) {
|
|
|
87
88
|
export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, splitFiltersValidation, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, isClientSide) {
|
|
88
89
|
if (requestTimeoutBeforeReady === void 0) { requestTimeoutBeforeReady = 0; }
|
|
89
90
|
if (retriesOnFailureBeforeReady === void 0) { retriesOnFailureBeforeReady = 0; }
|
|
90
|
-
var splits = storage.splits,
|
|
91
|
+
var splits = storage.splits, segments = storage.segments;
|
|
91
92
|
var startingUp = true;
|
|
92
93
|
/** timeout decorator for `splitChangesFetcher` promise */
|
|
93
94
|
function _promiseDecorator(promise) {
|
|
@@ -102,48 +103,29 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, sp
|
|
|
102
103
|
* @param noCache - true to revalidate data to fetch
|
|
103
104
|
* @param till - query param to bypass CDN requests
|
|
104
105
|
*/
|
|
105
|
-
return function splitChangesUpdater(noCache, till,
|
|
106
|
+
return function splitChangesUpdater(noCache, till, splitUpdateNotification) {
|
|
106
107
|
/**
|
|
107
108
|
* @param since - current changeNumber at splitsCache
|
|
108
109
|
* @param retry - current number of retry attempts
|
|
109
110
|
*/
|
|
110
|
-
function _splitChangesUpdater(
|
|
111
|
+
function _splitChangesUpdater(since, retry) {
|
|
111
112
|
if (retry === void 0) { retry = 0; }
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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))
|
|
113
|
+
log.debug(SYNC_SPLITS_FETCH, [since]);
|
|
114
|
+
return Promise.resolve(splitUpdateNotification ?
|
|
115
|
+
{ splits: [splitUpdateNotification.payload], till: splitUpdateNotification.changeNumber } :
|
|
116
|
+
splitChangesFetcher(since, noCache, till, _promiseDecorator))
|
|
124
117
|
.then(function (splitChanges) {
|
|
125
118
|
startingUp = false;
|
|
126
|
-
var
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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))
|
|
119
|
+
var mutation = computeSplitsMutation(splitChanges.splits, splitFiltersValidation);
|
|
120
|
+
log.debug(SYNC_SPLITS_UPDATE, [mutation.added.length, mutation.removed.length, mutation.segments.length]);
|
|
121
|
+
return Promise.all([
|
|
122
|
+
splits.update(mutation.added, mutation.removed, splitChanges.till),
|
|
123
|
+
segments.registerSegments(mutation.segments)
|
|
142
124
|
]).then(function (_a) {
|
|
143
|
-
var
|
|
125
|
+
var isThereUpdate = _a[0];
|
|
144
126
|
if (splitsEventEmitter) {
|
|
145
127
|
// To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
|
|
146
|
-
return Promise.resolve(!splitsEventEmitter.splitsArrived || (
|
|
128
|
+
return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && isThereUpdate && (isClientSide || checkAllSegmentsExist(segments))))
|
|
147
129
|
.catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
|
|
148
130
|
.then(function (emitSplitsArrivedEvent) {
|
|
149
131
|
// emit SDK events
|
|
@@ -160,7 +142,7 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, sp
|
|
|
160
142
|
if (startingUp && retriesOnFailureBeforeReady > retry) {
|
|
161
143
|
retry += 1;
|
|
162
144
|
log.info(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
|
|
163
|
-
return _splitChangesUpdater(
|
|
145
|
+
return _splitChangesUpdater(since, retry);
|
|
164
146
|
}
|
|
165
147
|
else {
|
|
166
148
|
startingUp = false;
|
|
@@ -168,7 +150,7 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, sp
|
|
|
168
150
|
return false;
|
|
169
151
|
});
|
|
170
152
|
}
|
|
171
|
-
// `getChangeNumber` never rejects or throws error
|
|
172
|
-
return
|
|
153
|
+
var sincePromise = Promise.resolve(splits.getChangeNumber()); // `getChangeNumber` never rejects or throws error
|
|
154
|
+
return sincePromise.then(_splitChangesUpdater);
|
|
173
155
|
};
|
|
174
156
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { errorParser, messageParser } from './NotificationParser';
|
|
2
2
|
import { notificationKeeperFactory } from './NotificationKeeper';
|
|
3
|
-
import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE
|
|
3
|
+
import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE } from '../constants';
|
|
4
4
|
import { STREAMING_PARSING_ERROR_FAILS, ERROR_STREAMING_SSE, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_NEW_MESSAGE } from '../../../logger/constants';
|
|
5
5
|
import { ABLY_ERROR, NON_REQUESTED, SSE_CONNECTION_ERROR } from '../../../utils/constants';
|
|
6
6
|
/**
|
|
@@ -75,7 +75,6 @@ export function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
|
|
|
75
75
|
case MEMBERSHIPS_MS_UPDATE:
|
|
76
76
|
case MEMBERSHIPS_LS_UPDATE:
|
|
77
77
|
case SPLIT_KILL:
|
|
78
|
-
case RB_SEGMENT_UPDATE:
|
|
79
78
|
pushEmitter.emit(parsedData.type, parsedData);
|
|
80
79
|
break;
|
|
81
80
|
/* occupancy & control events, handled by NotificationManagerKeeper */
|