Skip to content
Open
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
18 changes: 10 additions & 8 deletions src/dtos/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export interface IExcludedSegment {
export interface TargetingEntity {
name: string;
changeNumber: number;
status: 'ACTIVE' | 'ARCHIVED';
status?: 'ACTIVE' | 'ARCHIVED';
conditions: IDefinitionCondition[];
}

Expand Down Expand Up @@ -235,15 +235,17 @@ export interface IDefinition extends TargetingEntity {

/** Interface of the parsed JSON response of `/splitChanges` */
export interface IDefinitionChangesResponse {
ff?: {
t: number,
s?: number,
d: IDefinition[]
d?: {
till: number,
since?: number | null,
updated: IDefinition[],
removed: string[],
},
rbs?: {
t: number,
s?: number,
d: IRBSegment[]
till: number,
since?: number | null,
updated: IRBSegment[],
removed: string[],
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/evaluator/matchers/matcherTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ export const matcherTypes: Record<string, number> = {
ENDS_WITH: 12,
STARTS_WITH: 13,
CONTAINS_STRING: 14,
IN_SPLIT_TREATMENT: 15,
IN_SPLIT_TREATMENT: 15, // For flags only
EQUAL_TO_BOOLEAN: 16,
MATCHES_STRING: 17,
EQUAL_TO_SEMVER: 18,
GREATER_THAN_OR_EQUAL_TO_SEMVER: 19,
LESS_THAN_OR_EQUAL_TO_SEMVER: 20,
BETWEEN_SEMVER: 21,
IN_LIST_SEMVER: 22,
IN_LARGE_SEGMENT: 23,
IN_LARGE_SEGMENT: 23, // For client-side only
IN_RULE_BASED_SEGMENT: 24,
};

Expand Down
4 changes: 2 additions & 2 deletions src/storages/AbstractSplitsCacheAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
protected abstract removeSplit(name: string): Promise<boolean>
protected abstract setChangeNumber(changeNumber: number): Promise<boolean | void>

update(toAdd: IDefinition[], toRemove: IDefinition[], changeNumber: number): Promise<boolean> {
update(toAdd: IDefinition[], toRemove: string[], 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)))
Promise.all(toRemove.map(removedFF => this.removeSplit(removedFF)))
]).then(([, added, removed]) => {
return added.some(result => result) || removed.some(result => result);
});
Expand Down
4 changes: 2 additions & 2 deletions src/storages/AbstractSplitsCacheSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
protected abstract removeSplit(name: string): boolean
protected abstract setChangeNumber(changeNumber: number): boolean | void

update(toAdd: IDefinition[], toRemove: IDefinition[], changeNumber: number): boolean {
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): boolean {
let updated = toAdd.map(addedFF => this.addSplit(addedFF)).some(result => result);
updated = toRemove.map(removedFF => this.removeSplit(removedFF.name)).some(result => result) || updated;
updated = toRemove.map(removedFF => this.removeSplit(removedFF)).some(result => result) || updated;
this.setChangeNumber(changeNumber);
return updated;
}
Expand Down
8 changes: 4 additions & 4 deletions src/storages/__tests__/RBSegmentsCacheAsync.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ describe.each([{ cache: cacheInRedis, wrapper: redisClient }, { cache: cachePlug
expect(await cache.getChangeNumber()).toBe(1);

// Remove a segment
expect(await cache.update([], [rbSegment], 2)).toBe(true);
expect(await cache.update([], [rbSegment.name], 2)).toBe(true);
expect(await cache.get(rbSegment.name)).toBeNull();
expect(await cache.get(rbSegmentWithInSegmentMatcher.name)).toEqual(rbSegmentWithInSegmentMatcher);
expect(await cache.getChangeNumber()).toBe(2);

// Remove remaining segment
expect(await cache.update([], [rbSegmentWithInSegmentMatcher], 3)).toBe(true);
expect(await cache.update([], [rbSegmentWithInSegmentMatcher.name], 3)).toBe(true);
expect(await cache.get(rbSegment.name)).toBeNull();
expect(await cache.get(rbSegmentWithInSegmentMatcher.name)).toBeNull();
expect(await cache.getChangeNumber()).toBe(3);

// No changes
expect(await cache.update([], [rbSegmentWithInSegmentMatcher], 4)).toBe(false);
expect(await cache.update([], [rbSegmentWithInSegmentMatcher.name], 4)).toBe(false);
expect(await cache.getChangeNumber()).toBe(4);
});

Expand All @@ -55,6 +55,6 @@ describe.each([{ cache: cacheInRedis, wrapper: redisClient }, { cache: cachePlug
expect(await cache.contains(new Set(['nonexistent']))).toBe(false);
expect(await cache.contains(new Set([rbSegment.name, 'nonexistent']))).toBe(false);

await cache.update([], [rbSegment, rbSegmentWithInSegmentMatcher], 2);
await cache.update([], [rbSegment.name, rbSegmentWithInSegmentMatcher.name], 2);
});
});
8 changes: 4 additions & 4 deletions src/storages/__tests__/RBSegmentsCacheSync.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ describe.each([cacheInMemory, cacheInLocal])('Rule-based segments cache sync (Me
expect(cache.getChangeNumber()).toBe(1);

// Remove a segment
expect(cache.update([], [rbSegment], 2)).toBe(true);
expect(cache.update([], [rbSegment.name], 2)).toBe(true);
expect(cache.get(rbSegment.name)).toBeNull();
expect(cache.get(rbSegmentWithInSegmentMatcher.name)).toEqual(rbSegmentWithInSegmentMatcher);
expect(cache.getChangeNumber()).toBe(2);

// Remove remaining segment
expect(cache.update([], [rbSegmentWithInSegmentMatcher], 3)).toBe(true);
expect(cache.update([], [rbSegmentWithInSegmentMatcher.name], 3)).toBe(true);
expect(cache.get(rbSegment.name)).toBeNull();
expect(cache.get(rbSegmentWithInSegmentMatcher.name)).toBeNull();
expect(cache.getChangeNumber()).toBe(3);

// No changes
expect(cache.update([], [rbSegmentWithInSegmentMatcher], 4)).toBe(false);
expect(cache.update([], [rbSegmentWithInSegmentMatcher.name], 4)).toBe(false);
expect(cache.getChangeNumber()).toBe(4);
});

Expand All @@ -58,7 +58,7 @@ describe.each([cacheInMemory, cacheInLocal])('Rule-based segments cache sync (Me
expect(cache.contains(new Set(['nonexistent']))).toBe(false);
expect(cache.contains(new Set([rbSegment.name, 'nonexistent']))).toBe(false);

cache.update([], [rbSegment, rbSegmentWithInSegmentMatcher], 2);
cache.update([], [rbSegment.name, rbSegmentWithInSegmentMatcher.name], 2);
});

