Percentage split and variant hash collide when segment key equals feature key
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 3/5
- Temps estimé
- 1-2 jours
- Accessibilité débutants
- 78/100
Piste de recherche
Start in segments/evaluator.py at the PERCENTAGE_SPLIT handling and variant selection, then trace the get_evaluation_result entry point used by the reproduction. Verify that percentage splits and multivariate variants no longer collide when their keys match, and rerun the 1,000-identity example to confirm both variants are served.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Bug
A percentage split segment and a multivariate feature hash the same inputs when the segment key equals the feature key:
- the split hashes
[segment_key, identity_key](segments/evaluator.py,PERCENTAGE_SPLIT) - the variant hashes
[feature_key, identity_key](segments/evaluator.py, variant selection)
Both give the same number. An identity is only in a 50% split when that number is 50 or below, so it always lands in the first variant. The other variants are never served to anyone in the segment.
Segment and feature keys are ids from different tables, so they can be equal by chance.
Reproduction
from flag_engine.utils.hashing import get_hashed_percentage_for_object_ids as h
identity = "user-1"
assert h(["95", identity]) == h(["95", identity]) # split == variant
End to end: a segment with a 50% split on $.identity.key, overriding a feature with two 50/50 variants, evaluated for 1000 identities:
from collections import Counter
from flag_engine.engine import get_evaluation_result
def variants(segment_key: str, feature_key: str) -> Counter[str]:
context = {
"environment": {"key": "env", "name": "env"},
"segments": {
segment_key: {
"key": segment_key,
"name": "rollout",
"rules": [{"type": "ALL", "conditions": [
{"property": "$.identity.key", "operator": "PERCENTAGE_SPLIT", "value": "50"},
]}],
"overrides": [{
"key": feature_key, "name": "checkout", "enabled": True, "value": "control",
"variants": [
{"value": "a", "weight": 50, "priority": 0, "key": "variant-a"},
{"value": "b", "weight": 50, "priority": 1, "key": "variant-b"},
],
}],
}
},
"features": {"checkout": {"key": "1", "name": "checkout", "enabled": False, "value": None}},
}
counts: Counter[str] = Counter()
for i in range(1000):
context["identity"] = {"identifier": f"user-{i}", "key": f"user-{i}"}
flag = get_evaluation_result(context)["flags"]["checkout"]
if flag["enabled"]:
counts[flag["variant"]] += 1
return counts
print(variants("95", "96")) # Counter({'variant-b': 260, 'variant-a': 254})
print(variants("95", "95")) # Counter({'variant-a': 514})
Impact
Any segment override with variants on a percentage split segment whose key equals the feature key serves only one variant to the whole segment. For an experiment rollout, the experiment has a single arm. Seen in Flagsmith's API tests in Flagsmith/flagsmith#8646.
- Langage dominant
- Python
- Étoiles
- 10
- Forks
- 5
- Merge moyen
- 7 j 22 h
- PR mergées (30 j)
- 1
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de Flagsmith/flagsmith-engine
-
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
Flagsmith/flagsmith-engine#340 ·
-
Dependency DashboardOuverte
Difficulté 1/5 Moins d'une heure Accessibilité débutants 25/100
Flagsmith/flagsmith-engine#306 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 45/100
Flagsmith/flagsmith-engine#231 ·
-
Difficulté 1/5 1-3 heures Accessibilité débutants 55/100
Flagsmith/flagsmith-engine#207 · 2 commentaires ·
-
error: global flags not at the start of the expression at position 1Peut-être à nouveau libre @khvn26 l’a pris il y a 1059 jours, et aucune pull request n’est ouverte. Ouvertebug
Flagsmith/flagsmith-engine#196 · 1 commentaire · 1 personne assignée ·
Toutes les issues de Flagsmith/flagsmith-engine
Issues similaires
-
Validate non-divisible effective batch sizes in the Unsloth LoRA backendPeut-être pris @debesh-biswas l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
-
`rx.Model` event arguments emit `PydanticDeprecatedSince20` once per payload keyPeut-être pris Une pull request liée à cette issue est ouverte ou déjà fusionnée. Ouverte
Difficulté 1/5 Moins d'une heure Accessibilité débutants 88/100
reflex-dev/reflex#7634 · 1 commentaire ·
Les mainteneurs répondent en général sous 2 jours
-
documentation
Difficulté 1/5 1-3 heures Accessibilité débutants 82/100
topoteretes/cognee#6239 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
ranaroussi/yfinance#3009 ·
Les mainteneurs répondent en général sous 1 jour
-
Test discovery aborts on GPU builds without cuStateVec: check_cuStateVec expects a failed result but set_config() now raises RuntimeErrorPeut-être pris @dmeliksetian l’a pris aujourd’hui. Ouvertebug
Difficulté 2/5 1-3 heures Accessibilité débutants 84/100
Qiskit/qiskit-aer#2495 ·
Les mainteneurs répondent en général sous 1 jour