Skip to content

Commit 34288d4

Browse files
Loïc Dacharyrealaravinth
authored andcommitted
fix CheckRepoStats and reuse it during migration
The CheckRepoStats function missed the following counters: * label num_closed_issues & num_closed_pulls * milestone num_closed_issues & num_closed_pulls The update SQL statements for updating the repository num_closed_issues & num_closed_pulls fields were repeated in three functions (repo.CheckRepoStats, migrate.insertIssues and models.Issue.updateClosedNum) and were moved to a single helper. The UpdateRepoStats is implemented and called in the Finish migration method so that it happens immediately instead of wating for the CheckRepoStats to run. Signed-off-by: Loïc Dachary <[email protected]>
1 parent aa1e8f6 commit 34288d4

File tree

4 files changed

+156
-123
lines changed

4 files changed

+156
-123
lines changed

models/issue.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,19 +2061,9 @@ func (issue *Issue) BlockingDependencies() ([]*DependencyInfo, error) {
20612061

20622062
func (issue *Issue) updateClosedNum(e db.Engine) (err error) {
20632063
if issue.IsPull {
2064-
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=(SELECT count(*) FROM issue WHERE repo_id=? AND is_pull=? AND is_closed=?) WHERE id=?",
2065-
issue.RepoID,
2066-
true,
2067-
true,
2068-
issue.RepoID,
2069-
)
2064+
err = repoStatsCorrectNumClosed(e, issue.RepoID, true, "num_closed_pulls")
20702065
} else {
2071-
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=(SELECT count(*) FROM issue WHERE repo_id=? AND is_pull=? AND is_closed=?) WHERE id=?",
2072-
issue.RepoID,
2073-
false,
2074-
true,
2075-
issue.RepoID,
2076-
)
2066+
err = repoStatsCorrectNumClosed(e, issue.RepoID, false, "num_closed_issues")
20772067
}
20782068
return
20792069
}

models/migrate.go

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,11 @@ func insertIssue(sess db.Engine, issue *Issue) error {
5858
return err
5959
}
6060
issueLabels := make([]IssueLabel, 0, len(issue.Labels))
61-
labelIDs := make([]int64, 0, len(issue.Labels))
6261
for _, label := range issue.Labels {
6362
issueLabels = append(issueLabels, IssueLabel{
6463
IssueID: issue.ID,
6564
LabelID: label.ID,
6665
})
67-
labelIDs = append(labelIDs, label.ID)
6866
}
6967
if len(issueLabels) > 0 {
7068
if _, err := sess.Insert(issueLabels); err != nil {
@@ -82,55 +80,7 @@ func insertIssue(sess db.Engine, issue *Issue) error {
8280
}
8381
}
8482

85-
cols := make([]string, 0)
86-
if !issue.IsPull {
87-
sess.ID(issue.RepoID).Incr("num_issues")
88-
cols = append(cols, "num_issues")
89-
if issue.IsClosed {
90-
sess.Incr("num_closed_issues")
91-
cols = append(cols, "num_closed_issues")
92-
}
93-
} else {
94-
sess.ID(issue.RepoID).Incr("num_pulls")
95-
cols = append(cols, "num_pulls")
96-
if issue.IsClosed {
97-
sess.Incr("num_closed_pulls")
98-
cols = append(cols, "num_closed_pulls")
99-
}
100-
}
101-
if _, err := sess.NoAutoTime().Cols(cols...).Update(issue.Repo); err != nil {
102-
return err
103-
}
104-
105-
cols = []string{"num_issues"}
106-
sess.Incr("num_issues")
107-
if issue.IsClosed {
108-
sess.Incr("num_closed_issues")
109-
cols = append(cols, "num_closed_issues")
110-
}
111-
if _, err := sess.In("id", labelIDs).NoAutoTime().Cols(cols...).Update(new(Label)); err != nil {
112-
return err
113-
}
114-
115-
if issue.MilestoneID > 0 {
116-
cols = []string{"num_issues"}
117-
sess.Incr("num_issues")
118-
cl := "num_closed_issues"
119-
if issue.IsClosed {
120-
sess.Incr("num_closed_issues")
121-
cols = append(cols, "num_closed_issues")
122-
cl = "(num_closed_issues + 1)"
123-
}
124-
125-
if _, err := sess.ID(issue.MilestoneID).
126-
SetExpr("completeness", cl+" * 100 / (num_issues + 1)").
127-
NoAutoTime().Cols(cols...).
128-
Update(new(Milestone)); err != nil {
129-
return err
130-
}
131-
}
132-
133-
return nil
83+
return UpdateRepoStats(sess, issue.RepoID)
13484
}
13585

