Optimize GET /users internal api endpoint (#4168)

# What this PR does
Speed up `GET /users` internal api endpoint by reducing number of calls
to database

## Which issue(s) this PR closes
Related to slow schedules page issue -
https://github.com/grafana/oncall-private/issues/1552
## Checklist

- [ ] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
This commit is contained in:
Yulya Artyukhina 2024-04-11 16:49:47 +02:00 committed by GitHub
parent 6a5267b847
commit 08ce22b59b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 37 additions and 8 deletions

View file

@ -88,7 +88,14 @@ class ListUserSerializer(DynamicFieldsModelSerializer, EagerLoadingMixin):
cloud_connection_status = serializers.SerializerMethodField()
working_hours = WorkingHoursSerializer(required=False)
SELECT_RELATED = ["telegram_verification_code", "telegram_connection", "organization", "slack_user_identity"]
SELECT_RELATED = [
"telegram_verification_code",
"telegram_connection",
"organization",
"slack_user_identity",
"mobileappauthtoken",
"google_oauth2_user",
]
class Meta:
model = User
@ -159,7 +166,13 @@ class ListUserSerializer(DynamicFieldsModelSerializer, EagerLoadingMixin):
return {"default": " - ".join(default), "important": " - ".join(important)}
def get_cloud_connection_status(self, obj: User) -> CloudSyncStatus | None:
if settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED:
is_open_source_with_cloud_notifications = self.context.get("is_open_source_with_cloud_notifications", None)
is_open_source_with_cloud_notifications = (
is_open_source_with_cloud_notifications
if is_open_source_with_cloud_notifications is not None
else settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED
)
if is_open_source_with_cloud_notifications:
connector = self.context.get("connector", None)
identities = self.context.get("cloud_identities", {})
identity = identities.get(obj.email, None)

View file

@ -137,7 +137,13 @@ class CurrentUserView(APIView, CachedSchedulesContextMixin):
context = self.get_serializer_context()
context.update({"request": self.request, "format": self.format_kwarg, "view": self})
if settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED:
is_open_source_with_cloud_notifications = (
settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED
)
# set context to avoid additional requests to db
context["is_open_source_with_cloud_notifications"] = is_open_source_with_cloud_notifications
if is_open_source_with_cloud_notifications:
from apps.oss_installation.models import CloudConnector, CloudUserIdentity
connector = CloudConnector.objects.first()
@ -368,7 +374,13 @@ class UserView(
context = self.get_serializer_context()
if paginate_results and (page := self.paginate_queryset(queryset)) is not None:
if settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED:
is_open_source_with_cloud_notifications = (
settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED
)
# set context to avoid additional requests to db
context["is_open_source_with_cloud_notifications"] = is_open_source_with_cloud_notifications
if is_open_source_with_cloud_notifications:
from apps.oss_installation.models import CloudConnector, CloudUserIdentity
if (connector := CloudConnector.objects.first()) is not None:
@ -393,7 +405,13 @@ class UserView(
except NotFound:
return self.wrong_team_response()
if settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED:
is_open_source_with_cloud_notifications = (
settings.IS_OPEN_SOURCE and live_settings.GRAFANA_CLOUD_NOTIFICATIONS_ENABLED
)
# set context to avoid additional requests to db
context["is_open_source_with_cloud_notifications"] = is_open_source_with_cloud_notifications
if is_open_source_with_cloud_notifications:
from apps.oss_installation.models import CloudConnector, CloudUserIdentity
connector = CloudConnector.objects.first()

View file

@ -42,9 +42,7 @@ class MobileAppBackend(BaseMessagingBackend):
user_active_device.delete()
def serialize_user(self, user):
from apps.mobile_app.models import MobileAppAuthToken
return {"connected": MobileAppAuthToken.objects.filter(user=user).exists()}
return {"connected": getattr(user, "mobileappauthtoken", None) is not None}
def notify_user(self, user, alert_group, notification_policy, critical=False):
notify_user_about_new_alert_group.delay(