Skip to content

Commit 7e6fe08

Browse files
authored
perf(releases): bulk query for PRs in CommitSerializer (#87234)
I found the [p95 of /releases/](https://sentry.sentry.io/traces/?field=id&field=span.op&field=span.description&field=span.duration&field=transaction&field=timestamp&mode=aggregate&project=1&query=transaction%3A%2Fapi%2F0%2Forganizations%2F%7Borganization_id_or_slug%7D%2Freleases%2F&source=traces&statsPeriod=24h&targetId=8352cb4e96e0defb&visualize=%7B%22chartType%22%3A1%2C%22yAxes%22%3A%5B%22p95%28span.duration%29%22%5D%7D) transaction has an expensive serialize (`on_results`) step. In samples, I see that many PullRequest's are being queried individually, in a loop, from CommitWithReleaseSerializer. Ref #86806
1 parent 32f70c3 commit 7e6fe08

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

src/sentry/api/serializers/models/commit.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ def get_attrs(self, item_list, user, **kwargs):
5050
)
5151
)
5252

53-
pull_request_by_commit = {pr.merge_commit_sha: serialize(pr) for pr in pull_requests}
53+
pull_request_by_commit = {
54+
pr.merge_commit_sha: serialized_pr
55+
for (pr, serialized_pr) in zip(pull_requests, serialize(pull_requests))
56+
}
5457

5558
result = {}
5659
for item in item_list:

tests/sentry/api/serializers/test_commit.py

+65
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from sentry.api.serializers import serialize
44
from sentry.models.commit import Commit
55
from sentry.models.commitauthor import CommitAuthor
6+
from sentry.models.pullrequest import PullRequest
67
from sentry.models.release import Release
78
from sentry.models.releasecommit import ReleaseCommit
89
from sentry.models.repository import Repository
@@ -70,3 +71,67 @@ def test_no_author(self):
7071
result = serialize(commit, user)
7172

7273
assert result["author"] == {}
74+
75+
def test_pull_requests(self):
76+
"""Test we can correctly match pull requests to commits."""
77+
user = self.create_user()
78+
project = self.create_project()
79+
release = Release.objects.create(
80+
organization_id=project.organization_id, version=uuid4().hex
81+
)
82+
release.add_project(project)
83+
repository = Repository.objects.create(
84+
organization_id=project.organization_id, name="test/test"
85+
)
86+
commit1 = Commit.objects.create(
87+
organization_id=project.organization_id,
88+
repository_id=repository.id,
89+
key="abc",
90+
message="waddap",
91+
)
92+
ReleaseCommit.objects.create(
93+
organization_id=project.organization_id,
94+
project_id=project.id,
95+
release=release,
96+
commit=commit1,
97+
order=1,
98+
)
99+
100+
commit2 = Commit.objects.create(
101+
organization_id=project.organization_id,
102+
repository_id=repository.id,
103+
key="def",
104+
message="waddap2",
105+
)
106+
ReleaseCommit.objects.create(
107+
organization_id=project.organization_id,
108+
project_id=project.id,
109+
release=release,
110+
commit=commit2,
111+
order=2,
112+
)
113+
114+
PullRequest.objects.create(
115+
organization_id=project.organization_id,
116+
repository_id=repository.id,
117+
key="pr1",
118+
merge_commit_sha=commit1.key,
119+
)
120+
PullRequest.objects.create(
121+
organization_id=project.organization_id,
122+
repository_id=repository.id,
123+
key="pr2",
124+
merge_commit_sha=commit2.key,
125+
)
126+
PullRequest.objects.create(
127+
organization_id=project.organization_id,
128+
repository_id=repository.id,
129+
key="pr3",
130+
merge_commit_sha=commit1.key,
131+
)
132+
133+
results = serialize([commit1, commit2], user)
134+
135+
# In the case of multiple pull requests, one is chosen arbitrarily.
136+
assert results[0]["pullRequest"]["id"] == "pr1" or results[0]["pullRequest"]["id"] == "pr3"
137+
assert results[1]["pullRequest"]["id"] == "pr2"

0 commit comments

Comments
 (0)