From b54d481fc8f8f30885382cb4ec1d92aa2b06b551 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Mon, 30 Oct 2023 12:38:32 +0100 Subject: [PATCH] fix: variant hashing in playground (#5213) --- .../strategy/flexible-rollout-strategy.ts | 4 ++-- .../strategy/gradual-rollout-session-id.ts | 4 ++-- .../strategy/gradual-rollout-user-id.ts | 4 ++-- .../feature-evaluator/strategy/util.ts | 24 ++++++++++++++++--- .../playground/feature-evaluator/variant.ts | 4 ++-- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/lib/features/playground/feature-evaluator/strategy/flexible-rollout-strategy.ts b/src/lib/features/playground/feature-evaluator/strategy/flexible-rollout-strategy.ts index 97da0f04e7..728bdec61f 100644 --- a/src/lib/features/playground/feature-evaluator/strategy/flexible-rollout-strategy.ts +++ b/src/lib/features/playground/feature-evaluator/strategy/flexible-rollout-strategy.ts @@ -1,6 +1,6 @@ import { Strategy } from './strategy'; import { Context } from '../context'; -import normalizedValue from './util'; +import { normalizedStrategyValue } from './util'; import { resolveContextValue } from '../helpers'; const STICKINESS = { @@ -54,7 +54,7 @@ export default class FlexibleRolloutStrategy extends Strategy { if (!stickinessId) { return false; } - const normalizedUserId = normalizedValue(stickinessId, groupId); + const normalizedUserId = normalizedStrategyValue(stickinessId, groupId); return percentage > 0 && normalizedUserId <= percentage; } } diff --git a/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-session-id.ts b/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-session-id.ts index 391c5b62c1..3ea08d7502 100644 --- a/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-session-id.ts +++ b/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-session-id.ts @@ -1,5 +1,5 @@ import { Strategy } from './strategy'; -import normalizedValue from './util'; +import { normalizedStrategyValue } from './util'; import { Context } from '../context'; export default class GradualRolloutSessionIdStrategy extends Strategy { @@ -19,7 +19,7 @@ export default class GradualRolloutSessionIdStrategy extends Strategy { const percentage = Number(parameters.percentage); const groupId = parameters.groupId || ''; - const normalizedId = normalizedValue(sessionId, groupId); + const normalizedId = normalizedStrategyValue(sessionId, groupId); return percentage > 0 && normalizedId <= percentage; } diff --git a/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-user-id.ts b/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-user-id.ts index e4edd7ca82..f31325a4d0 100644 --- a/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-user-id.ts +++ b/src/lib/features/playground/feature-evaluator/strategy/gradual-rollout-user-id.ts @@ -1,6 +1,6 @@ import { Strategy } from './strategy'; import { Context } from '../context'; -import normalizedValue from './util'; +import { normalizedStrategyValue } from './util'; export default class GradualRolloutUserIdStrategy extends Strategy { constructor() { @@ -19,7 +19,7 @@ export default class GradualRolloutUserIdStrategy extends Strategy { const percentage = Number(parameters.percentage); const groupId = parameters.groupId || ''; - const normalizedUserId = normalizedValue(userId, groupId); + const normalizedUserId = normalizedStrategyValue(userId, groupId); return percentage > 0 && normalizedUserId <= percentage; } diff --git a/src/lib/features/playground/feature-evaluator/strategy/util.ts b/src/lib/features/playground/feature-evaluator/strategy/util.ts index c3ce7434ed..4c7cef05df 100644 --- a/src/lib/features/playground/feature-evaluator/strategy/util.ts +++ b/src/lib/features/playground/feature-evaluator/strategy/util.ts @@ -1,9 +1,27 @@ import * as murmurHash3 from 'murmurhash3js'; -export default function normalizedValue( +function normalizedValue( id: string, groupId: string, - normalizer = 100, + normalizer: number, + seed = 0, ): number { - return (murmurHash3.x86.hash32(`${groupId}:${id}`) % normalizer) + 1; + const hash = murmurHash3.x86.hash32(`${groupId}:${id}`, seed); + return (hash % normalizer) + 1; +} + +const STRATEGY_SEED = 0; + +export function normalizedStrategyValue(id: string, groupId: string): number { + return normalizedValue(id, groupId, 100, STRATEGY_SEED); +} + +const VARIANT_SEED = 86028157; + +export function normalizedVariantValue( + id: string, + groupId: string, + normalizer: number, +): number { + return normalizedValue(id, groupId, normalizer, VARIANT_SEED); } diff --git a/src/lib/features/playground/feature-evaluator/variant.ts b/src/lib/features/playground/feature-evaluator/variant.ts index 6784836b2e..3630e8e745 100644 --- a/src/lib/features/playground/feature-evaluator/variant.ts +++ b/src/lib/features/playground/feature-evaluator/variant.ts @@ -1,7 +1,7 @@ import { Context } from './context'; // eslint-disable-next-line import/no-cycle import { FeatureInterface } from './feature'; -import normalizedValue from './strategy/util'; +import { normalizedVariantValue } from './strategy/util'; import { resolveContextValue } from './helpers'; interface Override { @@ -91,7 +91,7 @@ export function selectVariantDefinition( const { stickiness } = variants[0]; - const target = normalizedValue( + const target = normalizedVariantValue( getSeed(context, stickiness), featureName, totalWeight,