Skip to content

Commit 57300db

Browse files
Handle undefined key in evaluator to support evaluation without key/target
1 parent 2afb814 commit 57300db

7 files changed

Lines changed: 13 additions & 14 deletions

File tree

src/evaluator/Engine.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ export function engineParser(log: ILogger, split: ISplit, storage: IStorageSync
2929

3030
return {
3131

32-
getTreatment(key: SplitIO.SplitKey, attributes: SplitIO.Attributes | undefined, splitEvaluator: ISplitEvaluator): MaybeThenable<IEvaluationResult> {
33-
34-
const parsedKey = keyParser(key);
32+
getTreatment(key: SplitIO.SplitKey | undefined, attributes: SplitIO.Attributes | undefined, splitEvaluator: ISplitEvaluator): MaybeThenable<IEvaluationResult> {
3533

3634
function evaluate(prerequisitesMet: boolean) {
3735
if (!prerequisitesMet) {
@@ -42,7 +40,7 @@ export function engineParser(log: ILogger, split: ISplit, storage: IStorageSync
4240
};
4341
}
4442

45-
const evaluation = evaluator(parsedKey, seed, trafficAllocation, trafficAllocationSeed, attributes, splitEvaluator) as MaybeThenable<IEvaluation>;
43+
const evaluation = evaluator(key ? keyParser(key) : undefined, seed, trafficAllocation, trafficAllocationSeed, attributes, splitEvaluator) as MaybeThenable<IEvaluation>;
4644

4745
return thenable(evaluation) ?
4846
evaluation.then(result => evaluationResult(result, defaultTreatment)) :

src/evaluator/combiners/ifelseif.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function ifElseIfCombinerContext(log: ILogger, predicates: IEvaluator[]):
3333
return undefined;
3434
}
3535

36-
function ifElseIfCombiner(key: SplitIO.SplitKeyObject, seed?: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) {
36+
function ifElseIfCombiner(key?: SplitIO.SplitKeyObject, seed?: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) {
3737
// In Async environments we are going to have async predicates. There is none way to know
3838
// before hand so we need to evaluate all the predicates, verify for thenables, and finally,
3939
// define how to return the treatment (wrap result into a Promise or not).

src/evaluator/condition/engineUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ export function getTreatment(log: ILogger, key: string, seed: number | undefined
1818
/**
1919
* Evaluates the traffic allocation to see if we should apply rollout conditions or not.
2020
*/
21-
export function shouldApplyRollout(trafficAllocation: number, key: string, trafficAllocationSeed: number) {
21+
export function shouldApplyRollout(trafficAllocation: number, bucketingKey: string, trafficAllocationSeed: number) {
2222
// For rollout, if traffic allocation for splits is 100%, we don't need to filter it because everything should evaluate the rollout.
2323
if (trafficAllocation < 100) {
24-
const _bucket = bucket(key, trafficAllocationSeed);
24+
const _bucket = bucket(bucketingKey, trafficAllocationSeed);
2525

2626
if (_bucket > trafficAllocation) {
2727
return false;

src/evaluator/condition/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ function match(log: ILogger, matchingResult: boolean, bucketingKey: string | und
2424
// Condition factory
2525
export function conditionContext(log: ILogger, matcherEvaluator: (key: SplitIO.SplitKeyObject, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable<boolean>, treatments?: { getTreatmentFor: (x: number) => string }, label?: string, conditionType?: 'ROLLOUT' | 'WHITELIST'): IEvaluator {
2626

27-
return function conditionEvaluator(key: SplitIO.SplitKeyObject, seed?: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) {
27+
return function conditionEvaluator(key?: SplitIO.SplitKeyObject, seed?: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) {
2828

2929
// Whitelisting has more priority than traffic allocation, so we don't apply this filtering to those conditions.
30-
if (conditionType === 'ROLLOUT' && !shouldApplyRollout(trafficAllocation!, key.bucketingKey, trafficAllocationSeed!)) {
30+
if (!key || (conditionType === 'ROLLOUT' && !shouldApplyRollout(trafficAllocation!, key.bucketingKey, trafficAllocationSeed!))) {
3131
return {
3232
treatment: undefined, // treatment value is assigned later
3333
label: NOT_IN_SPLIT

src/evaluator/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ function treatmentsException(splitNames: string[]) {
2424
return evaluations;
2525
}
2626

27+
// @TODO: test cases with no key
2728
export function evaluateFeature(
2829
log: ILogger,
29-
key: SplitIO.SplitKey,
30+
key: SplitIO.SplitKey | undefined,
3031
splitName: string,
3132
attributes: SplitIO.Attributes | undefined,
3233
storage: IStorageSync | IStorageAsync,
@@ -139,7 +140,7 @@ export function evaluateFeaturesByFlagSets(
139140

140141
function getEvaluation(
141142
log: ILogger,
142-
key: SplitIO.SplitKey,
143+
key: SplitIO.SplitKey | undefined,
143144
splitJSON: ISplit | null,
144145
attributes: SplitIO.Attributes | undefined,
145146
storage: IStorageSync | IStorageAsync,

src/evaluator/matchers/prerequisites.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { IDependencyMatcherValue, ISplitEvaluator } from '../types';
66

77
export function prerequisitesMatcherContext(prerequisites: ISplit['prerequisites'], storage: IStorageSync | IStorageAsync, log: ILogger) {
88

9-
return function prerequisitesMatcher({ key, attributes }: IDependencyMatcherValue, splitEvaluator: ISplitEvaluator): MaybeThenable<boolean> {
9+
return function prerequisitesMatcher({ key, attributes }: Partial<IDependencyMatcherValue>, splitEvaluator: ISplitEvaluator): MaybeThenable<boolean> {
1010

1111
prerequisites = prerequisites == null ? [] : prerequisites;
1212

src/evaluator/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ export interface IEvaluation {
2727

2828
export type IEvaluationResult = IEvaluation & { treatment: string; impressionsDisabled?: boolean }
2929

30-
export type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync) => MaybeThenable<IEvaluation>
30+
export type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey | undefined, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync) => MaybeThenable<IEvaluation>
3131

32-
export type IEvaluator = (key: SplitIO.SplitKeyObject, seed?: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable<IEvaluation | boolean | undefined>
32+
export type IEvaluator = (key?: SplitIO.SplitKeyObject, seed?: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable<IEvaluation | boolean | undefined>
3333

3434
export type IMatcher = (value: string | number | boolean | string[] | IDependencyMatcherValue, splitEvaluator?: ISplitEvaluator) => MaybeThenable<boolean>

0 commit comments

Comments
 (0)