Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
khvn26 committed Jul 10, 2024
1 parent f5a7eed commit a47b4bc
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 17 deletions.
21 changes: 20 additions & 1 deletion api/environments/identities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,12 @@ def update_traits(self, trait_data_items):
keys_to_delete = []
new_traits = []
updated_traits = []
transient_traits = []

for trait_data_item in trait_data_items:
trait_key = trait_data_item["trait_key"]
trait_value = trait_data_item["trait_value"]
transient = trait_data_item["transient"]

if trait_value is None:
# build a list of trait keys to delete having been nulled by the
Expand All @@ -257,9 +259,20 @@ def update_traits(self, trait_data_items):
if current_trait.trait_value == trait_value:
continue

if transient:
transient_traits.append(
Trait(**trait_value_data, trait_key=trait_key, identity=self)
)
continue

for attr, value in trait_value_data.items():
setattr(current_trait, attr, value)
updated_traits.append(current_trait)

elif transient:
transient_traits.append(
Trait(**trait_value_data, trait_key=trait_key, identity=self)
)
else:
new_traits.append(
Trait(**trait_value_data, trait_key=trait_key, identity=self)
Expand All @@ -278,5 +291,11 @@ def update_traits(self, trait_data_items):
Trait.objects.bulk_create(new_traits, ignore_conflicts=True)

# return the full list of traits for this identity by refreshing from the db
# override persisted traits by transient traits in case of key collisions
# TODO: handle this in the above logic to avoid a second hit to the DB
return self.identity_traits.all()
return [
*{
trait.trait_key: trait
for trait in (self.identity_traits.all() + transient_traits)
}.values()
]
1 change: 1 addition & 0 deletions api/environments/identities/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class _TraitSerializer(serializers.Serializer):

class SDKIdentitiesQuerySerializer(serializers.Serializer):
identifier = serializers.CharField(required=True)
transient = serializers.BooleanField(default=False)


class IdentityAllFeatureStatesFeatureSerializer(serializers.Serializer):
Expand Down
1 change: 1 addition & 0 deletions api/environments/identities/traits/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def get_trait_value(obj):

class TraitSerializerBasic(serializers.ModelSerializer):
trait_value = TraitValueField(allow_null=True)
transient = serializers.BooleanField(default=False)

class Meta:
model = Trait
Expand Down
16 changes: 11 additions & 5 deletions api/environments/identities/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,17 @@ def get(self, request):
{"detail": "Missing identifier"}
) # TODO: add 400 status - will this break the clients?

identity, _ = Identity.objects.get_or_create_for_sdk(
identifier=identifier,
environment=request.environment,
integrations=IDENTITY_INTEGRATIONS,
)
if request.query_params.get("transient"):
identity = Identity(
identifier=identifier,
environment=request.environment,
)
else:
identity, _ = Identity.objects.get_or_create_for_sdk(
identifier=identifier,
environment=request.environment,
integrations=IDENTITY_INTEGRATIONS,
)
self.identity = identity

if settings.EDGE_API_URL and request.environment.project.enable_dynamo_db:
Expand Down
33 changes: 22 additions & 11 deletions api/environments/sdk/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class IdentifyWithTraitsSerializer(
HideSensitiveFieldsSerializerMixin, serializers.Serializer
):
identifier = serializers.CharField(write_only=True, required=True)
transient = serializers.BooleanField(write_only=True, default=False)
traits = TraitSerializerBasic(required=False, many=True)
flags = SDKFeatureStateSerializer(read_only=True, many=True)

Expand All @@ -136,23 +137,33 @@ def save(self, **kwargs):
(optionally store traits if flag set on org)
"""
environment = self.context["environment"]
identity, created = Identity.objects.get_or_create(
identifier=self.validated_data["identifier"], environment=environment
)

transient = self.validated_data["transient"]
trait_data_items = self.validated_data.get("traits", [])

if not created and environment.project.organisation.persist_trait_data:
# if this is an update and we're persisting traits, then we need to
# partially update any traits and return the full list
trait_models = identity.update_traits(trait_data_items)
if transient:
identity = Identity(
identifier=self.validated_data["identifier"],
environment=environment,
)
trait_models = identity.generate_traits(trait_data_items, persist=False)

else:
# generate traits for the identity and store them if configured to do so
trait_models = identity.generate_traits(
trait_data_items,
persist=environment.project.organisation.persist_trait_data,
identity, created = Identity.objects.get_or_create(
identifier=self.validated_data["identifier"], environment=environment
)

if not created and environment.project.organisation.persist_trait_data:
# if this is an update and we're persisting traits, then we need to
# partially update any traits and return the full list
trait_models = identity.update_traits(trait_data_items)
else:
# generate traits for the identity and store them if configured to do so
trait_models = identity.generate_traits(
trait_data_items,
persist=environment.project.organisation.persist_trait_data,
)

all_feature_states = identity.get_all_feature_states(
traits=trait_models,
additional_filters=self.context.get("feature_states_additional_filters"),
Expand Down

0 comments on commit a47b4bc

Please sign in to comment.