@splitsoftware/splitio-commons 2.1.0-rc.2 → 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/CHANGES.txt +2 -7
- 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/readiness/readinessManager.js +0 -6
- package/cjs/services/splitApi.js +2 -2
- package/cjs/storages/AbstractSplitsCacheAsync.js +19 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +17 -9
- package/cjs/storages/KeyBuilder.js +8 -15
- package/cjs/storages/KeyBuilderCS.js +11 -5
- package/cjs/storages/KeyBuilderSS.js +3 -0
- package/cjs/storages/dataLoader.js +3 -5
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +117 -0
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +69 -15
- package/cjs/storages/inLocalStorage/index.js +7 -5
- 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/constants.js +1 -1
- 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 +3 -2
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +14 -16
- 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 +62 -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 +5 -10
- package/cjs/trackers/uniqueKeysTracker.js +1 -1
- package/cjs/utils/constants/browser.js +5 -0
- package/cjs/utils/constants/index.js +3 -2
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- 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/readiness/readinessManager.js +0 -6
- package/esm/services/splitApi.js +2 -2
- package/esm/storages/AbstractSplitsCacheAsync.js +19 -1
- package/esm/storages/AbstractSplitsCacheSync.js +17 -9
- package/esm/storages/KeyBuilder.js +8 -15
- package/esm/storages/KeyBuilderCS.js +11 -5
- package/esm/storages/KeyBuilderSS.js +3 -0
- package/esm/storages/dataLoader.js +2 -4
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +114 -0
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +69 -15
- package/esm/storages/inLocalStorage/index.js +7 -5
- 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/constants.js +1 -1
- 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 +3 -2
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +14 -16
- 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 +63 -52
- 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 +5 -10
- package/esm/trackers/uniqueKeysTracker.js +1 -1
- package/esm/utils/constants/browser.js +2 -0
- package/esm/utils/constants/index.js +2 -1
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -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/readiness/readinessManager.ts +0 -5
- 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 +23 -5
- package/src/storages/AbstractSplitsCacheSync.ts +22 -15
- package/src/storages/KeyBuilder.ts +9 -17
- package/src/storages/KeyBuilderCS.ts +13 -6
- package/src/storages/KeyBuilderSS.ts +4 -0
- package/src/storages/dataLoader.ts +2 -5
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +136 -0
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +80 -16
- package/src/storages/inLocalStorage/index.ts +12 -8
- 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/constants.ts +1 -1
- 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 +3 -2
- package/src/storages/types.ts +47 -18
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +19 -21
- 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 +74 -63
- 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 +5 -11
- package/src/trackers/uniqueKeysTracker.ts +1 -1
- package/src/utils/constants/browser.ts +2 -0
- package/src/utils/constants/index.ts +2 -1
- package/src/utils/lang/index.ts +2 -2
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/splitio.d.ts +1 -25
- package/cjs/storages/inLocalStorage/validateCache.js +0 -79
- package/esm/storages/inLocalStorage/validateCache.js +0 -75
- package/src/storages/inLocalStorage/validateCache.ts +0 -91
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ISplitsCacheSync } from './types';
|
|
2
|
-
import { ISplit } from '../dtos/types';
|
|
2
|
+
import { IRBSegment, ISplit } from '../dtos/types';
|
|
3
3
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
4
4
|
import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
|
|
5
5
|
|
|
@@ -9,16 +9,14 @@ import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
|
|
|
9
9
|
*/
|
|
10
10
|
export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
11
11
|
|
|
12
|
-
abstract addSplit(
|
|
12
|
+
protected abstract addSplit(split: ISplit): boolean
|
|
13
|
+
protected abstract removeSplit(name: string): boolean
|
|
14
|
+
protected abstract setChangeNumber(changeNumber: number): boolean | void
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
abstract removeSplit(name: string): boolean
|
|
19
|
-
|
|
20
|
-
removeSplits(names: string[]): boolean[] {
|
|
21
|
-
return names.map(name => this.removeSplit(name));
|
|
16
|
+
update(toAdd: ISplit[], toRemove: ISplit[], changeNumber: number): boolean {
|
|
17
|
+
this.setChangeNumber(changeNumber);
|
|
18
|
+
const updated = toAdd.map(addedFF => this.addSplit(addedFF)).some(result => result);
|
|
19
|
+
return toRemove.map(removedFF => this.removeSplit(removedFF.name)).some(result => result) || updated;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
abstract getSplit(name: string): ISplit | null
|
|
@@ -31,8 +29,6 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
31
29
|
return splits;
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
abstract setChangeNumber(changeNumber: number): boolean | void
|
|
35
|
-
|
|
36
32
|
abstract getChangeNumber(): number
|
|
37
33
|
|
|
38
34
|
getAll(): ISplit[] {
|
|
@@ -47,6 +43,14 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
47
43
|
|
|
48
44
|
abstract clear(): void
|
|
49
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Check if the splits information is already stored in cache. This data can be preloaded.
|
|
48
|
+
* It is used as condition to emit SDK_SPLITS_CACHE_LOADED, and then SDK_READY_FROM_CACHE.
|
|
49
|
+
*/
|
|
50
|
+
checkCache(): boolean {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
50
54
|
/**
|
|
51
55
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
52
56
|
* Used for SPLIT_KILL push notifications.
|
|
@@ -63,7 +67,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
63
67
|
newSplit.defaultTreatment = defaultTreatment;
|
|
64
68
|
newSplit.changeNumber = changeNumber;
|
|
65
69
|
|
|
66
|
-
return this.addSplit(
|
|
70
|
+
return this.addSplit(newSplit);
|
|
67
71
|
}
|
|
68
72
|
return false;
|
|
69
73
|
}
|
|
@@ -76,8 +80,8 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
76
80
|
* Given a parsed split, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists).
|
|
77
81
|
* This util is intended to simplify the implementation of `splitsCache::usesSegments` method
|
|
78
82
|
*/
|
|
79
|
-
export function usesSegments(
|
|
80
|
-
const conditions =
|
|
83
|
+
export function usesSegments(ruleEntity: ISplit | IRBSegment) {
|
|
84
|
+
const conditions = ruleEntity.conditions || [];
|
|
81
85
|
for (let i = 0; i < conditions.length; i++) {
|
|
82
86
|
const matchers = conditions[i].matcherGroup.matchers;
|
|
83
87
|
|
|
@@ -87,5 +91,8 @@ export function usesSegments(split: ISplit) {
|
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
|
|
94
|
+
const excluded = (ruleEntity as IRBSegment).excluded;
|
|
95
|
+
if (excluded && excluded.segments && excluded.segments.length > 0) return true;
|
|
96
|
+
|
|
90
97
|
return false;
|
|
91
98
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ISettings } from '../types';
|
|
2
|
-
import { startsWith } from '../utils/lang';
|
|
3
2
|
import { hash } from '../utils/murmur3/murmur3';
|
|
4
3
|
|
|
5
4
|
const everythingAtTheEnd = /[^.]+$/;
|
|
@@ -34,22 +33,20 @@ export class KeyBuilder {
|
|
|
34
33
|
return `${this.prefix}.splits.till`;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// }
|
|
36
|
+
buildSplitKeyPrefix() {
|
|
37
|
+
return `${this.prefix}.split.`;
|
|
38
|
+
}
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
return
|
|
40
|
+
buildRBSegmentKey(rbsegmentName: string) {
|
|
41
|
+
return `${this.prefix}.rbsegment.${rbsegmentName}`;
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
return `${this.prefix}.
|
|
44
|
+
buildRBSegmentsTillKey() {
|
|
45
|
+
return `${this.prefix}.rbsegments.till`;
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return `${this.prefix}.splits.usingSegments`;
|
|
48
|
+
buildRBSegmentKeyPrefix() {
|
|
49
|
+
return `${this.prefix}.rbsegment.`;
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
buildSegmentNameKey(segmentName: string) {
|
|
@@ -60,11 +57,6 @@ export class KeyBuilder {
|
|
|
60
57
|
return `${this.prefix}.segment.${segmentName}.till`;
|
|
61
58
|
}
|
|
62
59
|
|
|
63
|
-
// NOT USED
|
|
64
|
-
// buildSegmentsReady() {
|
|
65
|
-
// return `${this.prefix}.segments.ready`;
|
|
66
|
-
// }
|
|
67
|
-
|
|
68
60
|
extractKey(builtKey: string) {
|
|
69
61
|
const s = builtKey.match(everythingAtTheEnd);
|
|
70
62
|
|
|
@@ -15,7 +15,7 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
|
|
|
15
15
|
constructor(prefix: string, matchingKey: string) {
|
|
16
16
|
super(prefix);
|
|
17
17
|
this.matchingKey = matchingKey;
|
|
18
|
-
this.regexSplitsCacheKey = new RegExp(`^${prefix}\\.(splits?|trafficType|flagSet)\\.`);
|
|
18
|
+
this.regexSplitsCacheKey = new RegExp(`^${prefix}\\.(splits?|trafficType|flagSet|rbsegment)\\.`);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -28,8 +28,7 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
|
|
|
28
28
|
extractSegmentName(builtSegmentKeyName: string) {
|
|
29
29
|
const prefix = `${this.prefix}.${this.matchingKey}.segment.`;
|
|
30
30
|
|
|
31
|
-
if (startsWith(builtSegmentKeyName, prefix))
|
|
32
|
-
return builtSegmentKeyName.substr(prefix.length);
|
|
31
|
+
if (startsWith(builtSegmentKeyName, prefix)) return builtSegmentKeyName.slice(prefix.length);
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
buildLastUpdatedKey() {
|
|
@@ -44,8 +43,16 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
|
|
|
44
43
|
return `${this.prefix}.${this.matchingKey}.segments.till`;
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
return `${this.prefix}.
|
|
46
|
+
isSplitKey(key: string) {
|
|
47
|
+
return startsWith(key, `${this.prefix}.split.`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
isRBSegmentKey(key: string) {
|
|
51
|
+
return startsWith(key, `${this.prefix}.rbsegment.`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
buildSplitsWithSegmentCountKey() {
|
|
55
|
+
return `${this.prefix}.splits.usingSegments`;
|
|
49
56
|
}
|
|
50
57
|
}
|
|
51
58
|
|
|
@@ -58,7 +65,7 @@ export function myLargeSegmentsKeyBuilder(prefix: string, matchingKey: string):
|
|
|
58
65
|
extractSegmentName(builtSegmentKeyName: string) {
|
|
59
66
|
const p = `${prefix}.${matchingKey}.largeSegment.`;
|
|
60
67
|
|
|
61
|
-
if (startsWith(builtSegmentKeyName, p)) return builtSegmentKeyName.
|
|
68
|
+
if (startsWith(builtSegmentKeyName, p)) return builtSegmentKeyName.slice(p.length);
|
|
62
69
|
},
|
|
63
70
|
|
|
64
71
|
buildTillKey() {
|
|
@@ -53,6 +53,10 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
53
53
|
return `${this.buildSplitKeyPrefix()}*`;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
searchPatternForRBSegmentKeys() {
|
|
57
|
+
return `${this.buildRBSegmentKeyPrefix()}*`;
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
/* Telemetry keys */
|
|
57
61
|
|
|
58
62
|
buildLatencyKey(method: Method, bucket: number) {
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { PreloadedData } from '../types';
|
|
2
|
+
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../utils/constants/browser';
|
|
2
3
|
import { DataLoader, ISegmentsCacheSync, ISplitsCacheSync } from './types';
|
|
3
4
|
|
|
4
|
-
// This value might be eventually set via a config parameter
|
|
5
|
-
const DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days
|
|
6
|
-
|
|
7
5
|
/**
|
|
8
6
|
* Factory of client-side storage loader
|
|
9
7
|
*
|
|
@@ -37,10 +35,9 @@ export function dataLoaderFactory(preloadedData: PreloadedData): DataLoader {
|
|
|
37
35
|
|
|
38
36
|
// cleaning up the localStorage data, since some cached splits might need be part of the preloaded data
|
|
39
37
|
storage.splits.clear();
|
|
40
|
-
storage.splits.setChangeNumber(since);
|
|
41
38
|
|
|
42
39
|
// splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data
|
|
43
|
-
storage.splits.
|
|
40
|
+
storage.splits.update(Object.keys(splitsData).map(splitName => JSON.parse(splitsData[splitName])), [], since);
|
|
44
41
|
|
|
45
42
|
// add mySegments data
|
|
46
43
|
let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { IRBSegment } from '../../dtos/types';
|
|
2
|
+
import { ILogger } from '../../logger/types';
|
|
3
|
+
import { ISettings } from '../../types';
|
|
4
|
+
import { isFiniteNumber, isNaNNumber, toNumber } from '../../utils/lang';
|
|
5
|
+
import { setToArray } from '../../utils/lang/sets';
|
|
6
|
+
import { usesSegments } from '../AbstractSplitsCacheSync';
|
|
7
|
+
import { KeyBuilderCS } from '../KeyBuilderCS';
|
|
8
|
+
import { IRBSegmentsCacheSync } from '../types';
|
|
9
|
+
import { LOG_PREFIX } from './constants';
|
|
10
|
+
|
|
11
|
+
export class RBSegmentsCacheInLocal implements IRBSegmentsCacheSync {
|
|
12
|
+
|
|
13
|
+
private readonly keys: KeyBuilderCS;
|
|
14
|
+
private readonly log: ILogger;
|
|
15
|
+
|
|
16
|
+
constructor(settings: ISettings, keys: KeyBuilderCS) {
|
|
17
|
+
this.keys = keys;
|
|
18
|
+
this.log = settings.log;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
clear() {
|
|
22
|
+
this.getNames().forEach(name => this.remove(name));
|
|
23
|
+
localStorage.removeItem(this.keys.buildRBSegmentsTillKey());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): boolean {
|
|
27
|
+
this.setChangeNumber(changeNumber);
|
|
28
|
+
const updated = toAdd.map(toAdd => this.add(toAdd)).some(result => result);
|
|
29
|
+
return toRemove.map(toRemove => this.remove(toRemove.name)).some(result => result) || updated;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private setChangeNumber(changeNumber: number) {
|
|
33
|
+
try {
|
|
34
|
+
localStorage.setItem(this.keys.buildRBSegmentsTillKey(), changeNumber + '');
|
|
35
|
+
localStorage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
|
|
36
|
+
} catch (e) {
|
|
37
|
+
this.log.error(LOG_PREFIX + e);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private updateSegmentCount(diff: number) {
|
|
42
|
+
const segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
43
|
+
const count = toNumber(localStorage.getItem(segmentsCountKey)) + diff;
|
|
44
|
+
// @ts-expect-error
|
|
45
|
+
if (count > 0) localStorage.setItem(segmentsCountKey, count);
|
|
46
|
+
else localStorage.removeItem(segmentsCountKey);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private add(rbSegment: IRBSegment): boolean {
|
|
50
|
+
try {
|
|
51
|
+
const name = rbSegment.name;
|
|
52
|
+
const rbSegmentKey = this.keys.buildRBSegmentKey(name);
|
|
53
|
+
const rbSegmentFromLocalStorage = localStorage.getItem(rbSegmentKey);
|
|
54
|
+
const previous = rbSegmentFromLocalStorage ? JSON.parse(rbSegmentFromLocalStorage) : null;
|
|
55
|
+
|
|
56
|
+
localStorage.setItem(rbSegmentKey, JSON.stringify(rbSegment));
|
|
57
|
+
|
|
58
|
+
let usesSegmentsDiff = 0;
|
|
59
|
+
if (previous && usesSegments(previous)) usesSegmentsDiff--;
|
|
60
|
+
if (usesSegments(rbSegment)) usesSegmentsDiff++;
|
|
61
|
+
if (usesSegmentsDiff !== 0) this.updateSegmentCount(usesSegmentsDiff);
|
|
62
|
+
|
|
63
|
+
return true;
|
|
64
|
+
} catch (e) {
|
|
65
|
+
this.log.error(LOG_PREFIX + e);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private remove(name: string): boolean {
|
|
71
|
+
try {
|
|
72
|
+
const rbSegment = this.get(name);
|
|
73
|
+
if (!rbSegment) return false;
|
|
74
|
+
|
|
75
|
+
localStorage.removeItem(this.keys.buildRBSegmentKey(name));
|
|
76
|
+
|
|
77
|
+
if (usesSegments(rbSegment)) this.updateSegmentCount(-1);
|
|
78
|
+
|
|
79
|
+
return true;
|
|
80
|
+
} catch (e) {
|
|
81
|
+
this.log.error(LOG_PREFIX + e);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private getNames(): string[] {
|
|
87
|
+
const len = localStorage.length;
|
|
88
|
+
const accum = [];
|
|
89
|
+
|
|
90
|
+
let cur = 0;
|
|
91
|
+
|
|
92
|
+
while (cur < len) {
|
|
93
|
+
const key = localStorage.key(cur);
|
|
94
|
+
|
|
95
|
+
if (key != null && this.keys.isRBSegmentKey(key)) accum.push(this.keys.extractKey(key));
|
|
96
|
+
|
|
97
|
+
cur++;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return accum;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get(name: string): IRBSegment | null {
|
|
104
|
+
const item = localStorage.getItem(this.keys.buildRBSegmentKey(name));
|
|
105
|
+
return item && JSON.parse(item);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
contains(names: Set<string>): boolean {
|
|
109
|
+
const namesArray = setToArray(names);
|
|
110
|
+
const namesInStorage = this.getNames();
|
|
111
|
+
return namesArray.every(name => namesInStorage.indexOf(name) !== -1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getChangeNumber(): number {
|
|
115
|
+
const n = -1;
|
|
116
|
+
let value: string | number | null = localStorage.getItem(this.keys.buildRBSegmentsTillKey());
|
|
117
|
+
|
|
118
|
+
if (value !== null) {
|
|
119
|
+
value = parseInt(value, 10);
|
|
120
|
+
|
|
121
|
+
return isNaNNumber(value) ? n : value;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return n;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
usesSegments(): boolean {
|
|
128
|
+
const storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
|
|
129
|
+
const splitsWithSegmentsCount = storedCount === null ? 0 : toNumber(storedCount);
|
|
130
|
+
|
|
131
|
+
return isFiniteNumber(splitsWithSegmentsCount) ?
|
|
132
|
+
splitsWithSegmentsCount > 0 :
|
|
133
|
+
true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
}
|
|
@@ -5,6 +5,7 @@ import { KeyBuilderCS } from '../KeyBuilderCS';
|
|
|
5
5
|
import { ILogger } from '../../logger/types';
|
|
6
6
|
import { LOG_PREFIX } from './constants';
|
|
7
7
|
import { ISettings } from '../../types';
|
|
8
|
+
import { getStorageHash } from '../KeyBuilder';
|
|
8
9
|
import { setToArray } from '../../utils/lang/sets';
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -14,14 +15,21 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
14
15
|
|
|
15
16
|
private readonly keys: KeyBuilderCS;
|
|
16
17
|
private readonly log: ILogger;
|
|
18
|
+
private readonly storageHash: string;
|
|
17
19
|
private readonly flagSetsFilter: string[];
|
|
18
20
|
private hasSync?: boolean;
|
|
21
|
+
private updateNewFilter?: boolean;
|
|
19
22
|
|
|
20
|
-
constructor(settings: ISettings, keys: KeyBuilderCS) {
|
|
23
|
+
constructor(settings: ISettings, keys: KeyBuilderCS, expirationTimestamp?: number) {
|
|
21
24
|
super();
|
|
22
25
|
this.keys = keys;
|
|
23
26
|
this.log = settings.log;
|
|
27
|
+
this.storageHash = getStorageHash(settings);
|
|
24
28
|
this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
|
|
29
|
+
|
|
30
|
+
this._checkExpiration(expirationTimestamp);
|
|
31
|
+
|
|
32
|
+
this._checkFilterQuery();
|
|
25
33
|
}
|
|
26
34
|
|
|
27
35
|
private _decrementCount(key: string) {
|
|
@@ -49,16 +57,14 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
49
57
|
|
|
50
58
|
private _incrementCounts(split: ISplit) {
|
|
51
59
|
try {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
|
|
60
|
+
const ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
61
|
+
// @ts-expect-error
|
|
62
|
+
localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
64
|
+
if (usesSegments(split)) {
|
|
65
|
+
const segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
66
|
+
// @ts-expect-error
|
|
67
|
+
localStorage.setItem(segmentsCountKey, toNumber(localStorage.getItem(segmentsCountKey)) + 1);
|
|
62
68
|
}
|
|
63
69
|
} catch (e) {
|
|
64
70
|
this.log.error(LOG_PREFIX + e);
|
|
@@ -71,6 +77,8 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
71
77
|
* We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
|
|
72
78
|
*/
|
|
73
79
|
clear() {
|
|
80
|
+
this.log.info(LOG_PREFIX + 'Flushing Splits data from localStorage');
|
|
81
|
+
|
|
74
82
|
// collect item keys
|
|
75
83
|
const len = localStorage.length;
|
|
76
84
|
const accum = [];
|
|
@@ -86,8 +94,9 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
86
94
|
this.hasSync = false;
|
|
87
95
|
}
|
|
88
96
|
|
|
89
|
-
addSplit(
|
|
97
|
+
addSplit(split: ISplit) {
|
|
90
98
|
try {
|
|
99
|
+
const name = split.name;
|
|
91
100
|
const splitKey = this.keys.buildSplitKey(name);
|
|
92
101
|
const splitFromLocalStorage = localStorage.getItem(splitKey);
|
|
93
102
|
const previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
|
|
@@ -110,6 +119,8 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
110
119
|
removeSplit(name: string): boolean {
|
|
111
120
|
try {
|
|
112
121
|
const split = this.getSplit(name);
|
|
122
|
+
if (!split) return false;
|
|
123
|
+
|
|
113
124
|
localStorage.removeItem(this.keys.buildSplitKey(name));
|
|
114
125
|
|
|
115
126
|
this._decrementCounts(split);
|
|
@@ -122,12 +133,25 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
122
133
|
}
|
|
123
134
|
}
|
|
124
135
|
|
|
125
|
-
getSplit(name: string) {
|
|
136
|
+
getSplit(name: string): ISplit | null {
|
|
126
137
|
const item = localStorage.getItem(this.keys.buildSplitKey(name));
|
|
127
138
|
return item && JSON.parse(item);
|
|
128
139
|
}
|
|
129
140
|
|
|
130
141
|
setChangeNumber(changeNumber: number): boolean {
|
|
142
|
+
|
|
143
|
+
// when using a new split query, we must update it at the store
|
|
144
|
+
if (this.updateNewFilter) {
|
|
145
|
+
this.log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
|
|
146
|
+
const storageHashKey = this.keys.buildHashKey();
|
|
147
|
+
try {
|
|
148
|
+
localStorage.setItem(storageHashKey, this.storageHash);
|
|
149
|
+
} catch (e) {
|
|
150
|
+
this.log.error(LOG_PREFIX + e);
|
|
151
|
+
}
|
|
152
|
+
this.updateNewFilter = false;
|
|
153
|
+
}
|
|
154
|
+
|
|
131
155
|
try {
|
|
132
156
|
localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
|
|
133
157
|
// update "last updated" timestamp with current time
|
|
@@ -182,11 +206,51 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
182
206
|
const storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
|
|
183
207
|
const splitsWithSegmentsCount = storedCount === null ? 0 : toNumber(storedCount);
|
|
184
208
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
209
|
+
return isFiniteNumber(splitsWithSegmentsCount) ?
|
|
210
|
+
splitsWithSegmentsCount > 0 :
|
|
211
|
+
true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Check if the splits information is already stored in browser LocalStorage.
|
|
216
|
+
* In this function we could add more code to check if the data is valid.
|
|
217
|
+
* @override
|
|
218
|
+
*/
|
|
219
|
+
checkCache(): boolean {
|
|
220
|
+
return this.getChangeNumber() > -1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Clean Splits cache if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
|
|
225
|
+
*
|
|
226
|
+
* @param expirationTimestamp - if the value is not a number, data will not be cleaned
|
|
227
|
+
*/
|
|
228
|
+
private _checkExpiration(expirationTimestamp?: number) {
|
|
229
|
+
let value: string | number | null = localStorage.getItem(this.keys.buildLastUpdatedKey());
|
|
230
|
+
if (value !== null) {
|
|
231
|
+
value = parseInt(value, 10);
|
|
232
|
+
if (!isNaNNumber(value) && expirationTimestamp && value < expirationTimestamp) this.clear();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// @TODO eventually remove `_checkFilterQuery`. Cache should be cleared at the storage level, reusing same logic than PluggableStorage
|
|
237
|
+
private _checkFilterQuery() {
|
|
238
|
+
const storageHashKey = this.keys.buildHashKey();
|
|
239
|
+
const storageHash = localStorage.getItem(storageHashKey);
|
|
240
|
+
|
|
241
|
+
if (storageHash !== this.storageHash) {
|
|
242
|
+
try {
|
|
243
|
+
// mark cache to update the new query filter on first successful splits fetch
|
|
244
|
+
this.updateNewFilter = true;
|
|
245
|
+
|
|
246
|
+
// if there is cache, clear it
|
|
247
|
+
if (this.checkCache()) this.clear();
|
|
248
|
+
|
|
249
|
+
} catch (e) {
|
|
250
|
+
this.log.error(LOG_PREFIX + e);
|
|
251
|
+
}
|
|
189
252
|
}
|
|
253
|
+
// if the filter didn't change, nothing is done
|
|
190
254
|
}
|
|
191
255
|
|
|
192
256
|
getNamesByFlagSets(flagSets: string[]): Set<string>[] {
|
|
@@ -7,19 +7,23 @@ import { KeyBuilderCS, myLargeSegmentsKeyBuilder } from '../KeyBuilderCS';
|
|
|
7
7
|
import { isLocalStorageAvailable } from '../../utils/env/isLocalStorageAvailable';
|
|
8
8
|
import { SplitsCacheInLocal } from './SplitsCacheInLocal';
|
|
9
9
|
import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
|
|
10
|
+
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
|
|
10
11
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
11
12
|
import { LOG_PREFIX } from './constants';
|
|
12
13
|
import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
13
14
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
14
15
|
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
15
16
|
import { getMatching } from '../../utils/key';
|
|
16
|
-
import {
|
|
17
|
-
|
|
17
|
+
import { RBSegmentsCacheInLocal } from './RBSegmentsCacheInLocal';
|
|
18
|
+
|
|
19
|
+
export interface InLocalStorageOptions {
|
|
20
|
+
prefix?: string
|
|
21
|
+
}
|
|
18
22
|
|
|
19
23
|
/**
|
|
20
24
|
* InLocal storage factory for standalone client-side SplitFactory
|
|
21
25
|
*/
|
|
22
|
-
export function InLocalStorage(options:
|
|
26
|
+
export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyncFactory {
|
|
23
27
|
|
|
24
28
|
const prefix = validatePrefix(options.prefix);
|
|
25
29
|
|
|
@@ -34,13 +38,16 @@ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): ISt
|
|
|
34
38
|
const { settings, settings: { log, scheduler: { impressionsQueueSize, eventsQueueSize } } } = params;
|
|
35
39
|
const matchingKey = getMatching(settings.core.key);
|
|
36
40
|
const keys = new KeyBuilderCS(prefix, matchingKey);
|
|
41
|
+
const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
|
|
37
42
|
|
|
38
|
-
const splits = new SplitsCacheInLocal(settings, keys);
|
|
43
|
+
const splits = new SplitsCacheInLocal(settings, keys, expirationTimestamp);
|
|
44
|
+
const rbSegments = new RBSegmentsCacheInLocal(settings, keys);
|
|
39
45
|
const segments = new MySegmentsCacheInLocal(log, keys);
|
|
40
46
|
const largeSegments = new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey));
|
|
41
47
|
|
|
42
48
|
return {
|
|
43
49
|
splits,
|
|
50
|
+
rbSegments,
|
|
44
51
|
segments,
|
|
45
52
|
largeSegments,
|
|
46
53
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
@@ -49,10 +56,6 @@ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): ISt
|
|
|
49
56
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
50
57
|
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
51
58
|
|
|
52
|
-
validateCache() {
|
|
53
|
-
return validateCache(options, settings, keys, splits, segments, largeSegments);
|
|
54
|
-
},
|
|
55
|
-
|
|
56
59
|
destroy() { },
|
|
57
60
|
|
|
58
61
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
|
|
@@ -60,6 +63,7 @@ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): ISt
|
|
|
60
63
|
|
|
61
64
|
return {
|
|
62
65
|
splits: this.splits,
|
|
66
|
+
rbSegments: this.rbSegments,
|
|
63
67
|
segments: new MySegmentsCacheInLocal(log, new KeyBuilderCS(prefix, matchingKey)),
|
|
64
68
|
largeSegments: new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey)),
|
|
65
69
|
impressions: this.impressions,
|
|
@@ -7,6 +7,7 @@ import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
|
7
7
|
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
9
|
import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
10
|
+
import { RBSegmentsCacheInMemory } from './RBSegmentsCacheInMemory';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
@@ -17,10 +18,12 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
|
|
|
17
18
|
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { __splitFiltersValidation } } } = params;
|
|
18
19
|
|
|
19
20
|
const splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
21
|
+
const rbSegments = new RBSegmentsCacheInMemory();
|
|
20
22
|
const segments = new SegmentsCacheInMemory();
|
|
21
23
|
|
|
22
24
|
const storage = {
|
|
23
25
|
splits,
|
|
26
|
+
rbSegments,
|
|
24
27
|
segments,
|
|
25
28
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
26
29
|
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
@@ -7,6 +7,7 @@ import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
|
7
7
|
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
9
|
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
10
|
+
import { RBSegmentsCacheInMemory } from './RBSegmentsCacheInMemory';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
@@ -17,11 +18,13 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
17
18
|
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize }, sync: { __splitFiltersValidation } } } = params;
|
|
18
19
|
|
|
19
20
|
const splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
21
|
+
const rbSegments = new RBSegmentsCacheInMemory();
|
|
20
22
|
const segments = new MySegmentsCacheInMemory();
|
|
21
23
|
const largeSegments = new MySegmentsCacheInMemory();
|
|
22
24
|
|
|
23
25
|
const storage = {
|
|
24
26
|
splits,
|
|
27
|
+
rbSegments,
|
|
25
28
|
segments,
|
|
26
29
|
largeSegments,
|
|
27
30
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
@@ -36,6 +39,7 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
36
39
|
shared() {
|
|
37
40
|
return {
|
|
38
41
|
splits: this.splits,
|
|
42
|
+
rbSegments: this.rbSegments,
|
|
39
43
|
segments: new MySegmentsCacheInMemory(),
|
|
40
44
|
largeSegments: new MySegmentsCacheInMemory(),
|
|
41
45
|
impressions: this.impressions,
|