Browse Source

ref(notifications): remove more notification hc methods (#60669)

We don't need to query/serialize the notification settings tables
anymore as that logic is all encapsulated in the control silo. This PR
removes unused methods from the notification service.
Stephen Cefali 1 year ago
parent
commit
441d708e6b

+ 0 - 1
src/sentry/api/serializers/models/__init__.py

@@ -39,7 +39,6 @@ from .incidentseen import *  # noqa: F401,F403
 from .integration import *  # noqa: F401,F403
 from .integration_feature import *  # noqa: F401,F403
 from .notification_action import *  # noqa: F401,F403
-from .notification_setting import *  # noqa: F401,F403
 from .organization import *  # noqa: F401,F403
 from .organization_access_request import *  # noqa: F401,F403
 from .organization_member.base import *  # noqa: F401,F403

+ 0 - 112
src/sentry/api/serializers/models/notification_setting.py

@@ -1,112 +0,0 @@
-from collections import defaultdict
-from typing import Any, Iterable, Mapping, MutableMapping, Optional, Set, Union
-
-from sentry.api.serializers import Serializer
-from sentry.models.notificationsetting import NotificationSetting
-from sentry.models.team import Team
-from sentry.models.user import User
-from sentry.notifications.types import NotificationSettingTypes
-from sentry.services.hybrid_cloud.organization import RpcTeam
-from sentry.services.hybrid_cloud.user import RpcUser
-
-
-class NotificationSettingsSerializer(Serializer):
-    """
-    This Serializer fetches and serializes NotificationSettings for a list of
-    targets (users or teams.) Pass filters like `project=project` and
-    `type=NotificationSettingTypes.DEPLOY` to kwargs.
-    """
-
-    def get_attrs(
-        self,
-        item_list: Iterable[Union["Team", "User"]],
-        user: User,
-        **kwargs: Any,
-    ) -> MutableMapping[Union["Team", "User"], MutableMapping[str, Set[Any]]]:
-        """
-        This takes a list of recipients (which are either Users or Teams,
-        because both can have Notification Settings). The function
-        returns a mapping of targets to flat lists of object to be passed to the
-        `serialize` function.
-
-        :param item_list: Either a Set of User or Team objects whose
-            notification settings should be serialized.
-        :param user: The user who will be viewing the notification settings.
-        :param kwargs: Dict of optional filter options:
-            - type: NotificationSettingTypes enum value. e.g. WORKFLOW, DEPLOY.
-        """
-        type_option: Optional[NotificationSettingTypes] = kwargs.get("type")
-
-        team_map = {t.id: t for t in item_list if isinstance(t, (Team, RpcTeam))}
-        user_map = {u.id: u for u in item_list if isinstance(u, (User, RpcUser))}
-
-        notifications_settings = NotificationSetting.objects._filter(
-            type=type_option,
-            team_ids=list(team_map.keys()),
-            user_ids=list(user_map.keys()),
-        )
-
-        result: MutableMapping[Union[Team, User], MutableMapping[str, Set[Any]]] = defaultdict(
-            lambda: defaultdict(set)
-        )
-        for _, team in team_map.items():
-            result[team]["settings"] = set()
-        for _, user in user_map.items():
-            result[user]["settings"] = set()
-
-        for notifications_setting in notifications_settings:
-            if notifications_setting.user_id:
-                target_user = user_map[notifications_setting.user_id]
-                result[target_user]["settings"].add(notifications_setting)
-            elif notifications_setting.team_id:
-                target_team = team_map[notifications_setting.team_id]
-                result[target_team]["settings"].add(notifications_setting)
-            else:
-                raise ValueError(
-                    f"NotificationSetting {notifications_setting.id} has neither team_id nor user_id"
-                )
-        return result
-
-    def serialize(
-        self,
-        obj: Union[Team, User],
-        attrs: Mapping[str, Iterable[Any]],
-        user: User,
-        **kwargs: Any,
-    ) -> Mapping[str, Mapping[str, Mapping[int, Mapping[str, str]]]]:
-        """
-        Convert a user or team's NotificationSettings to a python object
-        comprised of primitives. This will backfill all possible notification
-        settings with the appropriate defaults.
-
-        Example: {
-            "workflow": {
-                "project": {
-                    1: {
-                        "email": "always",
-                        "slack": "always"
-                    },
-                    2: {
-                        "email": "subscribe_only",
-                        "slack": "subscribe_only"
-                    }
-                }
-            }
-        }
-
-        :param obj: A user or team.
-        :param attrs: The `obj` target's NotificationSettings
-        :param user: The user who will be viewing the NotificationSettings.
-        :param kwargs: The same `kwargs` as `get_attrs`.
-        :returns A mapping. See example.
-        """
-
-        data: MutableMapping[
-            str, MutableMapping[str, MutableMapping[int, MutableMapping[str, str]]]
-        ] = defaultdict(lambda: defaultdict(lambda: defaultdict(dict)))
-
-        # Forgive the variable name, I wanted the following lines to be legible.
-        for n in attrs["settings"]:
-            # Override the notification settings.
-            data[n.type_str][n.scope_str][n.scope_identifier][n.provider_str] = n.value_str
-        return data

+ 3 - 63
src/sentry/services/hybrid_cloud/notifications/impl.py

@@ -1,12 +1,9 @@
 from __future__ import annotations
 
-from typing import Callable, List, Mapping, MutableMapping, Optional, Tuple
+from typing import List, Mapping, MutableMapping, Optional, Tuple
 
 from django.db import router, transaction
-from django.db.models import QuerySet
 
-from sentry.api.serializers.base import Serializer
-from sentry.api.serializers.models.notification_setting import NotificationSettingsSerializer
 from sentry.models.notificationsetting import NotificationSetting
 from sentry.models.notificationsettingoption import NotificationSettingOption
 from sentry.models.notificationsettingprovider import NotificationSettingProvider
@@ -19,15 +16,7 @@ from sentry.notifications.types import (
     NotificationSettingsOptionEnum,
 )
 from sentry.services.hybrid_cloud.actor import ActorType, RpcActor
-from sentry.services.hybrid_cloud.auth.model import AuthenticationContext
-from sentry.services.hybrid_cloud.filter_query import (
-    FilterQueryDatabaseImpl,
-    OpaqueSerializedResponse,
-)
-from sentry.services.hybrid_cloud.notifications import NotificationsService, RpcNotificationSetting
-from sentry.services.hybrid_cloud.notifications.model import NotificationSettingFilterArgs
-from sentry.services.hybrid_cloud.notifications.serial import serialize_notification_setting
-from sentry.services.hybrid_cloud.user import RpcUser
+from sentry.services.hybrid_cloud.notifications import NotificationsService
 from sentry.services.hybrid_cloud.user.service import user_service
 from sentry.types.integrations import ExternalProviderEnum, ExternalProviders
 
@@ -117,9 +106,6 @@ class DatabaseBackedNotificationsService(NotificationsService):
     ) -> None:
         self.remove_notification_settings(team_id=team_id, user_id=None, provider=provider)
 
