Skip to content

Commit ab1ffb5

Browse files
authored
fix(flag-evaluation) Revert async API (#392)
In #384 I made the interface async, that is no longer needed.
1 parent 912f017 commit ab1ffb5

4 files changed

Lines changed: 30 additions & 47 deletions

File tree

packages/flag-evaluation/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bucketco/flag-evaluation",
3-
"version": "0.1.1",
3+
"version": "0.1.2",
44
"license": "MIT",
55
"repository": {
66
"type": "git",

packages/flag-evaluation/src/index.ts

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ export function unflattenJSON(data: Record<string, any>): Record<string, any> {
259259
* @param {string} hashInput - The input string used to generate the hash.
260260
* @return {number} A number between 0 and 100000 derived from the hash of the input string.
261261
*/
262-
export async function hashInt(hashInput: string): Promise<number> {
262+
export function hashInt(hashInput: string): number {
263263
// 1. hash the key and the partial rollout attribute
264264
// 2. take 20 bits from the hash and divide by 2^20 - 1 to get a number between 0 and 1
265265
// 3. multiply by 100000 to get a number between 0 and 100000 and compare it to the threshold
@@ -344,11 +344,11 @@ export function evaluate(
344344
}
345345
}
346346

347-
async function evaluateRecursively(
347+
function evaluateRecursively(
348348
filter: RuleFilter,
349349
context: Record<string, string>,
350350
missingContextFieldsSet: Set<string>,
351-
): Promise<boolean> {
351+
): boolean {
352352
switch (filter.type) {
353353
case "constant":
354354
return filter.value;
@@ -369,38 +369,30 @@ async function evaluateRecursively(
369369
return false;
370370
}
371371

372-
const hashVal = await hashInt(
372+
const hashVal = hashInt(
373373
`${filter.key}.${context[filter.partialRolloutAttribute]}`,
374374
);
375375

376376
return hashVal < filter.partialRolloutThreshold;
377377
}
378-
case "group": {
379-
const isAnd = filter.operator === "and";
380-
let result = isAnd;
381-
for (const current of filter.filters) {
382-
// short-circuit if we know the result already
383-
// could be simplified to isAnd !== result, but this is more readable
384-
if ((isAnd && !result) || (!isAnd && result)) {
385-
return result;
378+
case "group":
379+
return filter.filters.reduce((acc, current) => {
380+
if (filter.operator === "and") {
381+
return (
382+
acc &&
383+
evaluateRecursively(current, context, missingContextFieldsSet)
384+
);
386385
}
387-
388-
const newRes = await evaluateRecursively(
389-
current,
390-
context,
391-
missingContextFieldsSet,
386+
return (
387+
acc || evaluateRecursively(current, context, missingContextFieldsSet)
392388
);
393-
394-
result = isAnd ? result && newRes : result || newRes;
395-
}
396-
return result;
397-
}
389+
}, filter.operator === "and");
398390
case "negation":
399-
return !(await evaluateRecursively(
391+
return !evaluateRecursively(
400392
filter.filter,
401393
context,
402394
missingContextFieldsSet,
403-
));
395+
);
404396
default:
405397
return false;
406398
}
@@ -442,18 +434,16 @@ export interface EvaluationResult<T extends RuleValue> {
442434
missingContextFields?: string[];
443435
}
444436

445-
export async function evaluateFeatureRules<T extends RuleValue>({
437+
export function evaluateFeatureRules<T extends RuleValue>({
446438
context,
447439
featureKey,
448440
rules,
449-
}: EvaluationParams<T>): Promise<EvaluationResult<T>> {
441+
}: EvaluationParams<T>): EvaluationResult<T> {
450442
const flatContext = flattenJSON(context);
451443
const missingContextFieldsSet = new Set<string>();
452444

453-
const ruleEvaluationResults = await Promise.all(
454-
rules.map((rule) =>
455-
evaluateRecursively(rule.filter, flatContext, missingContextFieldsSet),
456-
),
445+
const ruleEvaluationResults = rules.map((rule) =>
446+
evaluateRecursively(rule.filter, flatContext, missingContextFieldsSet),
457447
);
458448

459449
const missingContextFields = Array.from(missingContextFieldsSet);

packages/flag-evaluation/test/index.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const feature = {
3838

3939
describe("evaluate feature targeting integration ", () => {
4040
it("evaluates all kinds of filters", async () => {
41-
const res = await evaluateFeatureRules({
41+
const res = evaluateFeatureRules({
4242
featureKey: "feature",
4343
rules: [
4444
{
@@ -109,7 +109,7 @@ describe("evaluate feature targeting integration ", () => {
109109
});
110110

111111
it("evaluates flag when there's no matching rule", async () => {
112-
const res = await evaluateFeatureRules({
112+
const res = evaluateFeatureRules({
113113
...feature,
114114
context: {
115115
company: {
@@ -137,7 +137,7 @@ describe("evaluate feature targeting integration ", () => {
137137
},
138138
};
139139

140-
const res = await evaluateFeatureRules({
140+
const res = evaluateFeatureRules({
141141
...feature,
142142
context,
143143
});
@@ -155,7 +155,7 @@ describe("evaluate feature targeting integration ", () => {
155155
});
156156

157157
it("evaluates flag with missing values", async () => {
158-
const res = await evaluateFeatureRules({
158+
const res = evaluateFeatureRules({
159159
featureKey: "feature",
160160
rules: [
161161
{
@@ -198,7 +198,7 @@ describe("evaluate feature targeting integration ", () => {
198198
});
199199

200200
it("returns list of missing context keys ", async () => {
201-
const res = await evaluateFeatureRules({
201+
const res = evaluateFeatureRules({
202202
...feature,
203203
context: {},
204204
});
@@ -214,7 +214,7 @@ describe("evaluate feature targeting integration ", () => {
214214
});
215215

216216
it("fails evaluation and includes key in missing keys when rollout attribute is missing from context", async () => {
217-
const res = await evaluateFeatureRules({
217+
const res = evaluateFeatureRules({
218218
featureKey: "myfeature",
219219
rules: [
220220
{
@@ -352,8 +352,8 @@ describe("rollout hash", () => {
352352
] as const;
353353

354354
for (const [input, expected] of tests) {
355-
it(`evaluates '${input}' = ${expected}`, async () => {
356-
const res = await hashInt(input);
355+
it(`evaluates '${input}' = ${expected}`, () => {
356+
const res = hashInt(input);
357357
expect(res).toEqual(expected);
358358
});
359359
}

yarn.lock

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -545,14 +545,7 @@ __metadata:
545545
languageName: unknown
546546
linkType: soft
547547

548-
"@bucketco/flag-evaluation@npm:~0.1.0":
549-
version: 0.1.0
550-
resolution: "@bucketco/flag-evaluation@npm:0.1.0"
551-
checksum: 10c0/a5d747962d43ce12b194735e92524a576edac9e9ad53c425b4a517123ca9918d3001891cd212f178b7cf6b235c79aa5cfa3942e162187da056c2ae1d5230a984
552-
languageName: node
553-
linkType: hard
554-
555-
"@bucketco/flag-evaluation@workspace:packages/flag-evaluation":
548+
"@bucketco/flag-evaluation@npm:~0.1.0, @bucketco/flag-evaluation@workspace:packages/flag-evaluation":
556549
version: 0.0.0-use.local
557550
resolution: "@bucketco/flag-evaluation@workspace:packages/flag-evaluation"
558551
dependencies:

0 commit comments

Comments
 (0)