perf(pull): load the repository once for all commit statuses (#39930)

Pages showing commit statuses loaded the repository of every status
separately, so a PR with ~75 statuses ran ~75 identical repository
queries per merge box render (about 3.4s in a production trace).
`statusRepoCanReadActions` only loaded the repository inside the
permission cache loader, which never runs once `RepoAssignment` has
published the permission.

- `CommitStatus.loadRepository` resolves through the request context
cache
- `statusRepoCanReadActions` loads the repository before the permission
lookup
- `RepoAssignment` publishes its repository to the context cache next to
the permission
- `GetCommitActionsStatusMap` drops its own repository map

Queries per request with 50 statuses (45 Actions, 5 external) on the
head commit, SQLite:

| Page | Repository queries | Total queries |
|---|---|---|
| PR view | 61 → 11 | 157 → 107 |
| Commit | 6 → 5 | 24 → 23 |
| Branches | 6 → 5 | 33 → 32 |
| Commits | 6 → 5 | 23 → 22 |
| Repo home | 8 → 7 | 35 → 34 |
| `/pulls` | 15 → 15 | 37 → 37 |

---------

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
Lunny Xiaoandsilverwind authored and GitHub committed 2026-10-31 17:32:03 +01:00
1 parent bbb8ef8244
commit 40507491f7
5 files changed
+17 -22

No files matched your search

+4 -1
View File
@@ -13,6 +13,7 @@ import (
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
user_model "gitea.dev/models/user"
"gitea.dev/modules/cache"
"gitea.dev/modules/commitstatus"
"gitea.dev/modules/git"
@@ -200,8 +201,10 @@ func TestCommitStatusesApplyDoerPermission(t *testing.T) {
},
}
git_model.CommitStatusesApplyDoerPermission(t.Context(), doer, statuses)
git_model.CommitStatusesApplyDoerPermission(cache.WithCacheContext(t.Context()), doer, statuses)
assert.Equal(t, visibleURL, statuses[0].TargetURL)
assert.Empty(t, statuses[1].TargetURL)
assert.Equal(t, "https://mycicd.org/1", statuses[2].TargetURL)
assert.NotNil(t, statuses[0].Repo)
assert.Same(t, statuses[0].Repo, statuses[2].Repo)
}