13686
// InsertIssueComments inserts many comments of issues.

models/repo.go

Lines changed: 149 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -961,12 +961,13 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
961961
}
962962

963963
type repoChecker struct {
964-
querySQL, correctSQL string
965-
desc string
964+
querySQL string
965+
correctSQL func(e db.Engine, id int64) error
966+
desc string
966967
}
967968

968-
func repoStatsCheck(ctx context.Context, checker *repoChecker) {
969-
results, err := db.GetEngine(db.DefaultContext).Query(checker.querySQL)
969+
func repoStatsCheck(ctx context.Context, e db.Engine, checker *repoChecker) {
970+
results, err := e.Query(checker.querySQL)
970971
if err != nil {
971972
log.Error("Select %s: %v", checker.desc, err)
972973
return
@@ -975,18 +976,105 @@ func repoStatsCheck(ctx context.Context, checker *repoChecker) {
975976
id, _ := strconv.ParseInt(string(result["id"]), 10, 64)
976977
select {
977978
case <-ctx.Done():
978-
log.Warn("CheckRepoStats: Cancelled before checking %s for Repo[%d]", checker.desc, id)
979+
log.Warn("CheckRepoStats: Cancelled before checking %s for with id=%d", checker.desc, id)
979980
return
980981
default:
981982
}
982983
log.Trace("Updating %s: %d", checker.desc, id)
983-
_, err = db.GetEngine(db.DefaultContext).Exec(checker.correctSQL, id, id)
984+
err = checker.correctSQL(e, id)
984985
if err != nil {
985986
log.Error("Update %s[%d]: %v", checker.desc, id, err)
986987
}
987988
}
988989
}
989990

991+
func StatsCorrectSQL(e db.Engine, sql string, id int64) error {
992+
_, err := e.Exec(sql, id, id)
993+
return err
994+
}
995+
996+
func repoStatsCorrectNumWatches(e db.Engine, id int64) error {
997+
return StatsCorrectSQL(e, "UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=? AND mode<>2) WHERE id=?", id)
998+
}
999+
1000+
func repoStatsCorrectNumStars(e db.Engine, id int64) error {
1001+
return StatsCorrectSQL(e, "UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?", id)
1002+
}
1003+
1004+
func labelStatsCorrectNumIssues(e db.Engine, id int64) error {
1005+
return StatsCorrectSQL(e, "UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=?) WHERE id=?", id)
1006+
}
1007+
1008+
func labelStatsCorrectNumIssuesRepo(e db.Engine, id int64) error {
1009+
_, err := e.Exec("UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=id) WHERE repo_id=?", id)
1010+
return err
1011+
}
1012+
1013+
func labelStatsCorrectNumClosedIssues(e db.Engine, id int64) error {
1014+
_, err := e.Exec("UPDATE `label` SET num_closed_issues=(SELECT COUNT(*) FROM `issue_label`,`issue` WHERE `issue_label`.label_id=`label`.id AND `issue_label`.issue_id=`issue`.id AND `issue`.is_closed=TRUE) WHERE `label`.id=?", id)
1015+
return err
1016+
}
1017+
1018+
func labelStatsCorrectNumClosedIssuesRepo(e db.Engine, id int64) error {
1019+
_, err := e.Exec("UPDATE `label` SET num_closed_issues=(SELECT COUNT(*) FROM `issue_label`,`issue` WHERE `issue_label`.label_id=`label`.id AND `issue_label`.issue_id=`issue`.id AND `issue`.is_closed=TRUE) WHERE `label`.repo_id=?", id)
1020+
return err
1021+
}
1022+
1023+
var milestoneStatsQueryNumIssues = "SELECT `milestone`.id FROM `milestone` WHERE `milestone`.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE `issue`.milestone_id=`milestone`.id AND `issue`.is_closed=TRUE) OR `milestone`.num_issues!=(SELECT COUNT(*) FROM `issue` WHERE `issue`.milestone_id=`milestone`.id)"
1024+
1025+
func milestoneStatsCorrectNumIssues(e db.Engine, id int64) error {
1026+
return updateMilestoneCounters(e, id)
1027+
}
1028+
1029+
func milestoneStatsCorrectNumIssuesRepo(e db.Engine, id int64) error {
1030+
results, err := e.Query(milestoneStatsQueryNumIssues+" AND `milestone`.repo_id = ?", id)
1031+
if err != nil {
1032+
return err
1033+
}
1034+
for _, result := range results {
1035+
id, _ := strconv.ParseInt(string(result["id"]), 10, 64)
1036+
err = milestoneStatsCorrectNumIssues(e, id)
1037+
if err != nil {
1038+
return err
1039+
}
1040+
}
1041+
return nil
1042+
}
1043+
1044+
func userStatsCorrectNumRepos(e db.Engine, id int64) error {
1045+
return StatsCorrectSQL(e, "UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?", id)
1046+
}
1047+
1048+
func repoStatsCorrectIssueNumComments(e db.Engine, id int64) error {
1049+
return StatsCorrectSQL(e, "UPDATE `issue` SET num_comments=(SELECT COUNT(*) FROM `comment` WHERE issue_id=? AND type=0) WHERE id=?", id)
1050+
}
1051+
1052+
func repoStatsCorrectNumIssues(e db.Engine, id int64) error {
1053+
return repoStatsCorrectNum(e, id, false, "num_issues")
1054+
}
1055+
1056+
func repoStatsCorrectNumPulls(e db.Engine, id int64) error {
1057+
return repoStatsCorrectNum(e, id, true, "num_pulls")
1058+
}
1059+
1060+
func repoStatsCorrectNum(e db.Engine, id int64, isPull bool, field string) error {
1061+
_, err := e.Exec("UPDATE `repository` SET "+field+"=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_pull=?) WHERE id=?", id, isPull, id)
1062+
return err
1063+
}
1064+
1065+
func repoStatsCorrectNumClosedIssues(e db.Engine, id int64) error {
1066+
return repoStatsCorrectNumClosed(e, id, false, "num_closed_issues")
1067+
}
1068+
1069+
func repoStatsCorrectNumClosedPulls(e db.Engine, id int64) error {
1070+
return repoStatsCorrectNumClosed(e, id, true, "num_closed_pulls")
1071+
}
1072+
1073+
func repoStatsCorrectNumClosed(e db.Engine, id int64, isPull bool, field string) error {
1074+
_, err := e.Exec("UPDATE `repository` SET "+field+"=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_closed=TRUE AND is_pull=?) WHERE id=?", id, isPull, id)
1075+
return err
1076+
}
1077+
9901078
// CheckRepoStats checks the repository stats
9911079
func CheckRepoStats(ctx context.Context) error {
9921080
log.Trace("Doing: CheckRepoStats")
@@ -995,93 +1083,72 @@ func CheckRepoStats(ctx context.Context) error {
9951083
// Repository.NumWatches
9961084
{
9971085
"SELECT repo.id FROM `repository` repo WHERE repo.num_watches!=(SELECT COUNT(*) FROM `watch` WHERE repo_id=repo.id AND mode<>2)",
998-
"UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=? AND mode<>2) WHERE id=?",
1086+
repoStatsCorrectNumWatches,
9991087
"repository count 'num_watches'",
10001088
},
10011089
// Repository.NumStars
10021090
{
10031091
"SELECT repo.id FROM `repository` repo WHERE repo.num_stars!=(SELECT COUNT(*) FROM `star` WHERE repo_id=repo.id)",
1004-
"UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?",
1092+
repoStatsCorrectNumStars,
10051093
"repository count 'num_stars'",
10061094
},
1095+
// Repository.NumClosedIssues
1096+
{
1097+
"SELECT repo.id FROM `repository` repo WHERE repo.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=TRUE AND is_pull=FALSE)",
1098+
repoStatsCorrectNumClosedIssues,
1099+
"repository count 'num_closed_issues'",
1100+
},
1101+
// Repository.NumClosedPulls
1102+
{
1103+
"SELECT repo.id FROM `repository` repo WHERE repo.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=TRUE AND is_pull=TRUE)",
1104+
repoStatsCorrectNumClosedPulls,
1105+
"repository count 'num_closed_pulls'",
1106+
},
10071107
// Label.NumIssues
10081108
{
10091109
"SELECT label.id FROM `label` WHERE label.num_issues!=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=label.id)",
1010-
"UPDATE `label` SET num_issues=(SELECT COUNT(*) FROM `issue_label` WHERE label_id=?) WHERE id=?",
1110+
labelStatsCorrectNumIssues,
10111111
"label count 'num_issues'",
10121112
},
1113+
// Label.NumClosedIssues
1114+
{
1115+
"SELECT `label`.id FROM `label` WHERE `label`.num_closed_issues!=(SELECT COUNT(*) FROM `issue_label`,`issue` WHERE `issue_label`.label_id=`label`.id AND `issue_label`.issue_id=`issue`.id AND `issue`.is_closed=TRUE)",
1116+
labelStatsCorrectNumClosedIssues,
1117+
"label count 'num_closed_issues'",
1118+
},
1119+
// Milestone.Num{,Closed}Issues
1120+
{
1121+
milestoneStatsQueryNumIssues,
1122+
milestoneStatsCorrectNumIssues,
1123+
"milestone count 'num_closed_issues' and 'num_issues'",
1124+
},
10131125
// User.NumRepos
10141126
{
10151127
"SELECT `user`.id FROM `user` WHERE `user`.num_repos!=(SELECT COUNT(*) FROM `repository` WHERE owner_id=`user`.id)",
1016-
"UPDATE `user` SET num_repos=(SELECT COUNT(*) FROM `repository` WHERE owner_id=?) WHERE id=?",
1128+
userStatsCorrectNumRepos,
10171129
"user count 'num_repos'",
10181130
},
10191131
// Issue.NumComments
10201132
{
10211133
"SELECT `issue`.id FROM `issue` WHERE `issue`.num_comments!=(SELECT COUNT(*) FROM `comment` WHERE issue_id=`issue`.id AND type=0)",
1022-
"UPDATE `issue` SET num_comments=(SELECT COUNT(*) FROM `comment` WHERE issue_id=? AND type=0) WHERE id=?",
1134+
repoStatsCorrectIssueNumComments,
10231135
"issue count 'num_comments'",
10241136
},
10251137
}
1138+
e := db.GetEngine(db.DefaultContext)
10261139
for _, checker := range checkers {
10271140
select {
10281141
case <-ctx.Done():
10291142
log.Warn("CheckRepoStats: Cancelled before %s", checker.desc)
10301143
return db.ErrCancelledf("before checking %s", checker.desc)
10311144
default:
1032-
repoStatsCheck(ctx, checker)
1033-
}
1034-
}
1035-
1036-
// ***** START: Repository.NumClosedIssues *****
1037-
desc := "repository count 'num_closed_issues'"
1038-
results, err := db.GetEngine(db.DefaultContext).Query("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, false)
1039-
if err != nil {
1040-
log.Error("Select %s: %v", desc, err)
1041-
} else {
1042-
for _, result := range results {
1043-
id, _ := strconv.ParseInt(string(result["id"]), 10, 64)
1044-
select {
1045-
case <-ctx.Done():
1046-
log.Warn("CheckRepoStats: Cancelled during %s for repo ID %d", desc, id)
1047-
return db.ErrCancelledf("during %s for repo ID %d", desc, id)
1048-
default:
1049-
}
1050-
log.Trace("Updating %s: %d", desc, id)
1051-
_, err = db.GetEngine(db.DefaultContext).Exec("UPDATE `repository` SET num_closed_issues=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_closed=? AND is_pull=?) WHERE id=?", id, true, false, id)
1052-
if err != nil {
1053-
log.Error("Update %s[%d]: %v", desc, id, err)
1054-
}
1145+
repoStatsCheck(ctx, e, checker)
10551146
}
10561147
}
1057-
// ***** END: Repository.NumClosedIssues *****
1058-
1059-
// ***** START: Repository.NumClosedPulls *****
1060-
desc = "repository count 'num_closed_pulls'"
1061-
results, err = db.GetEngine(db.DefaultContext).Query("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_pulls!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, true)
1062-
if err != nil {
1063-
log.Error("Select %s: %v", desc, err)
1064-
} else {
1065-
for _, result := range results {
1066-
id, _ := strconv.ParseInt(string(result["id"]), 10, 64)
1067-
select {
1068-
case <-ctx.Done():
1069-
log.Warn("CheckRepoStats: Cancelled")
1070-
return db.ErrCancelledf("during %s for repo ID %d", desc, id)
1071-
default:
1072-
}
1073-
log.Trace("Updating %s: %d", desc, id)
1074-
_, err = db.GetEngine(db.DefaultContext).Exec("UPDATE `repository` SET num_closed_pulls=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_closed=? AND is_pull=?) WHERE id=?", id, true, true, id)
1075-
if err != nil {
1076-
log.Error("Update %s[%d]: %v", desc, id, err)
1077-
}
1078-
}
1079-
}
1080-
// ***** END: Repository.NumClosedPulls *****
10811148

10821149
// FIXME: use checker when stop supporting old fork repo format.
10831150
// ***** START: Repository.NumForks *****
1084-
results, err = db.GetEngine(db.DefaultContext).Query("SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)")
1151+
results, err := e.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)")
10851152
if err != nil {
10861153
log.Error("Select repository count 'num_forks': %v", err)
10871154
} else {
@@ -1090,7 +1157,7 @@ func CheckRepoStats(ctx context.Context) error {
10901157
select {
10911158
case <-ctx.Done():
10921159
log.Warn("CheckRepoStats: Cancelled")
1093-
return db.ErrCancelledf("during %s for repo ID %d", desc, id)
1160+
return db.ErrCancelledf("during repository count 'num_fork' for repo ID %d", id)
10941161
default:
10951162
}
10961163
log.Trace("Updating repository count 'num_forks': %d", id)
@@ -1118,6 +1185,28 @@ func CheckRepoStats(ctx context.Context) error {
11181185
return nil
11191186
}
11201187

1188+
func UpdateRepoStats(e db.Engine, id int64) error {
1189+
var err error
1190+
1191+
for _, f := range []func(e db.Engine, id int64) error{
1192+
repoStatsCorrectNumWatches,
1193+
repoStatsCorrectNumStars,
1194+
repoStatsCorrectNumIssues,
1195+
repoStatsCorrectNumPulls,
1196+
repoStatsCorrectNumClosedIssues,
1197+
repoStatsCorrectNumClosedPulls,
1198+
labelStatsCorrectNumIssuesRepo,
1199+
labelStatsCorrectNumClosedIssuesRepo,
1200+
milestoneStatsCorrectNumIssuesRepo,
1201+
} {
1202+
err = f(e, id)
1203+
if err != nil {
1204+
return err
1205+
}
1206+
}
1207+
return nil
1208+
}
1209+
11211210
func updateUserStarNumbers(users []user_model.User) error {
11221211
ctx, committer, err := db.TxContext()
11231212
if err != nil {

services/migrations/gitea_uploader.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,10 @@ func (g *GiteaLocalUploader) Finish() error {
978978
return err
979979
}
980980

981+
if err := models.UpdateRepoStats(db.GetEngine(db.DefaultContext), g.repo.ID); err != nil {
982+
return err
983+
}
984+
981985
g.repo.Status = repo_model.RepositoryReady
982986
return repo_model.UpdateRepositoryCols(g.repo, "status")
983987
}

0 commit comments

Comments
 (0)