Browse Source

Revert "chore(hybrid-cloud): Break queries that depend on cross silo FKs (#45095)"

This reverts commit 2d87621f5f52323a7b371e478a601d65ae2f2c02.

Co-authored-by: corps <593850+corps@users.noreply.github.com>
getsentry-bot 2 years ago
parent
commit
da6cf991dd

+ 2 - 2
src/sentry/api/endpoints/project_transaction_threshold.py

@@ -90,7 +90,7 @@ class ProjectTransactionThresholdEndpoint(ProjectEndpoint):
                 )
                 project_threshold.threshold = data.get("threshold") or project_threshold.threshold
                 project_threshold.metric = data.get("metric") or project_threshold.metric
-                project_threshold.edited_by_id = request.user.id
+                project_threshold.edited_by = request.user
                 project_threshold.save()
 
                 created = False
@@ -101,7 +101,7 @@ class ProjectTransactionThresholdEndpoint(ProjectEndpoint):
                     organization=project.organization,
                     threshold=data.get("threshold", 300),
                     metric=data.get("metric", TransactionMetric.DURATION.value),
-                    edited_by_id=request.user.id,
+                    edited_by=request.user,
                 )
 
                 created = True

+ 1 - 1
src/sentry/api/endpoints/project_transaction_threshold_override.py

@@ -117,7 +117,7 @@ class ProjectTransactionThresholdOverrideEndpoint(OrganizationEventsV2EndpointBa
                 defaults={
                     "threshold": data["threshold"],
                     "metric": data["metric"],
-                    "edited_by_id": request.user.id,
+                    "edited_by": request.user,
                 },
             )
 

+ 6 - 24
src/sentry/api/helpers/group_index/update.py

@@ -49,7 +49,7 @@ from sentry.models.group import STATUS_UPDATE_CHOICES
 from sentry.models.grouphistory import record_group_history_from_activity_type
 from sentry.models.groupinbox import GroupInboxRemoveAction, add_group_to_inbox
 from sentry.notifications.types import SUBSCRIPTION_REASON_MAP, GroupSubscriptionReason
