Skip to content

Commit d06acd3

Browse files
authored
feat: Backend for Context values (#5798)
1 parent 28821fa commit d06acd3

File tree

6 files changed

+51
-14
lines changed

6 files changed

+51
-14
lines changed

api/environments/dynamodb/wrappers/identity_wrapper.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
from boto3.dynamodb.conditions import Attr, Key
88
from django.conf import settings
99
from django.core.exceptions import ObjectDoesNotExist
10+
from flag_engine.context.mappers import map_environment_identity_to_context
1011
from flag_engine.environments.models import EnvironmentModel
1112
from flag_engine.identities.models import IdentityModel
12-
from flag_engine.segments.evaluator import get_identity_segments
13+
from flag_engine.segments.evaluator import get_context_segments
1314
from rest_framework.exceptions import NotFound
1415

1516
from edge_api.identities.search import EdgeIdentitySearchData
@@ -189,7 +190,12 @@ def get_segment_ids(
189190
environment = EnvironmentModel.model_validate(
190191
environment_wrapper.get_item(identity.environment_api_key)
191192
)
192-
segments = get_identity_segments(environment, identity)
193+
context = map_environment_identity_to_context(
194+
environment=environment,
195+
identity=identity,
196+
override_traits=None,
197+
)
198+
segments = get_context_segments(context, environment.project.segments)
193199
return [segment.id for segment in segments]
194200

195201
return []

api/environments/identities/models.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
from django.db import models
55
from django.db.models import Prefetch, Q
6-
from flag_engine.segments.evaluator import evaluate_identity_in_segment
6+
from flag_engine.context.mappers import map_environment_identity_to_context
7+
from flag_engine.segments.evaluator import is_context_in_segment
78

89
from environments.identities.managers import IdentityManager
910
from environments.identities.traits.models import Trait
@@ -170,10 +171,15 @@ def get_segments(
170171
for segment in all_segments:
171172
engine_segment = map_segment_to_engine(segment)
172173

173-
if evaluate_identity_in_segment(
174+
context = map_environment_identity_to_context(
175+
environment=self.environment,
174176
identity=engine_identity,
175-
segment=engine_segment,
176177
override_traits=engine_traits,
178+
)
179+
180+
if is_context_in_segment(
181+
context=context,
182+
segment=engine_segment,
177183
):
178184
matching_segments.append(segment)
179185

api/integrations/webhook/serializers.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import typing
22

33
from django.db.models import Q
4-
from flag_engine.segments.evaluator import evaluate_identity_in_segment
4+
from flag_engine.segments.evaluator import is_context_in_segment
55
from rest_framework import serializers
66

77
from features.serializers import FeatureStateSerializerFull
88
from integrations.common.serializers import (
99
BaseEnvironmentIntegrationModelSerializer,
1010
)
1111
from segments.models import Segment
12-
from util.mappers.engine import map_identity_to_engine, map_segment_to_engine
12+
from util.mappers.engine import (
13+
map_engine_identity_to_context,
14+
map_identity_to_engine,
15+
map_segment_to_engine,
16+
)
1317

1418
from .models import WebhookConfiguration
1519

@@ -33,8 +37,9 @@ def get_member(self, obj: Segment) -> bool:
3337
with_overrides=False,
3438
)
3539
engine_segment = map_segment_to_engine(obj)
36-
return evaluate_identity_in_segment(
37-
identity=engine_identity,
40+
context = map_engine_identity_to_context(engine_identity)
41+
return is_context_in_segment(
42+
context=context,
3843
segment=engine_segment,
3944
)
4045

api/poetry.lock

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ environs = "^14.1.1"
133133
django-lifecycle = "~1.2.4"
134134
drf-writable-nested = "~0.6.2"
135135
django-filter = "~2.4.0"
136-
flagsmith-flag-engine = "^5.3.0"
136+
flagsmith-flag-engine = "^5.4.3"
137137
boto3 = "~1.35.95"
138138
slack-sdk = "~3.9.0"
139139
asgiref = "~3.8.1"

api/util/mappers/engine.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import TYPE_CHECKING, Dict, List, Optional
44
from uuid import UUID
55

6+
from flag_engine.context.types import EvaluationContext
67
from flag_engine.environments.integrations.models import IntegrationModel
78
from flag_engine.environments.models import (
89
EnvironmentAPIKeyModel,
@@ -418,6 +419,26 @@ def map_identity_to_engine(
418419
)
419420

420421

422+
def map_engine_identity_to_context(
423+
identity: IdentityModel,
424+
) -> "EvaluationContext":
425+
"""
426+
A special mapper to produce a minimal EvaluationContext
427+
in an environment-less form.
428+
Used when an environment object is not available, like when evaluating segments for webhooks.
429+
"""
430+
return {
431+
"environment": {"key": identity.environment_api_key, "name": ""},
432+
"identity": {
433+
"identifier": identity.identifier,
434+
"key": str(identity.django_id or identity.composite_key),
435+
"traits": {
436+
trait.trait_key: trait.trait_value for trait in identity.identity_traits
437+
},
438+
},
439+
}
440+
441+
421442
def _get_prioritised_feature_states(
422443
feature_states: Iterable["FeatureState"],
423444
) -> List["FeatureState"]:

0 commit comments

Comments
 (0)