Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 0 additions & 31 deletions api/environments/identities/helpers.py

This file was deleted.

45 changes: 13 additions & 32 deletions api/environments/identities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from django.db import models
from django.db.models import Prefetch, Q
from flag_engine.engine import get_evaluation_result

from environments.identities.managers import IdentityManager
from environments.identities.traits.models import Trait
Expand All @@ -11,15 +12,7 @@
from features.multivariate.models import MultivariateFeatureStateValue
from features.versioning.versioning_service import get_environment_flags_list
from segments.models import Segment
from util.engine_models.context.mappers import (
is_context_in_segment,
map_environment_identity_to_context,
)
from util.mappers.engine import (
map_identity_to_engine,
map_segment_to_engine,
map_traits_to_engine,
)
from util.mappers.engine import map_environment_to_evaluation_context


class Identity(models.Model):
Expand Down Expand Up @@ -154,7 +147,6 @@ def get_segments(
:param overrides_only: only retrieve the segments which have a valid override in the environment
:return: List of matching segments
"""
matching_segments = []
db_traits = (
self.identity_traits.all() if (traits is None and self.id) else traits or []
)
Expand All @@ -164,29 +156,18 @@ def get_segments(
else:
all_segments = self.environment.project.get_segments_from_cache()

engine_identity = map_identity_to_engine(
self,
with_overrides=False,
with_traits=False,
segments_by_pk = {segment.pk: segment for segment in all_segments}
context = map_environment_to_evaluation_context(
identity=self,
environment=self.environment,
traits=db_traits,
segments=all_segments,
)
engine_traits = map_traits_to_engine(db_traits)

for segment in all_segments:
engine_segment = map_segment_to_engine(segment)

context = map_environment_identity_to_context(
environment=self.environment,
identity=engine_identity,
override_traits=engine_traits,
)

if is_context_in_segment(
context=context,
segment=engine_segment,
):
matching_segments.append(segment)

return matching_segments
result = get_evaluation_result(context)
return [
segments_by_pk[segment_result["metadata"]["pk"]]
for segment_result in result["segments"]
]

def get_all_user_traits(self): # type: ignore[no-untyped-def]
# this is pointless, we should probably replace all uses with the below code
Expand Down
8 changes: 3 additions & 5 deletions api/features/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
LifecycleModelMixin,
hook,
)
from flag_engine.utils.hashing import get_hashed_percentage_for_object_ids
from ordered_model.models import OrderedModelBase # type: ignore[import-untyped]
from simple_history.models import HistoricalRecords # type: ignore[import-untyped]

Expand All @@ -49,9 +50,6 @@
SoftDeleteExportableModel,
abstract_base_auditable_model_factory,
)
from environments.identities.helpers import (
get_hashed_percentage_for_object_ids,
)
from features.constants import ENVIRONMENT, FEATURE_SEGMENT, IDENTITY
from features.custom_lifecycle import CustomLifecycleModelMixin
from features.feature_states.models import AbstractBaseFeatureValueModel
Expand Down Expand Up @@ -750,8 +748,8 @@ def get_multivariate_feature_state_value(
# avoid further queries to the DB
mv_options = list(self.multivariate_feature_state_values.all())

percentage_value = (
get_hashed_percentage_for_object_ids([self.id, identity_hash_key]) * 100
percentage_value = get_hashed_percentage_for_object_ids(
[self.id, identity_hash_key]
)

# Iterate over the mv options in order of id (so we get the same value each
Expand Down
24 changes: 9 additions & 15 deletions api/integrations/webhook/serializers.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import typing

from django.db.models import Q
from flag_engine.engine import get_evaluation_result
from rest_framework import serializers

from features.serializers import FeatureStateSerializerFull
from integrations.common.serializers import (
BaseEnvironmentIntegrationModelSerializer,
)
from segments.models import Segment
from util.engine_models.context.mappers import is_context_in_segment
from util.mappers.engine import (
map_engine_identity_to_context,
map_identity_to_engine,
map_segment_to_engine,
)
from util.mappers.engine import map_environment_to_evaluation_context

from .models import WebhookConfiguration

Expand All @@ -32,16 +28,14 @@ class Meta:
fields = ("id", "name", "member")

def get_member(self, obj: Segment) -> bool:
engine_identity = map_identity_to_engine(
self.context.get("identity"), # type: ignore[arg-type]
with_overrides=False,
)
engine_segment = map_segment_to_engine(obj)
context = map_engine_identity_to_context(engine_identity)
return is_context_in_segment(
context=context,
segment=engine_segment,
identity = self.context["identity"]
context = map_environment_to_evaluation_context(
identity=identity,
environment=identity.environment,
segments=[obj],
)
result = get_evaluation_result(context)
return bool(result["segments"])


class IntegrationFeatureStateSerializer(FeatureStateSerializerFull):
Expand Down
5 changes: 5 additions & 0 deletions api/segments/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from typing_extensions import TypedDict


class SegmentEngineMetadata(TypedDict):
pk: int
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
@pytest.mark.parametrize(
"hashed_percentage, expected_mv_value",
(
(variant_1_percentage_allocation / 100 - 0.01, variant_1_value),
(total_variance_percentage / 100 - 0.01, variant_2_value),
(total_variance_percentage / 100 + 0.01, control_value),
(variant_1_percentage_allocation - 1, variant_1_value),
(total_variance_percentage - 1, variant_2_value),
(total_variance_percentage + 1, control_value),
),
)
@mock.patch("features.models.get_hashed_percentage_for_object_ids")
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
STRING,
)
from environments.identities import views
from environments.identities.helpers import (
get_hashed_percentage_for_object_ids,
)
from environments.identities.models import Identity
from environments.identities.traits.models import Trait
from environments.models import Environment, EnvironmentAPIKey
Expand Down Expand Up @@ -598,14 +595,9 @@ def test_identities_endpoint_returns_value_for_segment_if_rule_type_percentage_s
segment=segment, type=SegmentRule.ALL_RULE
)

identity_percentage_value = get_hashed_percentage_for_object_ids(
[segment.id, identity.id]
)
Condition.objects.create(
operator=PERCENTAGE_SPLIT,
value=int(
(identity_percentage_value + (1 - identity_percentage_value) / 2) * 100.0
),
value=100,
rule=segment_rule,
)
feature_segment = FeatureSegment.objects.create(
Expand Down Expand Up @@ -651,12 +643,9 @@ def test_identities_endpoint_returns_default_value_if_rule_type_percentage_split
segment=segment, type=SegmentRule.ALL_RULE
)

identity_percentage_value = get_hashed_percentage_for_object_ids(
[segment.id, identity.id]
)
Condition.objects.create(
operator=PERCENTAGE_SPLIT,
value=int(identity_percentage_value / 2),
value=0,
rule=segment_rule,
)
feature_segment = FeatureSegment.objects.create(
Expand Down
2 changes: 1 addition & 1 deletion api/tests/unit/features/test_unit_features_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ def test_feature_state_type_feature_segment(
assert feature_state.type == FEATURE_SEGMENT


@pytest.mark.parametrize("hashed_percentage", (0.0, 0.3, 0.5, 0.8, 0.999999))
@pytest.mark.parametrize("hashed_percentage", (0.0, 30.0, 50.0, 80.0, 99.9999))
@mock.patch("features.models.get_hashed_percentage_for_object_ids")
def test_get_multivariate_value_returns_correct_value_when_we_pass_identity( # type: ignore[no-untyped-def]
mock_get_hashed_percentage,
Expand Down
Loading
Loading