test('usesSegments should track segments usage correctly', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ export class RBSegmentsCacheInLocal implements IRBSegmentsCacheSync {
this.storage.removeItem(this.keys.buildRBSegmentsTillKey());
}

update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): boolean {
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): boolean {
let updated = toAdd.map(toAdd => this.add(toAdd)).some(result => result);
updated = toRemove.map(toRemove => this.remove(toRemove.name)).some(result => result) || updated;
updated = toRemove.map(toRemove => this.remove(toRemove)).some(result => result) || updated;
this.setChangeNumber(changeNumber);
return updated;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe.each(storages)('SPLITS CACHE', (storage) => {

cache.update([something, somethingElse], [], 1);

cache.update([], [something, somethingElse], 1);
cache.update([], [something.name, somethingElse.name], 1);

expect(cache.getSplit(something.name)).toBe(null);
expect(cache.getSplit(somethingElse.name)).toBe(null);
Expand Down
4 changes: 2 additions & 2 deletions src/storages/inMemory/RBSegmentsCacheInMemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export class RBSegmentsCacheInMemory implements IRBSegmentsCacheSync {
this.segmentsCount = 0;
}

update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): boolean {
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): boolean {
let updated = toAdd.map(toAdd => this.add(toAdd)).some(result => result);
updated = toRemove.map(toRemove => this.remove(toRemove.name)).some(result => result) || updated;
updated = toRemove.map(toRemove => this.remove(toRemove)).some(result => result) || updated;
this.changeNumber = changeNumber;
return updated;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ test('SPLITS CACHE / In Memory / Update Splits', () => {

cache.update([something, somethingElse], [], 1);

cache.update([], [something, somethingElse], 1);
cache.update([], [something.name, somethingElse.name], 1);

expect(cache.getSplit(something.name)).toBe(null);
expect(cache.getSplit(somethingElse.name)).toBe(null);
Expand Down
4 changes: 2 additions & 2 deletions src/storages/inRedis/RBSegmentsCacheInRedis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class RBSegmentsCacheInRedis implements IRBSegmentsCacheAsync {
});
}

update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): Promise<boolean> {
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): Promise<boolean> {
return Promise.all([
this.setChangeNumber(changeNumber),
Promise.all(toAdd.map(toAdd => {
Expand All @@ -46,7 +46,7 @@ export class RBSegmentsCacheInRedis implements IRBSegmentsCacheAsync {
return this.redis.set(key, stringifiedNewRBSegment).then(() => true);
})),
Promise.all(toRemove.map(toRemove => {
const key = this.keys.buildRBSegmentKey(toRemove.name);
const key = this.keys.buildRBSegmentKey(toRemove);
return this.redis.del(key).then((status: number) => status === 1);
}))
]).then(([, added, removed]) => {
Expand Down
6 changes: 3 additions & 3 deletions src/storages/inRedis/__tests__/SplitsCacheInRedis.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ describe('SPLITS CACHE REDIS', () => {
expect(lol1Split.defaultTreatment).not.toBe('some_treatment_2'); // existing split is not updated if given changeNumber is older

// Delete splits and TT keys
await cache.update([], [splitWithUserTT, splitWithAccountTT], -1);
await cache.update([], [splitWithUserTT.name, splitWithAccountTT.name], -1);
await connection.del(keysBuilder.buildSplitsTillKey());
expect(await connection.keys(`${prefix}*`)).toHaveLength(0);
await connection.disconnect();
Expand Down Expand Up @@ -191,7 +191,7 @@ describe('SPLITS CACHE REDIS', () => {
expect(await cache.getNamesByFlagSets([])).toEqual([]);

// Delete splits, TT and flag set keys
await cache.update([], [featureFlagThree, featureFlagTwo, featureFlagWithEmptyFS], -1);
await cache.update([], [featureFlagThree.name, featureFlagTwo.name, featureFlagWithEmptyFS.name], -1);
await connection.del(keysBuilder.buildSplitsTillKey());
expect(await connection.keys(`${prefix}*`)).toHaveLength(0);
await connection.disconnect();
Expand Down Expand Up @@ -219,7 +219,7 @@ describe('SPLITS CACHE REDIS', () => {
expect(await cacheWithoutFilters.getNamesByFlagSets(['o', 'n', 'e'])).toEqual([new Set(['ff_one', 'ff_two']), new Set(['ff_one']), new Set(['ff_one', 'ff_three'])]);

// Delete splits, TT and flag set keys
await cacheWithoutFilters.update([], [featureFlagThree, featureFlagTwo, featureFlagOne, featureFlagWithEmptyFS], -1);
await cacheWithoutFilters.update([], [featureFlagThree.name, featureFlagTwo.name, featureFlagOne.name, featureFlagWithEmptyFS.name], -1);
await connection.del(keysBuilder.buildSplitsTillKey());
expect(await connection.keys(`${prefix}*`)).toHaveLength(0);
await connection.disconnect();
Expand Down
4 changes: 2 additions & 2 deletions src/storages/pluggable/RBSegmentsCachePluggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class RBSegmentsCachePluggable implements IRBSegmentsCacheAsync {
});
}

update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): Promise<boolean> {
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): Promise<boolean> {
return Promise.all([
this.setChangeNumber(changeNumber),
Promise.all(toAdd.map(toAdd => {
Expand All @@ -45,7 +45,7 @@ export class RBSegmentsCachePluggable implements IRBSegmentsCacheAsync {
return this.wrapper.set(key, stringifiedNewRBSegment).then(() => true);
})),
Promise.all(toRemove.map(toRemove => {
const key = this.keys.buildRBSegmentKey(toRemove.name);
const key = this.keys.buildRBSegmentKey(toRemove);
return this.wrapper.del(key);
}))
]).then(([, added, removed]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ describe('SPLITS CACHE PLUGGABLE', () => {
expect(lol1Split.defaultTreatment).not.toBe('some_treatment_2'); // existing split is not updated if given changeNumber is older

// Delete splits and TT keys
await cache.update([], [splitWithUserTT, splitWithAccountTT], -1);
await cache.update([], [splitWithUserTT.name, splitWithAccountTT.name], -1);
await wrapper.del(keysBuilder.buildSplitsTillKey());
expect(await wrapper.getKeysByPrefix('SPLITIO')).toHaveLength(0);
});
Expand Down
17 changes: 9 additions & 8 deletions src/storages/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import SplitIO from '../../types/splitio';
import { MaybeThenable, IDefinition, IRBSegment, IMySegmentsResponse, IMembershipsResponse, ISegmentChangesResponse, IDefinitionChangesResponse } from '../dtos/types';
import { MaybeThenable, IDefinition, IRBSegment, IMySegmentsResponse, IMembershipsResponse, ISegmentChangesResponse } from '../dtos/types';
import { ISplitChangesResponse } from '../sync/polling/fetchers/splitChangesFetcher';
import { MySegmentsData } from '../sync/polling/types';
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, MultiMethodExceptions, MultiMethodLatencies, MultiConfigs, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../sync/submitters/types';
import { ISettings } from '../types';
Expand Down Expand Up @@ -194,7 +195,7 @@ export interface IPluggableStorageWrapper {
/** Splits cache */

export interface ISplitsCacheBase {
update(toAdd: IDefinition[], toRemove: IDefinition[], changeNumber: number): MaybeThenable<boolean>,
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): MaybeThenable<boolean>,
getSplit(name: string): MaybeThenable<IDefinition | null>,
getSplits(names: string[]): MaybeThenable<Record<string, IDefinition | null>>, // `fetchMany` in spec
// should never reject or throw an exception. Instead return -1 by default, assuming no splits are present in the storage.
Expand All @@ -211,7 +212,7 @@ export interface ISplitsCacheBase {
}

export interface ISplitsCacheSync extends ISplitsCacheBase {
update(toAdd: IDefinition[], toRemove: IDefinition[], changeNumber: number): boolean,
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): boolean,
getSplit(name: string): IDefinition | null,
getSplits(names: string[]): Record<string, IDefinition | null>,
getChangeNumber(): number,
Expand All @@ -225,7 +226,7 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
}

export interface ISplitsCacheAsync extends ISplitsCacheBase {
update(toAdd: IDefinition[], toRemove: IDefinition[], changeNumber: number): Promise<boolean>,
update(toAdd: IDefinition[], toRemove: string[], changeNumber: number): Promise<boolean>,
getSplit(name: string): Promise<IDefinition | null>,
getSplits(names: string[]): Promise<Record<string, IDefinition | null>>,
getChangeNumber(): Promise<number>,
Expand All @@ -241,15 +242,15 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
/** Rule-Based Segments cache */

export interface IRBSegmentsCacheBase {
update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): MaybeThenable<boolean>,
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): MaybeThenable<boolean>,
get(name: string): MaybeThenable<IRBSegment | null>,
getChangeNumber(): MaybeThenable<number>,
clear(): MaybeThenable<boolean | void>,
contains(names: Set<string>): MaybeThenable<boolean>,
}

export interface IRBSegmentsCacheSync extends IRBSegmentsCacheBase {
update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): boolean,
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): boolean,
get(name: string): IRBSegment | null,
getChangeNumber(): number,
getAll(): IRBSegment[],
Expand All @@ -260,7 +261,7 @@ export interface IRBSegmentsCacheSync extends IRBSegmentsCacheBase {
}

export interface IRBSegmentsCacheAsync extends IRBSegmentsCacheBase {
update(toAdd: IRBSegment[], toRemove: IRBSegment[], changeNumber: number): Promise<boolean>,
update(toAdd: IRBSegment[], toRemove: string[], changeNumber: number): Promise<boolean>,
get(name: string): Promise<IRBSegment | null>,
getChangeNumber(): Promise<number>,
clear(): Promise<boolean | void>,
Expand Down Expand Up @@ -544,7 +545,7 @@ export type RolloutPlan = {
/**
* Feature flags and rule-based segments.
*/
splitChanges: IDefinitionChangesResponse;
splitChanges: ISplitChangesResponse;
/**
* Optional map of matching keys to their memberships.
*/
Expand Down
Loading