perf: eliminate N+1 in IssueSerializer and dedupe cycle conflict check#4
Draft
d0cd wants to merge 1 commit into
Draft
perf: eliminate N+1 in IssueSerializer and dedupe cycle conflict check#4d0cd wants to merge 1 commit into
d0cd wants to merge 1 commit into
Conversation
…ict check - IssueSerializer.to_representation now reads assignees/labels from the existing prefetched M2M cache instead of issuing fresh IssueAssignee / IssueLabel filter queries per instance. The view's get_queryset already prefetches both relations, so every issue serialized in a list endpoint was wasting up to 4 extra queries. - CycleListCreate.post collapses the duplicate "exists check then refetch" pair into a single .first() lookup. Run-on: Niteshift Staging Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
IssueSerializer.to_representation(apps/api/plane/api/serializers/issue.py): replaced four freshIssueAssignee.objects.filter(issue=instance)/IssueLabel.objects.filter(issue=instance)queries with reads against the M2M prefetch cache that the view already populates viaprefetch_related(\"assignees\", \"labels\"). Listing N issues went from O(N) extra DB round-trips per relation to zero.CycleListCreateAPIEndpoint.post(apps/api/plane/api/views/cycle.py): the external-id conflict check ran the sameCycle.objects.filter(...)twice (once as.exists(), once as.first()). Collapsed into a single.first()lookup.These are two of the highest-impact, lowest-risk wins surfaced by an audit of the public REST API hot paths.
Test plan
GET /api/v1/workspaces/<slug>/projects/<pid>/issues/returns the same payload (assignees + labels arrays of UUID strings)?expand=assignees,labelsstill returns expanded user/label objectsdjango-debug-toolbar(or Django ORM logging) that issue list endpoints no longer fan out per-issue assignee/label queriesPOST /api/v1/.../cycles/with a duplicateexternal_id/external_sourcepair still returns 409 with the existing cycle id🤖 Generated with Claude Code
🌒 Run on Niteshift: View Task