-    def get_many(self, *, filter: NotificationSettingFilterArgs) -> List[RpcNotificationSetting]:
-        return self._FQ.get_many(filter)
-
     def remove_notification_settings_for_organization(self, *, organization_id: int) -> None:
         assert organization_id, "organization_id must be a positive integer"
         NotificationSetting.objects.remove_for_organization(organization_id=organization_id)
@@ -143,15 +129,6 @@ class DatabaseBackedNotificationsService(NotificationsService):
             scope_identifier=project_id,
         ).delete()
 
-    def serialize_many(
-        self,
-        *,
-        filter: NotificationSettingFilterArgs,
-        as_user: Optional[RpcUser] = None,
-        auth_context: Optional[AuthenticationContext] = None,
-    ) -> List[OpaqueSerializedResponse]:
-        return self._FQ.serialize_many(filter, as_user, auth_context)
-
     def get_subscriptions_for_projects(
         self,
         *,
@@ -173,6 +150,7 @@ class DatabaseBackedNotificationsService(NotificationsService):
         )
         return {
             project: (s.is_disabled, s.is_active, s.has_only_inactive_subscriptions)
+            # TODO(Steve): Simplify API to pass in one project at a time
             for project, s in controller.get_subscriptions_status_for_projects(
                 user=user, project_ids=project_ids, type=type
             ).items()
@@ -228,41 +206,3 @@ class DatabaseBackedNotificationsService(NotificationsService):
         )
         raw_output = controller.get_notification_recipients(type=type, actor_type=actor_type)
         return {str(provider.name): actors for provider, actors in raw_output.items()}
