Skip to content

Commit 6e7d790

Browse files
Merge pull request #389 from splitio/refactor_splits_cache_update_method
Refactor splits cache: replace `add/removeSplits` with `update` method
2 parents af3ef14 + 8377736 commit 6e7d790

25 files changed

+377
-471
lines changed

src/logger/constants.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ export const RETRIEVE_CLIENT_EXISTING = 28;
2020
export const RETRIEVE_MANAGER = 29;
2121
export const SYNC_OFFLINE_DATA = 30;
2222
export const SYNC_SPLITS_FETCH = 31;
23-
export const SYNC_SPLITS_NEW = 32;
24-
export const SYNC_SPLITS_REMOVED = 33;
25-
export const SYNC_SPLITS_SEGMENTS = 34;
23+
export const SYNC_SPLITS_UPDATE = 32;
2624
export const STREAMING_NEW_MESSAGE = 35;
2725
export const SYNC_TASK_START = 36;
2826
export const SYNC_TASK_EXECUTE = 37;

src/logger/messages/debug.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ export const codesDebug: [number, string][] = codesInfo.concat([
2121
// synchronizer
2222
[c.SYNC_OFFLINE_DATA, c.LOG_PREFIX_SYNC_OFFLINE + 'Feature flags data: \n%s'],
2323
[c.SYNC_SPLITS_FETCH, c.LOG_PREFIX_SYNC_SPLITS + 'Spin up feature flags update using since = %s'],
24-
[c.SYNC_SPLITS_NEW, c.LOG_PREFIX_SYNC_SPLITS + 'New feature flags %s'],
25-
[c.SYNC_SPLITS_REMOVED, c.LOG_PREFIX_SYNC_SPLITS + 'Removed feature flags %s'],
26-
[c.SYNC_SPLITS_SEGMENTS, c.LOG_PREFIX_SYNC_SPLITS + 'Segment names collected %s'],
24+
[c.SYNC_SPLITS_UPDATE, c.LOG_PREFIX_SYNC_SPLITS + 'New feature flags %s. Removed feature flags %s. Segment names collected %s'],
2725
[c.STREAMING_NEW_MESSAGE, c.LOG_PREFIX_SYNC_STREAMING + 'New SSE message received, with data: %s.'],
2826
[c.SYNC_TASK_START, c.LOG_PREFIX_SYNC + ': Starting %s. Running each %s millis'],
2927
[c.SYNC_TASK_EXECUTE, c.LOG_PREFIX_SYNC + ': Running %s'],

src/sdkManager/__tests__/index.asyncCache.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('Manager with async cache', () => {
3333
const cache = new SplitsCacheInRedis(loggerMock, keys, connection);
3434
const manager = sdkManagerFactory({ mode: 'consumer', log: loggerMock }, cache, sdkReadinessManagerMock);
3535
await cache.clear();
36-
await cache.addSplit(splitObject.name, splitObject as any);
36+
await cache.addSplit(splitObject as any);
3737

3838
/** List all splits */
3939
const views = await manager.splits();

src/sdkManager/__tests__/index.syncCache.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe('Manager with sync cache (In Memory)', () => {
1919
/** Setup: create manager */
2020
const cache = new SplitsCacheInMemory();
2121
const manager = sdkManagerFactory({ mode: 'standalone', log: loggerMock }, cache, sdkReadinessManagerMock);
22-
cache.addSplit(splitObject.name, splitObject as any);
22+
cache.addSplit(splitObject as any);
2323

2424
test('List all splits', () => {
2525

src/storages/AbstractSplitsCacheAsync.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,22 @@ import { objectAssign } from '../utils/lang/objectAssign';
88
*/
99
export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
1010

11-
abstract addSplit(name: string, split: ISplit): Promise<boolean>
12-
abstract addSplits(entries: [string, ISplit][]): Promise<boolean[] | void>
13-
abstract removeSplits(names: string[]): Promise<boolean[] | void>
11+
protected abstract addSplit(split: ISplit): Promise<boolean>
12+
protected abstract removeSplit(name: string): Promise<boolean>
13+
protected abstract setChangeNumber(changeNumber: number): Promise<boolean | void>
14+
15+
update(toAdd: ISplit[], toRemove: ISplit[], changeNumber: number): Promise<boolean> {
16+
return Promise.all([
17+
this.setChangeNumber(changeNumber),
18+
Promise.all(toAdd.map(addedFF => this.addSplit(addedFF))),
19+
Promise.all(toRemove.map(removedFF => this.removeSplit(removedFF.name)))
20+
]).then(([, added, removed]) => {
21+
return added.some(result => result) || removed.some(result => result);
22+
});
23+
}
24+
1425
abstract getSplit(name: string): Promise<ISplit | null>
1526
abstract getSplits(names: string[]): Promise<Record<string, ISplit | null>>
16-
abstract setChangeNumber(changeNumber: number): Promise<boolean | void>
1727
abstract getChangeNumber(): Promise<number>
1828
abstract getAll(): Promise<ISplit[]>
1929
abstract getSplitNames(): Promise<string[]>
@@ -52,7 +62,7 @@ export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
5262
newSplit.defaultTreatment = defaultTreatment;
5363
newSplit.changeNumber = changeNumber;
5464

55-
return this.addSplit(name, newSplit);
65+
return this.addSplit(newSplit);
5666
}
5767
return false;
5868
}).catch(() => false);

src/storages/AbstractSplitsCacheSync.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
99
*/
1010
export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
1111

12-
abstract addSplit(name: string, split: ISplit): boolean
13-
14-
addSplits(entries: [string, ISplit][]): boolean[] {
15-
return entries.map(keyValuePair => this.addSplit(keyValuePair[0], keyValuePair[1]));
16-
}
17-
18-
abstract removeSplit(name: string): boolean
19-
20-
removeSplits(names: string[]): boolean[] {
21-
return names.map(name => this.removeSplit(name));
12+
protected abstract addSplit(split: ISplit): boolean
13+
protected abstract removeSplit(name: string): boolean
14+
protected abstract setChangeNumber(changeNumber: number): boolean | void
15+
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;
2220
}
2321

2422
abstract getSplit(name: string): ISplit | null
@@ -31,8 +29,6 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
3129
return splits;
3230
}
3331

34-
abstract setChangeNumber(changeNumber: number): boolean | void
35-
3632
abstract getChangeNumber(): number
3733

3834
getAll(): ISplit[] {
@@ -71,7 +67,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
7167
newSplit.defaultTreatment = defaultTreatment;
7268
newSplit.changeNumber = changeNumber;
7369

74-
return this.addSplit(name, newSplit);
70+
return this.addSplit(newSplit);
7571
}
7672
return false;
7773
}

src/storages/KeyBuilder.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ISettings } from '../types';
2-
import { startsWith } from '../utils/lang';
32
import { hash } from '../utils/murmur3/murmur3';
43

54
const everythingAtTheEnd = /[^.]+$/;
@@ -34,24 +33,10 @@ export class KeyBuilder {
3433
return `${this.prefix}.splits.till`;
3534
}
3635

37-
// NOT USED
38-
// buildSplitsReady() {
39-
// return `${this.prefix}.splits.ready`;
40-
// }
41-
42-
isSplitKey(key: string) {
43-
return startsWith(key, `${this.prefix}.split.`);
44-
}
45-
4636
buildSplitKeyPrefix() {
4737
return `${this.prefix}.split.`;
4838
}
4939

50-
// Only used by InLocalStorage.
51-
buildSplitsWithSegmentCountKey() {
52-
return `${this.prefix}.splits.usingSegments`;
53-
}
54-
5540
buildSegmentNameKey(segmentName: string) {
5641
return `${this.prefix}.segment.${segmentName}`;
5742
}
@@ -60,11 +45,6 @@ export class KeyBuilder {
6045
return `${this.prefix}.segment.${segmentName}.till`;
6146
}
6247

63-
// NOT USED
64-
// buildSegmentsReady() {
65-
// return `${this.prefix}.segments.ready`;
66-
// }
67-
6848
extractKey(builtKey: string) {
6949
const s = builtKey.match(everythingAtTheEnd);
7050

src/storages/KeyBuilderCS.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
2828
extractSegmentName(builtSegmentKeyName: string) {
2929
const prefix = `${this.prefix}.${this.matchingKey}.segment.`;
3030

31-
if (startsWith(builtSegmentKeyName, prefix))
32-
return builtSegmentKeyName.substr(prefix.length);
31+
if (startsWith(builtSegmentKeyName, prefix)) return builtSegmentKeyName.slice(prefix.length);
3332
}
3433

3534
buildLastUpdatedKey() {
@@ -43,6 +42,14 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
4342
buildTillKey() {
4443
return `${this.prefix}.${this.matchingKey}.segments.till`;
4544
}
45+
46+
isSplitKey(key: string) {
47+
return startsWith(key, `${this.prefix}.split.`);
48+
}
49+
50+
buildSplitsWithSegmentCountKey() {
51+
return `${this.prefix}.splits.usingSegments`;
52+
}
4653
}
4754

4855
export function myLargeSegmentsKeyBuilder(prefix: string, matchingKey: string): MySegmentsKeyBuilder {
@@ -54,7 +61,7 @@ export function myLargeSegmentsKeyBuilder(prefix: string, matchingKey: string):
5461
extractSegmentName(builtSegmentKeyName: string) {
5562
const p = `${prefix}.${matchingKey}.largeSegment.`;
5663

57-
if (startsWith(builtSegmentKeyName, p)) return builtSegmentKeyName.substr(p.length);
64+
if (startsWith(builtSegmentKeyName, p)) return builtSegmentKeyName.slice(p.length);
5865
},
5966

6067
buildTillKey() {

src/storages/__tests__/KeyBuilder.spec.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,9 @@ test('KEYS / splits keys', () => {
99
const expectedKey = `SPLITIO.split.${splitName}`;
1010
const expectedTill = 'SPLITIO.splits.till';
1111

12-
expect(builder.isSplitKey(expectedKey)).toBe(true);
13-
expect(builder.buildSplitKey(splitName) === expectedKey).toBe(true);
14-
expect(builder.buildSplitsTillKey() === expectedTill).toBe(true);
15-
expect(builder.extractKey(builder.buildSplitKey(splitName)) === splitName).toBe(true);
16-
17-
// NOT USED
18-
// const expectedReady = 'SPLITIO.splits.ready';
19-
// expect(builder.buildSplitsReady() === expectedReady).toBe(true);
12+
expect(builder.buildSplitKey(splitName)).toBe(expectedKey);
13+
expect(builder.buildSplitsTillKey()).toBe(expectedTill);
14+
expect(builder.extractKey(builder.buildSplitKey(splitName))).toBe(splitName);
2015
});
2116

2217
test('KEYS / splits keys with custom prefix', () => {
@@ -27,13 +22,8 @@ test('KEYS / splits keys with custom prefix', () => {
2722
const expectedKey = `${prefix}.split.${splitName}`;
2823
const expectedTill = `${prefix}.splits.till`;
2924

30-
expect(builder.isSplitKey(expectedKey)).toBe(true);
3125
expect(builder.buildSplitKey(splitName)).toBe(expectedKey);
3226
expect(builder.buildSplitsTillKey() === expectedTill).toBe(true);
33-
34-
// NOT USED
35-
// const expectedReady = `${prefix}.SPLITIO.splits.ready`;
36-
// expect(builder.buildSplitsReady() === expectedReady).toBe(true);
3727
});
3828

3929
const prefix = 'SPLITIO';

src/storages/__tests__/testUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ export function assertSyncRecorderCacheInterface(cache: IEventsCacheSync | IImpr
2323
// Split mocks
2424

2525
//@ts-ignore
26-
export const splitWithUserTT: ISplit = { trafficTypeName: 'user_tt', conditions: [] };
26+
export const splitWithUserTT: ISplit = { name: 'user_ff', trafficTypeName: 'user_tt', conditions: [] };
2727
//@ts-ignore
28-
export const splitWithAccountTT: ISplit = { trafficTypeName: 'account_tt', conditions: [] };
28+
export const splitWithAccountTT: ISplit = { name: 'account_ff', trafficTypeName: 'account_tt', conditions: [] };
2929
//@ts-ignore
3030
export const splitWithAccountTTAndUsesSegments: ISplit = { trafficTypeName: 'account_tt', conditions: [{ matcherGroup: { matchers: [{ matcherType: 'IN_SEGMENT', userDefinedSegmentMatcherData: { segmentName: 'employees' } }] } }] };
3131
//@ts-ignore

0 commit comments

Comments
 (0)