Batch-load related data in actions run, job, and task API endpoints (#37032)
Avoid per-item DB queries in ListRuns, ListJobs, and ListActionTasks by batch-loading trigger users, repositories, and task attributes before the conversion loop. Remove ReferencesGitRepo from the /actions route group since no task/run endpoints use it. Added tests for these endpoints as well. --------- Signed-off-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
This commit is contained in:
@@ -71,11 +71,11 @@ func init() {
|
||||
db.RegisterModel(new(ActionRunIndex))
|
||||
}
|
||||
|
||||
func (run *ActionRun) HTMLURL() string {
|
||||
func (run *ActionRun) HTMLURL(ctxOpt ...context.Context) string {
|
||||
if run.Repo == nil {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s/actions/runs/%d", run.Repo.HTMLURL(), run.ID)
|
||||
return fmt.Sprintf("%s/actions/runs/%d", run.Repo.HTMLURL(ctxOpt...), run.ID)
|
||||
}
|
||||
|
||||
func (run *ActionRun) Link() string {
|
||||
@@ -120,11 +120,7 @@ func (run *ActionRun) RefTooltip() string {
|
||||
}
|
||||
|
||||
// LoadAttributes load Repo TriggerUser if not loaded
|
||||
func (run *ActionRun) LoadAttributes(ctx context.Context) (err error) {
|
||||
if run == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (run *ActionRun) LoadAttributes(ctx context.Context) error {
|
||||
if err := run.LoadRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -133,18 +129,19 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if run.TriggerUser == nil {
|
||||
run.TriggerUserID, run.TriggerUser, err = user_model.GetPossibleUserByID(ctx, run.TriggerUserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return run.LoadTriggerUser(ctx)
|
||||
}
|
||||
|
||||
return nil
|
||||
func (run *ActionRun) LoadTriggerUser(ctx context.Context) (err error) {
|
||||
if run.TriggerUser != nil {
|
||||
return nil
|
||||
}
|
||||
run.TriggerUserID, run.TriggerUser, err = user_model.GetPossibleUserByID(ctx, run.TriggerUserID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (run *ActionRun) LoadRepo(ctx context.Context) error {
|
||||
if run == nil || run.Repo != nil {
|
||||
if run.Repo != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -51,10 +51,6 @@ func (attempt *ActionRunAttempt) Duration() time.Duration {
|
||||
}
|
||||
|
||||
func (attempt *ActionRunAttempt) LoadAttributes(ctx context.Context) (err error) {
|
||||
if attempt == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if attempt.Run == nil {
|
||||
run, err := GetRunByRepoAndID(ctx, attempt.RepoID, attempt.RunID)
|
||||
if err != nil {
|
||||
|
||||
@@ -120,10 +120,6 @@ func (job *ActionRunJob) LoadRepo(ctx context.Context) error {
|
||||
|
||||
// LoadAttributes load Run if not loaded
|
||||
func (job *ActionRunJob) LoadAttributes(ctx context.Context) error {
|
||||
if job == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := job.LoadRun(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -56,8 +56,10 @@ func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error {
|
||||
return err
|
||||
}
|
||||
for _, j := range jobs {
|
||||
if j.RunID > 0 && j.Run == nil {
|
||||
if j.Run == nil {
|
||||
j.Run = runs[j.RunID]
|
||||
}
|
||||
if j.Run != nil {
|
||||
j.Run.Repo = j.Repo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
@@ -17,27 +18,39 @@ import (
|
||||
|
||||
type RunList []*ActionRun
|
||||
|
||||
// GetUserIDs returns a slice of user's id
|
||||
func (runs RunList) GetUserIDs() []int64 {
|
||||
return container.FilterSlice(runs, func(run *ActionRun) (int64, bool) {
|
||||
return run.TriggerUserID, true
|
||||
})
|
||||
}
|
||||
|
||||
func (runs RunList) LoadTriggerUser(ctx context.Context) error {
|
||||
userIDs := runs.GetUserIDs()
|
||||
userIDs := container.FilterSlice(runs, func(run *ActionRun) (int64, bool) {
|
||||
return run.TriggerUserID, run.TriggerUser == nil
|
||||
})
|
||||
users := make(map[int64]*user_model.User, len(userIDs))
|
||||
if err := db.GetEngine(ctx).In("id", userIDs).Find(&users); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, run := range runs {
|
||||
if run.TriggerUserID == user_model.ActionsUserID {
|
||||
run.TriggerUser = user_model.NewActionsUser()
|
||||
} else {
|
||||
run.TriggerUser = users[run.TriggerUserID]
|
||||
if run.TriggerUser == nil {
|
||||
run.TriggerUser = user_model.NewGhostUser()
|
||||
}
|
||||
if run.TriggerUser != nil {
|
||||
continue
|
||||
}
|
||||
run.TriggerUser = users[run.TriggerUserID]
|
||||
if run.TriggerUserID < 0 {
|
||||
run.TriggerUserID, run.TriggerUser, _ = user_model.GetPossibleUserByID(ctx, run.TriggerUserID)
|
||||
} else if run.TriggerUser == nil {
|
||||
run.TriggerUserID, run.TriggerUser, _ = user_model.GetPossibleUserByID(ctx, user_model.GhostUserID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (runs RunList) LoadRepos(ctx context.Context) error {
|
||||
repoIDs := container.FilterSlice(runs, func(run *ActionRun) (int64, bool) {
|
||||
return run.RepoID, run.Repo == nil
|
||||
})
|
||||
repos, err := repo_model.GetRepositoriesMapByIDs(ctx, repoIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, run := range runs {
|
||||
if run.Repo == nil {
|
||||
run.Repo = repos[run.RepoID]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -125,9 +125,6 @@ func (task *ActionTask) LoadJob(ctx context.Context) error {
|
||||
|
||||
// LoadAttributes load Job Steps if not loaded
|
||||
func (task *ActionTask) LoadAttributes(ctx context.Context) error {
|
||||
if task == nil {
|
||||
return nil
|
||||
}
|
||||
if err := task.LoadJob(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -376,8 +376,9 @@ func (repo *Repository) CommitLink(commitID string) (result string) {
|
||||
}
|
||||
|
||||
// APIURL returns the repository API URL
|
||||
func (repo *Repository) APIURL() string {
|
||||
return setting.AppURL + "api/v1/repos/" + url.PathEscape(repo.OwnerName) + "/" + url.PathEscape(repo.Name)
|
||||
func (repo *Repository) APIURL(ctxOpt ...context.Context) string {
|
||||
ctx := util.OptionalArg(ctxOpt, context.TODO())
|
||||
return httplib.MakeAbsoluteURL(ctx, setting.AppSubURL+"/api/v1/repos/"+url.PathEscape(repo.OwnerName)+"/"+url.PathEscape(repo.Name))
|
||||
}
|
||||
|
||||
// GetCommitsCountCacheKey returns cache key used for commits count caching.
|
||||
|
||||
Reference in New Issue
Block a user