-from sentry.services.hybrid_cloud.user import RpcUser, user_service
+from sentry.services.hybrid_cloud.user import RpcUser
 from sentry.signals import (
     issue_ignored,
     issue_mark_reviewed,
@@ -61,6 +61,7 @@ from sentry.tasks.integrations import kick_off_status_syncs
 from sentry.tasks.merge import merge_groups
 from sentry.types.activity import ActivityType
 from sentry.utils import metrics
+from sentry.utils.functional import extract_lazy_object
 
 from . import ACTIVITIES_COUNT, BULK_MUTATION_LIMIT, SearchFunction, delete_group_list
 from .validators import GroupValidator, ValidationError
@@ -279,15 +280,10 @@ def update_groups(
                 # no version yet
                 "version": ""
             }
-
-            serialized_user = user_service.serialize_many(
-                filter=dict(user_ids=[user.id]), as_user=user
-            )
             status_details = {
                 "inNextRelease": True,
+                "actor": serialize(extract_lazy_object(user), user),
             }
-            if serialized_user:
-                status_details["actor"] = serialized_user[0]
             res_type = GroupResolution.Type.in_next_release
             res_type_str = "in_next_release"
             res_status = GroupResolution.Status.pending
@@ -305,15 +301,10 @@ def update_groups(
                 # no version yet
                 "version": release.version
             }
-
-            serialized_user = user_service.serialize_many(
-                filter=dict(user_ids=[user.id]), as_user=user
-            )
             status_details = {
                 "inRelease": release.version,
+                "actor": serialize(extract_lazy_object(user), user),
             }
-            if serialized_user:
-                status_details["actor"] = serialized_user[0]
             res_type = GroupResolution.Type.in_release
             res_type_str = "in_release"
             res_status = GroupResolution.Status.resolved
@@ -327,15 +318,10 @@ def update_groups(
             commit = statusDetails["inCommit"]
             activity_type = ActivityType.SET_RESOLVED_IN_COMMIT.value
             activity_data = {"commit": commit.id}
-            serialized_user = user_service.serialize_many(
-                filter=dict(user_ids=[user.id]), as_user=user
-            )
-
             status_details = {
                 "inCommit": serialize(commit, user),
+                "actor": serialize(extract_lazy_object(user), user),
             }
-            if serialized_user:
-                status_details["actor"] = serialized_user[0]
             res_type_str = "in_commit"
         else:
             res_type_str = "now"
@@ -586,18 +572,14 @@ def update_groups(
                                 "actor_id": user.id if user.is_authenticated else None,
                             },
                         )
-                        serialized_user = user_service.serialize_many(
-                            filter=dict(user_ids=[user.id]), as_user=user
-                        )
                         result["statusDetails"] = {
                             "ignoreCount": ignore_count,
                             "ignoreUntil": ignore_until,
                             "ignoreUserCount": ignore_user_count,
                             "ignoreUserWindow": ignore_user_window,
                             "ignoreWindow": ignore_window,
+                            "actor": serialize(extract_lazy_object(user), user),
                         }
-                        if serialized_user:
-                            result["statusDetails"]["actor"] = serialized_user[0]
                 else:
                     GroupSnooze.objects.filter(group__in=group_ids).delete()
                     ignore_until = None

+ 12 - 20
src/sentry/api/serializers/models/alert_rule.py

@@ -1,5 +1,4 @@
 from collections import defaultdict
-from typing import MutableMapping
 
 from django.db.models import Max, prefetch_related_objects
 
@@ -24,7 +23,6 @@ from sentry.models import (
     fetch_actors_by_actor_ids,
 )
 from sentry.services.hybrid_cloud.app import app_service
-from sentry.services.hybrid_cloud.user import RpcUser, user_service
 from sentry.snuba.models import SnubaQueryEventType
 
 
@@ -72,32 +70,26 @@ class AlertRuleSerializer(Serializer):
             rule_result = result[alert_rules[alert_rule_id]].setdefault("projects", [])
             rule_result.append(project_slug)
 
-        rule_activities = list(
-            AlertRuleActivity.objects.filter(
-                alert_rule__in=item_list, type=AlertRuleActivityType.CREATED.value
-            )
-        )
-
-        use_by_user_id: MutableMapping[int, RpcUser] = {
-            user.id: user
-            for user in user_service.get_many(
-                filter=dict(user_ids=[r.user_id for r in rule_activities])
-            )
-        }
-        for rule_activity in rule_activities:
-            rpc_user = use_by_user_id.get(rule_activity.user_id)
-            if rpc_user:
-                user = dict(id=rpc_user.id, name=rpc_user.get_display_name(), email=rpc_user.email)
+        for rule_activity in AlertRuleActivity.objects.filter(
+            alert_rule__in=item_list, type=AlertRuleActivityType.CREATED.value
+        ).select_related("alert_rule", "user"):
+            if rule_activity.user:
+                user = {
+                    "id": rule_activity.user.id,
+                    "name": rule_activity.user.get_display_name(),
+                    "email": rule_activity.user.email,
+                }
             else:
                 user = None
-            result[alert_rules[rule_activity.alert_rule_id]]["created_by"] = user
 
+            result[alert_rules[rule_activity.alert_rule.id]].update({"created_by": user})
+
+        resolved_actors = {}
         owners_by_type = defaultdict(list)
         for item in item_list:
             if item.owner_id is not None:
                 owners_by_type[actor_type_to_string(item.owner.type)].append(item.owner_id)
 
-        resolved_actors = {}
         for k, v in ACTOR_TYPES.items():
             resolved_actors[k] = {
                 a.actor_id: a.id

+ 18 - 12
src/sentry/api/serializers/models/discoversavedquery.py

@@ -1,28 +1,34 @@
 from collections import defaultdict
 
-from sentry.api.serializers import Serializer, register
+from django.db.models.query import prefetch_related_objects
+
+from sentry.api.serializers import Serializer, register, serialize
+from sentry.api.serializers.models.user import UserSerializer
 from sentry.constants import ALL_ACCESS_PROJECTS
 from sentry.discover.models import DiscoverSavedQuery
-from sentry.services.hybrid_cloud.user import user_service
 from sentry.utils.dates import outside_retention_with_modified_start, parse_timestamp
 
 
 @register(DiscoverSavedQuery)
 class DiscoverSavedQuerySerializer(Serializer):
     def get_attrs(self, item_list, user):
+        prefetch_related_objects(item_list, "created_by")
+
         result = defaultdict(lambda: {"created_by": {}})
 
-        service_serialized = user_service.serialize_many(
-            filter={
-                "user_ids": [
-                    discover_saved_query.created_by_id
+        user_serializer = UserSerializer()
+        serialized_users = {
+            user["id"]: user
+            for user in serialize(
+                [
+                    discover_saved_query.created_by
                     for discover_saved_query in item_list
-                    if discover_saved_query.created_by_id
-                ]
-            },
-            as_user=user,
-        )
-        serialized_users = {user["id"]: user for user in service_serialized}
+                    if discover_saved_query.created_by
+                ],
+                user=user,
+                serializer=user_serializer,
+            )
+        }
 
         for discover_saved_query in item_list:
             result[discover_saved_query]["created_by"] = serialized_users.get(

+ 13 - 19
src/sentry/api/serializers/models/exporteddata.py

@@ -1,31 +1,25 @@
-from sentry.api.serializers import Serializer, register
+from sentry.api.serializers import Serializer, register, serialize
 from sentry.data_export.base import ExportQueryType
 from sentry.data_export.models import ExportedData
-from sentry.services.hybrid_cloud.user import user_service
+from sentry.models import User
 
 
 @register(ExportedData)
 class ExportedDataSerializer(Serializer):
     def get_attrs(self, item_list, user, **kwargs):
         attrs = {}
-        serialized_users = {
-            u["id"]: u
-            for u in user_service.serialize_many(
-                filter=dict(user_ids=[item.user_id for item in item_list])
-            )
-        }
+        users = User.objects.filter(id__in={item.user_id for item in item_list})
+        user_lookup = {user.id: user for user in users}
         for item in item_list:
-            if str(item.user_id) in serialized_users:
-                serialized_user = serialized_users[str(item.user_id)]
-                attrs[item] = {
-                    "user": {
-                        "id": serialized_user["id"],
-                        "email": serialized_user["email"],
-                        "username": serialized_user["username"],
-                    }
+            user = user_lookup[item.user_id]
+            serialized_user = serialize(user)
+            attrs[item] = {
+                "user": {
+                    "id": serialized_user["id"],
+                    "email": serialized_user["email"],
+                    "username": serialized_user["username"],
                 }
-            else:
-                attrs[item] = {}
+            }
         return attrs
 
     def serialize(self, obj, attrs, user, **kwargs):
@@ -39,7 +33,7 @@ class ExportedDataSerializer(Serializer):
 
         return {
             "id": obj.id,
-            "user": attrs.get("user"),
+            "user": attrs["user"],
             "dateCreated": obj.date_added,
             "dateFinished": obj.date_finished,
             "dateExpired": obj.date_expired,

+ 18 - 27
src/sentry/api/serializers/models/group.py

@@ -15,7 +15,6 @@ from typing import (
     Optional,
     Protocol,
     Sequence,
-    Set,
     Tuple,
     TypedDict,
     Union,
@@ -36,6 +35,7 @@ from sentry.auth.superuser import is_active_superuser
 from sentry.constants import LOG_LEVELS
 from sentry.issues.grouptype import GroupCategory
 from sentry.models import (
+    ActorTuple,
     Commit,
     Environment,
     Group,
@@ -183,32 +183,19 @@ class GroupSerializerBase(Serializer, ABC):
         self.collapse = collapse
         self.expand = expand
 
-    def _serialize_assignees(self, item_list: Sequence[Group]) -> Mapping[int, Union[Team, Any]]:
-        gas = GroupAssignee.objects.filter(group__in=item_list)
-        result: MutableMapping[int, Union[Team, Any]] = {}
-        all_team_ids: MutableMapping[int, Set[int]] = {}
-        all_user_ids: MutableMapping[int, Set[int]] = {}
-
-        for g in gas:
-            if g.team_id:
-                if g.team_id not in all_team_ids:
-                    all_team_ids[g.team_id] = {g.group_id}
-                else:
-                    all_team_ids[g.team_id].add(g.group_id)
-            if g.user_id:
-                if g.team_id not in all_team_ids:
-                    all_user_ids[g.user_id] = {g.group_id}
-                else:
-                    all_user_ids[g.user_id].add(g.group_id)
-
-        for team in Team.objects.filter(id__in=all_team_ids.keys()):
-            for group_id in all_team_ids[team.id]:
-                result[group_id] = team
-        for user in user_service.get_many(filter=dict(user_ids=list(all_user_ids.keys()))):
-            for group_id in all_user_ids[user.id]:
-                result[group_id] = user
+    def _serialize_assigness(
+        self, actor_dict: Mapping[int, ActorTuple]
+    ) -> Mapping[int, Union[Team, Any]]:
+        actors_by_type: MutableMapping[Any, List[ActorTuple]] = defaultdict(list)
+        for actor in actor_dict.values():
+            actors_by_type[actor.type].append(actor)
 
-        return result
+        resolved_actors = {}
+        for t, actors in actors_by_type.items():
+            serializable = ActorTuple.resolve_many(actors)
+            resolved_actors[t] = {actor.id: actor for actor in serializable}
+
+        return {key: resolved_actors[value.type][value.id] for key, value in actor_dict.items()}
 
     def get_attrs(
         self, item_list: Sequence[Group], user: Any, **kwargs: Any
@@ -236,7 +223,11 @@ class GroupSerializerBase(Serializer, ABC):
             seen_groups = {}
             subscriptions = defaultdict(lambda: (False, False, None))
 
-        resolved_assignees = self._serialize_assignees(item_list)
+        assignees: Mapping[int, ActorTuple] = {
+            a.group_id: a.assigned_actor()
+            for a in GroupAssignee.objects.filter(group__in=item_list)
+        }
+        resolved_assignees = self._serialize_assigness(assignees)
 
         ignore_items = {g.group_id: g for g in GroupSnooze.objects.filter(group__in=item_list)}
 

+ 6 - 4
src/sentry/api/serializers/models/incident.py

@@ -44,7 +44,9 @@ class IncidentSerializer(Serializer):
 
         if "seen_by" in self.expand:
             incident_seen_list = list(
-                IncidentSeen.objects.filter(incident__in=item_list).order_by("-last_seen")
+                IncidentSeen.objects.filter(incident__in=item_list)
+                .select_related("user")
+                .order_by("-last_seen")
             )
             incident_seen_dict = defaultdict(list)
             for incident_seen, serialized_seen_by in zip(
@@ -106,9 +108,9 @@ class DetailedIncidentSerializer(IncidentSerializer):
         subscribed_incidents = set()
         if user.is_authenticated:
             subscribed_incidents = set(
-                IncidentSubscription.objects.filter(
-                    incident__in=item_list, user_id=user.id
-                ).values_list("incident_id", flat=True)
+                IncidentSubscription.objects.filter(incident__in=item_list, user=user).values_list(
+                    "incident_id", flat=True
+                )
             )
 
         for item in item_list:

+ 8 - 4
src/sentry/api/serializers/models/incidentactivity.py

@@ -1,16 +1,20 @@
 from django.db.models import prefetch_related_objects
 
-from sentry.api.serializers import Serializer, register
+from sentry.api.serializers import Serializer, register, serialize
+from sentry.api.serializers.models.user import UserSerializer
 from sentry.incidents.models import IncidentActivity
-from sentry.services.hybrid_cloud.user import user_service
 
 
 @register(IncidentActivity)
 class IncidentActivitySerializer(Serializer):
     def get_attrs(self, item_list, user, **kwargs):
         prefetch_related_objects(item_list, "incident__organization")
-        serialized_users = user_service.serialize_many(
-            filter={"user_ids": [i.user_id for i in item_list if i.user_id]}, as_user=user
+        prefetch_related_objects(item_list, "user")
+        user_serializer = UserSerializer()
+        serialized_users = serialize(
+            {item.user for item in item_list if item.user_id},
+            user=user,
+            serializer=user_serializer,
         )
         user_lookup = {user["id"]: user for user in serialized_users}
         return {item: {"user": user_lookup.get(str(item.user_id))} for item in item_list}

+ 5 - 11
src/sentry/api/serializers/models/incidentseen.py

@@ -1,20 +1,14 @@
-from sentry.api.serializers import Serializer, register
+from django.db.models import prefetch_related_objects
+
+from sentry.api.serializers import Serializer, register, serialize
 from sentry.incidents.models import IncidentSeen
-from sentry.services.hybrid_cloud.user import user_service
 
 
 @register(IncidentSeen)
 class IncidentSeenSerializer(Serializer):
     def get_attrs(self, item_list, user):
-        user_map = {
-            d["id"]: d
-            for d in user_service.serialize_many(
-                filter={
-                    "user_ids": [i.user_id for i in item_list],
-                },
-                as_user=user,
-            )
-        }
+        prefetch_related_objects(item_list, "user")
+        user_map = {d["id"]: d for d in serialize({i.user for i in item_list}, user)}
 
         result = {}
         for item in item_list:

Some files were not shown because too many files changed in this diff