loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request 'feat: improve `GetLatestCommitStatusForPairs`' (#5983) from gusted/improve-commit-pairs into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5983
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>

Gusted 146824ba eaa66f85

+191 -39
+31 -1
models/fixtures/commit_status.yml
··· 7 7 target_url: https://example.com/builds/ 8 8 description: My awesome CI-service 9 9 context: ci/awesomeness 10 + context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7 10 11 creator_id: 2 11 12 12 13 - ··· 18 19 target_url: https://example.com/coverage/ 19 20 description: My awesome Coverage service 20 21 context: cov/awesomeness 22 + context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe 21 23 creator_id: 2 22 24 23 25 - ··· 29 31 target_url: https://example.com/coverage/ 30 32 description: My awesome Coverage service 31 33 context: cov/awesomeness 34 + context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe 32 35 creator_id: 2 33 36 34 37 - ··· 40 43 target_url: https://example.com/builds/ 41 44 description: My awesome CI-service 42 45 context: ci/awesomeness 46 + context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7 43 47 creator_id: 2 44 48 45 49 - ··· 51 55 target_url: https://example.com/builds/ 52 56 description: My awesome deploy service 53 57 context: deploy/awesomeness 58 + context_hash: ae9547713a6665fc4261d0756904932085a41cf2 54 59 creator_id: 2 55 60 56 61 - 57 62 id: 6 58 - index: 6 63 + index: 1 59 64 repo_id: 62 60 65 state: "failure" 61 66 sha: "774f93df12d14931ea93259ae93418da4482fcc1" 62 67 target_url: "/user2/test_workflows/actions" 63 68 description: My awesome deploy service 64 69 context: deploy/awesomeness 70 + context_hash: ae9547713a6665fc4261d0756904932085a41cf2 71 + creator_id: 2 72 + 73 + - 74 + id: 7 75 + index: 6 76 + repo_id: 1 77 + state: "pending" 78 + sha: "1234123412341234123412341234123412341234" 79 + target_url: https://example.com/builds/ 80 + description: My awesome deploy service 81 + context: deploy/awesomeness 82 + context_hash: ae9547713a6665fc4261d0756904932085a41cf2 83 + creator_id: 2 84 + 85 + - 86 + id: 8 87 + index: 2 88 + repo_id: 62 89 + state: "error" 90 + sha: "774f93df12d14931ea93259ae93418da4482fcc1" 91 + target_url: "/user2/test_workflows/actions" 92 + description: "My awesome deploy service - v2" 93 + context: deploy/awesomeness 94 + context_hash: ae9547713a6665fc4261d0756904932085a41cf2 65 95 creator_id: 2
+8 -35
models/git/commit_status.go
··· 288 288 289 289 // GetLatestCommitStatusForPairs returns all statuses with a unique context for a given list of repo-sha pairs 290 290 func GetLatestCommitStatusForPairs(ctx context.Context, repoSHAs []RepoSHA) (map[int64][]*CommitStatus, error) { 291 - type result struct { 292 - Index int64 293 - RepoID int64 294 - SHA string 295 - } 296 - 297 - results := make([]result, 0, len(repoSHAs)) 298 - 299 - getBase := func() *xorm.Session { 300 - return db.GetEngine(ctx).Table(&CommitStatus{}) 301 - } 291 + results := []*CommitStatus{} 302 292 303 293 // Create a disjunction of conditions for each repoID and SHA pair 304 294 conds := make([]builder.Cond, 0, len(repoSHAs)) 305 295 for _, repoSHA := range repoSHAs { 306 296 conds = append(conds, builder.Eq{"repo_id": repoSHA.RepoID, "sha": repoSHA.SHA}) 307 297 } 308 - sess := getBase().Where(builder.Or(conds...)). 309 - Select("max( `index` ) as `index`, repo_id, sha"). 310 - GroupBy("context_hash, repo_id, sha").OrderBy("max( `index` ) desc") 311 298 299 + sess := db.GetEngine(ctx).Table(&CommitStatus{}). 300 + Select("MAX(`index`) AS `index`, *"). 301 + Where(builder.Or(conds...)). 302 + GroupBy("context_hash, repo_id, sha").OrderBy("MAX(`index`) DESC") 312 303 err := sess.Find(&results) 313 304 if err != nil { 314 305 return nil, err ··· 316 307 317 308 repoStatuses := make(map[int64][]*CommitStatus) 318 309 319 - if len(results) > 0 { 320 - statuses := make([]*CommitStatus, 0, len(results)) 321 - 322 - conds = make([]builder.Cond, 0, len(results)) 323 - for _, result := range results { 324 - cond := builder.Eq{ 325 - "`index`": result.Index, 326 - "repo_id": result.RepoID, 327 - "sha": result.SHA, 328 - } 329 - conds = append(conds, cond) 330 - } 331 - err = getBase().Where(builder.Or(conds...)).Find(&statuses) 332 - if err != nil { 333 - return nil, err 334 - } 335 - 336 - // Group the statuses by repo ID 337 - for _, status := range statuses { 338 - repoStatuses[status.RepoID] = append(repoStatuses[status.RepoID], status) 339 - } 310 + // Group the statuses by repo ID 311 + for _, status := range results { 312 + repoStatuses[status.RepoID] = append(repoStatuses[status.RepoID], status) 340 313 } 341 314 342 315 return repoStatuses, nil
+152 -3
models/git/commit_status_test.go
··· 35 35 SHA: sha1, 36 36 }) 37 37 require.NoError(t, err) 38 - assert.Equal(t, 5, int(maxResults)) 39 - assert.Len(t, statuses, 5) 38 + assert.EqualValues(t, 6, maxResults) 39 + assert.Len(t, statuses, 6) 40 40 41 41 assert.Equal(t, "ci/awesomeness", statuses[0].Context) 42 42 assert.Equal(t, structs.CommitStatusPending, statuses[0].State) ··· 58 58 assert.Equal(t, structs.CommitStatusError, statuses[4].State) 59 59 assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL(db.DefaultContext)) 60 60 61 + assert.Equal(t, "deploy/awesomeness", statuses[5].Context) 62 + assert.Equal(t, structs.CommitStatusPending, statuses[5].State) 63 + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[5].APIURL(db.DefaultContext)) 64 + 61 65 statuses, maxResults, err = db.FindAndCount[git_model.CommitStatus](db.DefaultContext, &git_model.CommitStatusOptions{ 62 66 ListOptions: db.ListOptions{Page: 2, PageSize: 50}, 63 67 RepoID: repo1.ID, 64 68 SHA: sha1, 65 69 }) 66 70 require.NoError(t, err) 67 - assert.Equal(t, 5, int(maxResults)) 71 + assert.EqualValues(t, 6, maxResults) 68 72 assert.Empty(t, statuses) 69 73 } 70 74 ··· 265 269 assert.Empty(t, statuses[0].TargetURL) 266 270 assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL) 267 271 } 272 + 273 + func TestGetLatestCommitStatusForPairs(t *testing.T) { 274 + require.NoError(t, unittest.PrepareTestDatabase()) 275 + 276 + t.Run("All", func(t *testing.T) { 277 + pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, nil) 278 + require.NoError(t, err) 279 + 280 + assert.EqualValues(t, map[int64][]*git_model.CommitStatus{ 281 + 1: { 282 + { 283 + ID: 7, 284 + Index: 6, 285 + RepoID: 1, 286 + State: structs.CommitStatusPending, 287 + SHA: "1234123412341234123412341234123412341234", 288 + TargetURL: "https://example.com/builds/", 289 + Description: "My awesome deploy service", 290 + ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2", 291 + Context: "deploy/awesomeness", 292 + CreatorID: 2, 293 + }, 294 + { 295 + ID: 4, 296 + Index: 4, 297 + State: structs.CommitStatusFailure, 298 + TargetURL: "https://example.com/builds/", 299 + Description: "My awesome CI-service", 300 + Context: "ci/awesomeness", 301 + CreatorID: 2, 302 + RepoID: 1, 303 + SHA: "1234123412341234123412341234123412341234", 304 + ContextHash: "c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7", 305 + }, 306 + { 307 + ID: 3, 308 + Index: 3, 309 + State: structs.CommitStatusSuccess, 310 + TargetURL: "https://example.com/coverage/", 311 + Description: "My awesome Coverage service", 312 + Context: "cov/awesomeness", 313 + CreatorID: 2, 314 + RepoID: 1, 315 + SHA: "1234123412341234123412341234123412341234", 316 + ContextHash: "3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe", 317 + }, 318 + }, 319 + 62: { 320 + { 321 + ID: 8, 322 + Index: 2, 323 + RepoID: 62, 324 + State: structs.CommitStatusError, 325 + TargetURL: "/user2/test_workflows/actions", 326 + Description: "My awesome deploy service - v2", 327 + Context: "deploy/awesomeness", 328 + SHA: "774f93df12d14931ea93259ae93418da4482fcc1", 329 + ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2", 330 + CreatorID: 2, 331 + }, 332 + }, 333 + }, pairs) 334 + }) 335 + 336 + t.Run("Repo 1", func(t *testing.T) { 337 + pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{1, "1234123412341234123412341234123412341234"}}) 338 + require.NoError(t, err) 339 + 340 + assert.EqualValues(t, map[int64][]*git_model.CommitStatus{ 341 + 1: { 342 + { 343 + ID: 7, 344 + Index: 6, 345 + RepoID: 1, 346 + State: structs.CommitStatusPending, 347 + SHA: "1234123412341234123412341234123412341234", 348 + TargetURL: "https://example.com/builds/", 349 + Description: "My awesome deploy service", 350 + ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2", 351 + Context: "deploy/awesomeness", 352 + CreatorID: 2, 353 + }, 354 + { 355 + ID: 4, 356 + Index: 4, 357 + State: structs.CommitStatusFailure, 358 + TargetURL: "https://example.com/builds/", 359 + Description: "My awesome CI-service", 360 + Context: "ci/awesomeness", 361 + CreatorID: 2, 362 + RepoID: 1, 363 + SHA: "1234123412341234123412341234123412341234", 364 + ContextHash: "c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7", 365 + }, 366 + { 367 + ID: 3, 368 + Index: 3, 369 + State: structs.CommitStatusSuccess, 370 + TargetURL: "https://example.com/coverage/", 371 + Description: "My awesome Coverage service", 372 + Context: "cov/awesomeness", 373 + CreatorID: 2, 374 + RepoID: 1, 375 + SHA: "1234123412341234123412341234123412341234", 376 + ContextHash: "3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe", 377 + }, 378 + }, 379 + }, pairs) 380 + }) 381 + t.Run("Repo 62", func(t *testing.T) { 382 + pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{62, "774f93df12d14931ea93259ae93418da4482fcc1"}}) 383 + require.NoError(t, err) 384 + 385 + assert.EqualValues(t, map[int64][]*git_model.CommitStatus{ 386 + 62: { 387 + { 388 + ID: 8, 389 + Index: 2, 390 + RepoID: 62, 391 + State: structs.CommitStatusError, 392 + TargetURL: "/user2/test_workflows/actions", 393 + Description: "My awesome deploy service - v2", 394 + Context: "deploy/awesomeness", 395 + SHA: "774f93df12d14931ea93259ae93418da4482fcc1", 396 + ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2", 397 + CreatorID: 2, 398 + }, 399 + }, 400 + }, pairs) 401 + }) 402 + 403 + t.Run("Repo 62 nonexistant sha", func(t *testing.T) { 404 + pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{62, "774f93df12d14931ea93259ae93418da4482fcc"}}) 405 + require.NoError(t, err) 406 + 407 + assert.EqualValues(t, map[int64][]*git_model.CommitStatus{}, pairs) 408 + }) 409 + 410 + t.Run("SHA with non existant repo id", func(t *testing.T) { 411 + pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{1, "774f93df12d14931ea93259ae93418da4482fcc1"}}) 412 + require.NoError(t, err) 413 + 414 + assert.EqualValues(t, map[int64][]*git_model.CommitStatus{}, pairs) 415 + }) 416 + }