fix: issue create update n+1 and issue activity get n+1 (#1606)

* fix: issue create update n+1 and issue activity get n+1

* dev: notifications n+1
This commit is contained in:
Nikhil 2023-07-24 12:23:34 +05:30 committed by GitHub
parent 8ff834c328
commit e83ef7332d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 56 deletions

View File

@ -115,8 +115,15 @@ class IssueCreateSerializer(BaseSerializer):
labels = validated_data.pop("labels_list", None)
blocks = validated_data.pop("blocks_list", None)
project = self.context["project"]
issue = Issue.objects.create(**validated_data, project=project)
project_id = self.context["project_id"]
workspace_id = self.context["workspace_id"]
default_assignee_id = self.context["default_assignee_id"]
issue = Issue.objects.create(**validated_data, project_id=project_id)
# Issue Audit Users
created_by_id = issue.created_by_id
updated_by_id = issue.updated_by_id
if blockers is not None and len(blockers):
IssueBlocker.objects.bulk_create(
@ -124,10 +131,10 @@ class IssueCreateSerializer(BaseSerializer):
IssueBlocker(
block=issue,
blocked_by=blocker,
project=project,
workspace=project.workspace,
created_by=issue.created_by,
updated_by=issue.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for blocker in blockers
],
@ -140,10 +147,10 @@ class IssueCreateSerializer(BaseSerializer):
IssueAssignee(
assignee=user,
issue=issue,
project=project,
workspace=project.workspace,
created_by=issue.created_by,
updated_by=issue.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for user in assignees
],
@ -151,14 +158,14 @@ class IssueCreateSerializer(BaseSerializer):
)
else:
# Then assign it to default assignee
if project.default_assignee is not None:
if default_assignee_id is not None:
IssueAssignee.objects.create(
assignee=project.default_assignee,
assignee_id=default_assignee_id,
issue=issue,
project=project,
workspace=project.workspace,
created_by=issue.created_by,
updated_by=issue.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
if labels is not None and len(labels):
@ -167,10 +174,10 @@ class IssueCreateSerializer(BaseSerializer):
IssueLabel(
label=label,
issue=issue,
project=project,
workspace=project.workspace,
created_by=issue.created_by,
updated_by=issue.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for label in labels
],
@ -183,10 +190,10 @@ class IssueCreateSerializer(BaseSerializer):
IssueBlocker(
block=block,
blocked_by=issue,
project=project,
workspace=project.workspace,
created_by=issue.created_by,
updated_by=issue.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for block in blocks
],
@ -201,6 +208,12 @@ class IssueCreateSerializer(BaseSerializer):
labels = validated_data.pop("labels_list", None)
blocks = validated_data.pop("blocks_list", None)
# Related models
project_id = instance.project_id
workspace_id = instance.workspace_id
created_by_id = instance.created_by_id
updated_by_id = instance.updated_by_id
if blockers is not None:
IssueBlocker.objects.filter(block=instance).delete()
IssueBlocker.objects.bulk_create(
@ -208,10 +221,10 @@ class IssueCreateSerializer(BaseSerializer):
IssueBlocker(
block=instance,
blocked_by=blocker,
project=instance.project,
workspace=instance.project.workspace,
created_by=instance.created_by,
updated_by=instance.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for blocker in blockers
],
@ -225,10 +238,10 @@ class IssueCreateSerializer(BaseSerializer):
IssueAssignee(
assignee=user,
issue=instance,
project=instance.project,
workspace=instance.project.workspace,
created_by=instance.created_by,
updated_by=instance.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for user in assignees
],
@ -242,10 +255,10 @@ class IssueCreateSerializer(BaseSerializer):
IssueLabel(
label=label,
issue=instance,
project=instance.project,
workspace=instance.project.workspace,
created_by=instance.created_by,
updated_by=instance.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for label in labels
],
@ -259,16 +272,17 @@ class IssueCreateSerializer(BaseSerializer):
IssueBlocker(
block=block,
blocked_by=instance,
project=instance.project,
workspace=instance.project.workspace,
created_by=instance.created_by,
updated_by=instance.updated_by,
project_id=project_id,
workspace_id=workspace_id,
created_by_id=created_by_id,
updated_by_id=updated_by_id,
)
for block in blocks
],
batch_size=10,
)
# Time updation occues even when other related models are updated
instance.updated_at = timezone.now()
return super().update(instance, validated_data)

View File

@ -270,9 +270,15 @@ class IssueViewSet(BaseViewSet):
def create(self, request, slug, project_id):
try:
project = Project.objects.get(workspace__slug=slug, pk=project_id)
project = Project.objects.get(pk=project_id)
serializer = IssueCreateSerializer(
data=request.data, context={"project": project}
data=request.data,
context={
"project_id": project_id,
"workspace_id": project.workspace_id,
"default_assignee_id": project.default_assignee_id,
},
)
if serializer.is_valid():
@ -396,6 +402,7 @@ class IssueActivityEndpoint(BaseAPIView):
IssueComment.objects.filter(issue_id=issue_id)
.filter(project__project_projectmember__member=self.request.user)
.order_by("created_at")
.select_related("actor", "issue", "project", "workspace")
)
issue_activities = IssueActivitySerializer(issue_activities, many=True).data
issue_comments = IssueCommentSerializer(issue_comments, many=True).data
@ -1096,7 +1103,8 @@ class IssueArchiveViewSet(BaseViewSet):
return Response(IssueSerializer(issue).data, status=status.HTTP_200_OK)
except Issue.DoesNotExist:
return Response(
{"error": "Issue Does not exist"}, status=status.HTTP_404_NOT_FOUND)
{"error": "Issue Does not exist"}, status=status.HTTP_404_NOT_FOUND
)
except Exception as e:
capture_exception(e)
return Response(
@ -1104,6 +1112,7 @@ class IssueArchiveViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
class IssueSubscriberViewSet(BaseViewSet):
serializer_class = IssueSubscriberSerializer
model = IssueSubscriber
@ -1144,18 +1153,22 @@ class IssueSubscriberViewSet(BaseViewSet):
def list(self, request, slug, project_id, issue_id):
try:
members = ProjectMember.objects.filter(
workspace__slug=slug, project_id=project_id
).annotate(
is_subscribed=Exists(
IssueSubscriber.objects.filter(
workspace__slug=slug,
project_id=project_id,
issue_id=issue_id,
subscriber=OuterRef("member"),
members = (
ProjectMember.objects.filter(
workspace__slug=slug, project_id=project_id
)
.annotate(
is_subscribed=Exists(
IssueSubscriber.objects.filter(
workspace__slug=slug,
project_id=project_id,
issue_id=issue_id,
subscriber=OuterRef("member"),
)
)
)
).select_related("member")
.select_related("member")
)
serializer = ProjectMemberLiteSerializer(members, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
except Exception as e:

View File

@ -38,9 +38,13 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
# Filter type
type = request.GET.get("type", "all")
notifications = Notification.objects.filter(
workspace__slug=slug, receiver_id=request.user.id
).order_by("snoozed_till", "-created_at")
notifications = (
Notification.objects.filter(
workspace__slug=slug, receiver_id=request.user.id
)
.select_related("workspace", "project," "triggered_by", "receiver")
.order_by("snoozed_till", "-created_at")
)
# Filter for snoozed notifications
if snoozed == "false":