Skip to content

Commit 1ef714c

Browse files
authored
fix: variants will now distribute correctly when used with a gradual rollout strategy (#282)
1 parent 4285bb5 commit 1ef714c

File tree

6 files changed

+18
-11
lines changed

6 files changed

+18
-11
lines changed

UnleashClient/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
REQUEST_TIMEOUT = 30
77
REQUEST_RETRIES = 3
88
METRIC_LAST_SENT_TIME = "mlst"
9-
CLIENT_SPEC_VERSION = "4.5.0"
9+
CLIENT_SPEC_VERSION = "5.0.2"
1010

1111
# =Unleash=
1212
APPLICATION_HEADERS = {

UnleashClient/utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ def increment(self, key):
4040

4141

4242
def normalized_hash(
43-
identifier: str, activation_group: str, normalizer: int = 100
43+
identifier: str, activation_group: str, normalizer: int = 100, seed: int = 0
4444
) -> int:
45-
return mmh3.hash(f"{activation_group}:{identifier}", signed=False) % normalizer + 1
45+
return (
46+
mmh3.hash(f"{activation_group}:{identifier}", signed=False, seed=seed)
47+
% normalizer
48+
+ 1
49+
)
4650

4751

4852
def get_identifier(context_key_name: str, context: dict) -> Any:

UnleashClient/variants/Variants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from UnleashClient import utils
77
from UnleashClient.constants import DISABLED_VARIATION
88

9+
VARIANT_HASH_SEED = 86028157
10+
911

1012
class Variants:
1113
def __init__(
@@ -103,6 +105,7 @@ def get_variant(self, context: dict, flag_status: Optional[bool] = None) -> dict
103105
self._get_seed(context, stickiness_selector),
104106
self.group_id,
105107
total_weight,
108+
seed=VARIANT_HASH_SEED,
106109
)
107110
counter = 0
108111
for variation in self.variants:

tests/unit_tests/strategies/test_strategy_variants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ def test_flexiblerollout_satisfies_constraints_returns_variant(strategy):
3636
assert result.enabled
3737
assert result.variant == {
3838
"enabled": True,
39-
"name": "VarB",
40-
"payload": {"type": "string", "value": "Test 2"},
39+
"name": "VarC",
40+
"payload": {"type": "string", "value": "Test 3"},
4141
}
4242

4343

tests/unit_tests/test_features.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ def test_select_variation_novariation(test_feature):
107107
def test_select_variation_variation(test_feature_variants):
108108
selected_variant = test_feature_variants.get_variant({"userId": "2"})
109109
assert selected_variant["enabled"]
110-
assert selected_variant["name"] == "VarB"
110+
assert selected_variant["name"] == "VarC"
111111

112112

113113
def test_variant_metrics_are_reset(test_feature_variants):
114114
test_feature_variants.get_variant({"userId": "2"})
115-
assert test_feature_variants.variant_counts["VarB"] == 1
115+
assert test_feature_variants.variant_counts["VarC"] == 1
116116

117117
test_feature_variants.reset_stats()
118118
assert not test_feature_variants.variant_counts
@@ -121,7 +121,7 @@ def test_variant_metrics_are_reset(test_feature_variants):
121121
def test_variant_metrics_with_existing_variant(test_feature_variants):
122122
for iteration in range(1, 7):
123123
test_feature_variants.get_variant({"userId": "2"})
124-
assert test_feature_variants.variant_counts["VarB"] == iteration
124+
assert test_feature_variants.variant_counts["VarC"] == iteration
125125

126126

127127
def test_variant_metrics_with_disabled_feature(test_feature_variants):
@@ -149,8 +149,8 @@ def test_strategy_variant_is_returned(test_feature_strategy_variants):
149149

150150
assert variant == {
151151
"enabled": True,
152-
"name": "VarB",
153-
"payload": {"type": "string", "value": "Test 2"},
152+
"name": "VarC",
153+
"payload": {"type": "string", "value": "Test 3"},
154154
}
155155

156156

tests/unit_tests/test_variants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def test_variation_selectvariation_happypath(variations):
5555
variant = variations.get_variant({"userId": "2"})
5656
assert variant
5757
assert "payload" in variant
58-
assert variant["name"] == "VarC"
58+
assert variant["name"] == "VarA"
5959

6060

6161
def test_variation_customvariation(variations_with_stickiness):

0 commit comments

Comments
 (0)