Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/logger/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ export const RETRIEVE_CLIENT_EXISTING = 28;
export const RETRIEVE_MANAGER = 29;
export const SYNC_OFFLINE_DATA = 30;
export const SYNC_SPLITS_FETCH = 31;
export const SYNC_SPLITS_NEW = 32;
export const SYNC_SPLITS_REMOVED = 33;
export const SYNC_SPLITS_SEGMENTS = 34;
export const SYNC_SPLITS_UPDATE = 32;
export const STREAMING_NEW_MESSAGE = 35;
export const SYNC_TASK_START = 36;
export const SYNC_TASK_EXECUTE = 37;
Expand Down
4 changes: 1 addition & 3 deletions src/logger/messages/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ export const codesDebug: [number, string][] = codesInfo.concat([
// synchronizer
[c.SYNC_OFFLINE_DATA, c.LOG_PREFIX_SYNC_OFFLINE + 'Feature flags data: \n%s'],
[c.SYNC_SPLITS_FETCH, c.LOG_PREFIX_SYNC_SPLITS + 'Spin up feature flags update using since = %s'],
[c.SYNC_SPLITS_NEW, c.LOG_PREFIX_SYNC_SPLITS + 'New feature flags %s'],
[c.SYNC_SPLITS_REMOVED, c.LOG_PREFIX_SYNC_SPLITS + 'Removed feature flags %s'],
[c.SYNC_SPLITS_SEGMENTS, c.LOG_PREFIX_SYNC_SPLITS + 'Segment names collected %s'],
[c.SYNC_SPLITS_UPDATE, c.LOG_PREFIX_SYNC_SPLITS + 'New feature flags %s. Removed feature flags %s. Segment names collected %s'],
[c.STREAMING_NEW_MESSAGE, c.LOG_PREFIX_SYNC_STREAMING + 'New SSE message received, with data: %s.'],
[c.SYNC_TASK_START, c.LOG_PREFIX_SYNC + ': Starting %s. Running each %s millis'],
[c.SYNC_TASK_EXECUTE, c.LOG_PREFIX_SYNC + ': Running %s'],
Expand Down
2 changes: 1 addition & 1 deletion src/sdkManager/__tests__/index.asyncCache.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('Manager with async cache', () => {
const cache = new SplitsCacheInRedis(loggerMock, keys, connection);
const manager = sdkManagerFactory({ mode: 'consumer', log: loggerMock }, cache, sdkReadinessManagerMock);
await cache.clear();
await cache.addSplit(splitObject.name, splitObject as any);
await cache.addSplit(splitObject as any);

/** List all splits */
const views = await manager.splits();
Expand Down
2 changes: 1 addition & 1 deletion src/sdkManager/__tests__/index.syncCache.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Manager with sync cache (In Memory)', () => {
/** Setup: create manager */
const cache = new SplitsCacheInMemory();
const manager = sdkManagerFactory({ mode: 'standalone', log: loggerMock }, cache, sdkReadinessManagerMock);
cache.addSplit(splitObject.name, splitObject as any);
cache.addSplit(splitObject as any);

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

Expand Down
20 changes: 15 additions & 5 deletions src/storages/AbstractSplitsCacheAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@ import { objectAssign } from '../utils/lang/objectAssign';
*/
export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {

abstract addSplit(name: string, split: ISplit): Promise<boolean>
abstract addSplits(entries: [string, ISplit][]): Promise<boolean[] | void>
abstract removeSplits(names: string[]): Promise<boolean[] | void>
protected abstract addSplit(split: ISplit): Promise<boolean>
protected abstract removeSplit(name: string): Promise<boolean>
protected abstract setChangeNumber(changeNumber: number): Promise<boolean | void>

update(toAdd: ISplit[], toRemove: ISplit[], changeNumber: number): Promise<boolean> {
return Promise.all([
this.setChangeNumber(changeNumber),
Promise.all(toAdd.map(addedFF => this.addSplit(addedFF))),
Promise.all(toRemove.map(removedFF => this.removeSplit(removedFF.name)))
]).then(([, added, removed]) => {
return added.some(result => result) || removed.some(result => result);
});
}

abstract getSplit(name: string): Promise<ISplit | null>
abstract getSplits(names: string[]): Promise<Record<string, ISplit | null>>
abstract setChangeNumber(changeNumber: number): Promise<boolean | void>
abstract getChangeNumber(): Promise<number>
abstract getAll(): Promise<ISplit[]>
abstract getSplitNames(): Promise<string[]>
Expand Down Expand Up @@ -52,7 +62,7 @@ export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
newSplit.defaultTreatment = defaultTreatment;
newSplit.changeNumber = changeNumber;

return this.addSplit(name, newSplit);
return this.addSplit(newSplit);
}
return false;
}).catch(() => false);
Expand Down
22 changes: 9 additions & 13 deletions src/storages/AbstractSplitsCacheSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
*/
export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {

abstract addSplit(name: string, split: ISplit): boolean

addSplits(entries: [string, ISplit][]): boolean[] {
return entries.map(keyValuePair => this.addSplit(keyValuePair[0], keyValuePair[1]));
}

abstract removeSplit(name: string): boolean

removeSplits(names: string[]): boolean[] {
return names.map(name => this.removeSplit(name));
protected abstract addSplit(split: ISplit): boolean
protected abstract removeSplit(name: string): boolean
protected abstract setChangeNumber(changeNumber: number): boolean | void

update(toAdd: ISplit[], toRemove: ISplit[], changeNumber: number): boolean {
this.setChangeNumber(changeNumber);
const updated = toAdd.map(addedFF => this.addSplit(addedFF)).some(result => result);
return toRemove.map(removedFF => this.removeSplit(removedFF.name)).some(result => result) || updated;
}

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

abstract setChangeNumber(changeNumber: number): boolean | void

abstract getChangeNumber(): number

getAll(): ISplit[] {
Expand Down Expand Up @@ -71,7 +67,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
newSplit.defaultTreatment = defaultTreatment;
newSplit.changeNumber = changeNumber;

return this.addSplit(name, newSplit);
return this.addSplit(newSplit);
}
return false;
}
Expand Down
20 changes: 0 additions & 20 deletions src/storages/KeyBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ISettings } from '../types';
import { startsWith } from '../utils/lang';
import { hash } from '../utils/murmur3/murmur3';

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

// NOT USED
// buildSplitsReady() {
// return `${this.prefix}.splits.ready`;
// }

isSplitKey(key: string) {
return startsWith(key, `${this.prefix}.split.`);
}

buildSplitKeyPrefix() {
return `${this.prefix}.split.`;
}

// Only used by InLocalStorage.
buildSplitsWithSegmentCountKey() {
return `${this.prefix}.splits.usingSegments`;
}

buildSegmentNameKey(segmentName: string) {
return `${this.prefix}.segment.${segmentName}`;
}
Expand All @@ -60,11 +45,6 @@ export class KeyBuilder {
return `${this.prefix}.segment.${segmentName}.till`;
}

// NOT USED
// buildSegmentsReady() {
// return `${this.prefix}.segments.ready`;
// }

extractKey(builtKey: string) {
const s = builtKey.match(everythingAtTheEnd);

Expand Down
13 changes: 10 additions & 3 deletions src/storages/KeyBuilderCS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
extractSegmentName(builtSegmentKeyName: string) {
const prefix = `${this.prefix}.${this.matchingKey}.segment.`;

if (startsWith(builtSegmentKeyName, prefix))
return builtSegmentKeyName.substr(prefix.length);
if (startsWith(builtSegmentKeyName, prefix)) return builtSegmentKeyName.slice(prefix.length);
}

buildLastUpdatedKey() {
Expand All @@ -43,6 +42,14 @@ export class KeyBuilderCS extends KeyBuilder implements MySegmentsKeyBuilder {
buildTillKey() {
return `${this.prefix}.${this.matchingKey}.segments.till`;
}

isSplitKey(key: string) {
return startsWith(key, `${this.prefix}.split.`);
}

buildSplitsWithSegmentCountKey() {
return `${this.prefix}.splits.usingSegments`;
}
}

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

if (startsWith(builtSegmentKeyName, p)) return builtSegmentKeyName.substr(p.length);
if (startsWith(builtSegmentKeyName, p)) return builtSegmentKeyName.slice(p.length);
},

buildTillKey() {
Expand Down
16 changes: 3 additions & 13 deletions src/storages/__tests__/KeyBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,9 @@ test('KEYS / splits keys', () => {
const expectedKey = `SPLITIO.split.${splitName}`;
const expectedTill = 'SPLITIO.splits.till';

expect(builder.isSplitKey(expectedKey)).toBe(true);
expect(builder.buildSplitKey(splitName) === expectedKey).toBe(true);
expect(builder.buildSplitsTillKey() === expectedTill).toBe(true);
expect(builder.extractKey(builder.buildSplitKey(splitName)) === splitName).toBe(true);

// NOT USED
// const expectedReady = 'SPLITIO.splits.ready';
// expect(builder.buildSplitsReady() === expectedReady).toBe(true);
expect(builder.buildSplitKey(splitName)).toBe(expectedKey);
expect(builder.buildSplitsTillKey()).toBe(expectedTill);
expect(builder.extractKey(builder.buildSplitKey(splitName))).toBe(splitName);
});

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

expect(builder.isSplitKey(expectedKey)).toBe(true);
expect(builder.buildSplitKey(splitName)).toBe(expectedKey);
expect(builder.buildSplitsTillKey() === expectedTill).toBe(true);

// NOT USED
// const expectedReady = `${prefix}.SPLITIO.splits.ready`;
// expect(builder.buildSplitsReady() === expectedReady).toBe(true);
});

const prefix = 'SPLITIO';
Expand Down
4 changes: 2 additions & 2 deletions src/storages/__tests__/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export function assertSyncRecorderCacheInterface(cache: IEventsCacheSync | IImpr
// Split mocks

//@ts-ignore
export const splitWithUserTT: ISplit = { trafficTypeName: 'user_tt', conditions: [] };
export const splitWithUserTT: ISplit = { name: 'user_ff', trafficTypeName: 'user_tt', conditions: [] };
//@ts-ignore
export const splitWithAccountTT: ISplit = { trafficTypeName: 'account_tt', conditions: [] };
export const splitWithAccountTT: ISplit = { name: 'account_ff', trafficTypeName: 'account_tt', conditions: [] };
//@ts-ignore
export const splitWithAccountTTAndUsesSegments: ISplit = { trafficTypeName: 'account_tt', conditions: [{ matcherGroup: { matchers: [{ matcherType: 'IN_SEGMENT', userDefinedSegmentMatcherData: { segmentName: 'employees' } }] } }] };
//@ts-ignore
Expand Down
3 changes: 1 addition & 2 deletions src/storages/dataLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ export function dataLoaderFactory(preloadedData: PreloadedData): DataLoader {

// cleaning up the localStorage data, since some cached splits might need be part of the preloaded data
storage.splits.clear();
storage.splits.setChangeNumber(since);

// splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data
storage.splits.addSplits(Object.keys(splitsData).map(splitName => JSON.parse(splitsData[splitName])));
storage.splits.update(Object.keys(splitsData).map(splitName => JSON.parse(splitsData[splitName])), [], since);

// add mySegments data
let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
Expand Down
7 changes: 5 additions & 2 deletions src/storages/inLocalStorage/SplitsCacheInLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
this.hasSync = false;
}

addSplit(name: string, split: ISplit) {
addSplit(split: ISplit) {
try {
const name = split.name;
const splitKey = this.keys.buildSplitKey(name);
const splitFromLocalStorage = localStorage.getItem(splitKey);
const previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
Expand All @@ -120,6 +121,8 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
removeSplit(name: string): boolean {
try {
const split = this.getSplit(name);
if (!split) return false;

localStorage.removeItem(this.keys.buildSplitKey(name));

this._decrementCounts(split);
Expand All @@ -132,7 +135,7 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
}
}

getSplit(name: string) {
getSplit(name: string): ISplit | null {
const item = localStorage.getItem(this.keys.buildSplitKey(name));
return item && JSON.parse(item);
}
Expand Down
Loading