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
6 changes: 3 additions & 3 deletions src/evaluator/__tests__/evaluate-feature.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const splitsMock: Record<string, IDefinition> = {
};

const mockStorage = {
splits: {
getSplit(name: string) {
definitions: {
get(name: string) {
if (name === 'throw_exception') throw new Error('Error');
if (splitsMock[name]) return splitsMock[name];

Expand All @@ -43,7 +43,7 @@ test('EVALUATOR / should return label exception, treatment control and config nu
// This validation is async because the only exception possible when retrieving a Split would happen with Async storages.
const evaluation = await evaluationPromise;

expect(evaluation).toEqual(expectedOutput); // If there was an error on the getSplits we should get the results for exception.
expect(evaluation).toEqual(expectedOutput); // If there was an error on the get method, we should get the results for exception.
});


Expand Down
42 changes: 21 additions & 21 deletions src/evaluator/__tests__/evaluate-features.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ const flagSetsMock: Record<string, Set<string>> = {
};

const mockStorage = {
splits: {
getSplit(name: string) {
definitions: {
get(name: string) {
if (name === 'throw_exception') throw new Error('Error');
if (splitsMock[name]) return splitsMock[name];

return null;
},
getSplits(names: string[]) {
getMany(names: string[]) {
return names.reduce((acc, name) => {
acc[name] = this.getSplit(name);
acc[name] = this.get(name);
return acc;
}, {} as Record<string, IDefinition | null>);
},
getNamesByFlagSets(flagSets: string[]) {
getNamesBySets(flagSets: string[]) {
return flagSets.map(flagset => flagSetsMock[flagset] || new Set());
}
}
Expand All @@ -59,7 +59,7 @@ test('EVALUATOR - Multiple evaluations at once / should return label exception,
mockStorage,
);

expect(evaluation).toEqual(expectedOutput); // If there was an error on the `getSplits` we should get the results for exception.
expect(evaluation).toEqual(expectedOutput); // If there was an error on the get method, we should get the results for exception.

});

Expand Down Expand Up @@ -126,7 +126,7 @@ describe('EVALUATOR - Multiple evaluations at once by flag sets', () => {
},
};

const getResultsByFlagsets = (flagSets: string[], storage = mockStorage) => {
const getResultsByFlagSets = (flagSets: string[], storage = mockStorage) => {
return evaluateFeaturesByFlagSets(
loggerMock,
'fake-key',
Expand All @@ -139,7 +139,7 @@ describe('EVALUATOR - Multiple evaluations at once by flag sets', () => {

test('should return right labels, treatments and configs if storage returns without errors', async () => {

let multipleEvaluationAtOnceByFlagSets = await getResultsByFlagsets(['reg_and_config', 'arch_and_killed']);
let multipleEvaluationAtOnceByFlagSets = await getResultsByFlagSets(['reg_and_config', 'arch_and_killed']);

// assert evaluationWithConfig
expect(multipleEvaluationAtOnceByFlagSets['config']).toEqual(expectedOutput['config']); // If the split is retrieved successfully we should get the right evaluation result, label and config.
Expand All @@ -158,39 +158,39 @@ describe('EVALUATOR - Multiple evaluations at once by flag sets', () => {
// assert not_existent_split not in evaluation if it is not related to defined flag sets
expect(multipleEvaluationAtOnceByFlagSets['not_existent_split']).toEqual(undefined);

multipleEvaluationAtOnceByFlagSets = await getResultsByFlagsets([]);
multipleEvaluationAtOnceByFlagSets = await getResultsByFlagSets([]);
expect(multipleEvaluationAtOnceByFlagSets).toEqual({});

multipleEvaluationAtOnceByFlagSets = await getResultsByFlagsets(['reg_and_config']);
multipleEvaluationAtOnceByFlagSets = await getResultsByFlagSets(['reg_and_config']);
expect(multipleEvaluationAtOnceByFlagSets['config']).toEqual(expectedOutput['config']);
expect(multipleEvaluationAtOnceByFlagSets['regular']).toEqual({ ...expectedOutput['config'], config: null });
expect(multipleEvaluationAtOnceByFlagSets['killed']).toEqual(undefined);
expect(multipleEvaluationAtOnceByFlagSets['archived']).toEqual(undefined);
});

test('should log a warning if evaluating with flag sets that doesn\'t contain cached feature flags', async () => {
const getSplitsSpy = jest.spyOn(mockStorage.splits, 'getSplits');
const getManySpy = jest.spyOn(mockStorage.definitions, 'getMany');

// No flag set contains cached feature flags -> getSplits method is not called
expect(getResultsByFlagsets(['inexistent_set1', 'inexistent_set2'])).toEqual({});
expect(getSplitsSpy).not.toHaveBeenCalled();
// No flag set contains cached feature flags -> getMany method is not called
expect(getResultsByFlagSets(['inexistent_set1', 'inexistent_set2'])).toEqual({});
expect(getManySpy).not.toHaveBeenCalled();
expect(loggerMock.warn.mock.calls).toEqual([
[WARN_FLAGSET_WITHOUT_FLAGS, ['method-name', 'inexistent_set1']],
[WARN_FLAGSET_WITHOUT_FLAGS, ['method-name', 'inexistent_set2']],
]);

// One flag set contains cached feature flags -> getSplits method is called
expect(getResultsByFlagsets(['inexistent_set3', 'reg_and_config'])).toEqual(getResultsByFlagsets(['reg_and_config']));
expect(getSplitsSpy).toHaveBeenLastCalledWith(['regular', 'config']);
// One flag set contains cached feature flags -> getMany method is called
expect(getResultsByFlagSets(['inexistent_set3', 'reg_and_config'])).toEqual(getResultsByFlagSets(['reg_and_config']));
expect(getManySpy).toHaveBeenLastCalledWith(['regular', 'config']);
expect(loggerMock.warn).toHaveBeenLastCalledWith(WARN_FLAGSET_WITHOUT_FLAGS, ['method-name', 'inexistent_set3']);

getSplitsSpy.mockRestore();
getManySpy.mockRestore();
loggerMock.warn.mockClear();

// Should support async storage too
expect(await getResultsByFlagsets(['inexistent_set1', 'inexistent_set2'], {
splits: {
getNamesByFlagSets(flagSets: string[]) { return Promise.resolve(flagSets.map(flagset => flagSetsMock[flagset] || new Set())); }
expect(await getResultsByFlagSets(['inexistent_set1', 'inexistent_set2'], {
definitions: {
getNamesBySets(flagSets: string[]) { return Promise.resolve(flagSets.map(flagset => flagSetsMock[flagset] || new Set())); }
}
} as unknown as IStorageSync)).toEqual({});
expect(loggerMock.warn.mock.calls).toEqual([
Expand Down
22 changes: 11 additions & 11 deletions src/evaluator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ export function evaluateFeature(
let definition;

try {
definition = storage.splits.getSplit(definitionName);
definition = storage.definitions.get(definitionName);
} catch (e) {
// Exception on sync `getSplit` storage. Not possible ATM with InMemory and InLocal storages.
// Exception on sync storage. Not possible ATM with InMemory and InLocal storages.
return EVALUATION_EXCEPTION;
}

Expand All @@ -56,7 +56,7 @@ export function evaluateFeature(
storage,
options,
)).catch(
// Exception on async `getSplit` storage. For example, when the storage is redis or
// Exception on async storage. For example, when the storage is redis or
// pluggable and there is a connection issue and we can't retrieve the split to be evaluated
() => EVALUATION_EXCEPTION
);
Expand All @@ -83,16 +83,16 @@ export function evaluateFeatures(
let definitions;

try {
definitions = storage.splits.getSplits(definitionNames);
definitions = storage.definitions.getMany(definitionNames);
} catch (e) {
// Exception on sync `getSplits` storage. Not possible ATM with InMemory and InLocal storages.
// Exception on sync storage. Not possible ATM with InMemory and InLocal storages.
return treatmentsException(definitionNames);
}

return thenable(definitions) ?
definitions.then(definitions => getEvaluations(log, key, definitionNames, definitions, attributes, storage, options))
.catch(() => {
// Exception on async `getSplits` storage. For example, when the storage is redis or
// Exception on async storage. For example, when the storage is redis or
// pluggable and there is a connection issue and we can't retrieve the split to be evaluated
return treatmentsException(definitionNames);
}) :
Expand Down Expand Up @@ -128,7 +128,7 @@ export function evaluateFeaturesByFlagSets(

// get features by flag sets
try {
storedFlagNames = storage.splits.getNamesByFlagSets(flagSets);
storedFlagNames = storage.definitions.getNamesBySets(flagSets);
} catch (e) {
// return empty evaluations
return {};
Expand Down Expand Up @@ -156,7 +156,7 @@ function getEvaluation(
const split = engineParser(log, definition, storage);
const evaluation = split.getTreatment(key, attributes, evaluateFeature);

// If the storage is async and the evaluated flag uses segments or dependencies, evaluation is thenable
// If the storage is async and the evaluated definition uses segments or dependencies, evaluation is thenable
if (thenable(evaluation)) {
return evaluation.then(result => {
result.changeNumber = definition.changeNumber;
Expand All @@ -183,7 +183,7 @@ function getEvaluations(
log: ILogger,
key: SplitIO.SplitKey,
definitionNames: string[],
splits: Record<string, IDefinition | null>,
definitions: Record<string, IDefinition | null>,
attributes: SplitIO.Attributes | undefined,
storage: IStorageSync | IStorageAsync,
options?: SplitIO.EvaluationOptions,
Expand All @@ -194,7 +194,7 @@ function getEvaluations(
const evaluation = getEvaluation(
log,
key,
splits[definitionName],
definitions[definitionName],
attributes,
storage,
options
Expand All @@ -218,7 +218,7 @@ export function evaluateDefaultTreatment(
let definition;

try {
definition = storage.splits.getSplit(definitionName);
definition = storage.definitions.get(definitionName);
} catch (e) {
return EVALUATION_EXCEPTION;
}
Expand Down
4 changes: 2 additions & 2 deletions src/evaluator/matchers/__tests__/dependency.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const STORED_SPLITS: Record<string, IDefinition> = {
};

const mockStorage = {
splits: {
getSplit: (name: string) => STORED_SPLITS[name]
definitions: {
get: (name: string) => STORED_SPLITS[name]
}
};

Expand Down
4 changes: 2 additions & 2 deletions src/evaluator/matchers/__tests__/prerequisites.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const STORED_SPLITS: Record<string, IDefinition> = {
};

const mockStorage = {
splits: {
getSplit: (name: string) => STORED_SPLITS[name]
definitions: {
get: (name: string) => STORED_SPLITS[name]
}
} as IStorageSync;

Expand Down
8 changes: 4 additions & 4 deletions src/evaluator/matchers/__tests__/rbsegment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ const STORED_RBSEGMENTS: Record<string, IRBSegment> = {

const mockStorageSync = {
isSync: true,
splits: {
getSplit(name: string) {
definitions: {
get(name: string) {
return STORED_SPLITS[name];
}
},
Expand All @@ -202,8 +202,8 @@ const mockStorageSync = {

const mockStorageAsync = {
isSync: false,
splits: {
getSplit(name: string) {
definitions: {
get(name: string) {
return Promise.resolve(STORED_SPLITS[name]);
}
},
Expand Down
Loading