-
-    class _NotificationSettingsQuery(
-        FilterQueryDatabaseImpl[
-            NotificationSetting, NotificationSettingFilterArgs, RpcNotificationSetting, None
-        ],
-    ):
-        def apply_filters(
-            self, query: QuerySet[NotificationSetting], filters: NotificationSettingFilterArgs
-        ) -> QuerySet[NotificationSetting]:
-            if "provider" in filters and filters["provider"] is not None:
-                query = query.filter(provider=filters["provider"])
-            if "type" in filters and filters["type"] is not None:
-                query = query.filter(type=filters["type"].value)
-            if "scope_type" in filters and filters["scope_type"] is not None:
-                query = query.filter(scope_type=filters["scope_type"])
-            if "scope_identifier" in filters and filters["scope_identifier"] is not None:
-                query = query.filter(scope_identifier=filters["scope_identifier"])
-            if "user_ids" in filters and len(filters["user_ids"]) > 0:
-                query = query.filter(user_id__in=filters["user_ids"])
-            if "team_ids" in filters and len(filters["team_ids"]) > 0:
-                query = query.filter(team_id__in=filters["team_ids"])
-            return query.all()
-
-        def base_query(self, ids_only: bool = False) -> QuerySet[NotificationSetting]:
-            return NotificationSetting.objects
-
-        def filter_arg_validator(self) -> Callable[[NotificationSettingFilterArgs], Optional[str]]:
-            return self._filter_has_any_key_validator("user_ids", "team_ids")
-
-        def serialize_api(self, serializer_type: Optional[None]) -> Serializer:
-            return NotificationSettingsSerializer()
-
-        def serialize_rpc(
-            self, notification_setting: NotificationSetting
-        ) -> RpcNotificationSetting:
-            return serialize_notification_setting(notification_setting)
-
-    _FQ = _NotificationSettingsQuery()

+ 0 - 21
src/sentry/services/hybrid_cloud/notifications/service.py

@@ -11,12 +11,7 @@ from sentry.notifications.types import (
     NotificationSettingsOptionEnum,
 )
 from sentry.services.hybrid_cloud.actor import ActorType, RpcActor
-from sentry.services.hybrid_cloud.auth.model import AuthenticationContext
-from sentry.services.hybrid_cloud.filter_query import OpaqueSerializedResponse
-from sentry.services.hybrid_cloud.notifications import RpcNotificationSetting
-from sentry.services.hybrid_cloud.notifications.model import NotificationSettingFilterArgs
 from sentry.services.hybrid_cloud.rpc import RpcService, rpc_method
-from sentry.services.hybrid_cloud.user import RpcUser
 from sentry.silo import SiloMode
 from sentry.types.integrations import ExternalProviderEnum, ExternalProviders
 
@@ -65,22 +60,6 @@ class NotificationsService(RpcService):
     ) -> None:
         pass
 
-    @rpc_method
-    @abstractmethod
-    def get_many(self, *, filter: NotificationSettingFilterArgs) -> List[RpcNotificationSetting]:
-        pass
-
-    @rpc_method
-    @abstractmethod
-    def serialize_many(
-        self,
-        *,
-        filter: NotificationSettingFilterArgs,
-        as_user: Optional[RpcUser] = None,
-        auth_context: Optional[AuthenticationContext] = None,
-    ) -> List[OpaqueSerializedResponse]:
-        pass
-
     @rpc_method
     @abstractmethod
     def remove_notification_settings_for_organization(self, *, organization_id: int) -> None: