Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove num_watches column from table repository #32557

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions models/fixtures/repository.yml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ func prepareMigrationTasks() []*migration {
newMigration(308, "Add index(user_id, is_deleted) for action table", v1_23.AddNewIndexForUserDashboard),
newMigration(309, "Improve Notification table indices", v1_23.ImproveNotificationTableIndices),
newMigration(310, "Add Priority to ProtectedBranch", v1_23.AddPriorityToProtectedBranch),
newMigration(310, "Remove repository column num_watches", v1_23.RemoveRepoNumWatches),
}
return preparedMigrations
}
Expand Down
16 changes: 16 additions & 0 deletions models/migrations/v1_23/v311.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package v1_23 //nolint

import (
"code.gitea.io/gitea/models/migrations/base"

"xorm.io/xorm"
)

func RemoveRepoNumWatches(x *xorm.Engine) error {
sess := x.NewSession()
defer sess.Close()
return base.DropTableColumns(sess, "repository", "num_watches")
}
11 changes: 0 additions & 11 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ func StatsCorrectSQL(ctx context.Context, sql string, id int64) error {
return err
}

func repoStatsCorrectNumWatches(ctx context.Context, id int64) error {
return StatsCorrectSQL(ctx, "UPDATE `repository` SET num_watches=(SELECT COUNT(*) FROM `watch` WHERE repo_id=? AND mode<>2) WHERE id=?", id)
}

func repoStatsCorrectNumStars(ctx context.Context, id int64) error {
return StatsCorrectSQL(ctx, "UPDATE `repository` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE repo_id=?) WHERE id=?", id)
}
Expand Down Expand Up @@ -139,12 +135,6 @@ func CheckRepoStats(ctx context.Context) error {
log.Trace("Doing: CheckRepoStats")

checkers := []*repoChecker{
// Repository.NumWatches
{
statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_watches!=(SELECT COUNT(*) FROM `watch` WHERE repo_id=repo.id AND mode<>2)"),
repoStatsCorrectNumWatches,
"repository count 'num_watches'",
},
// Repository.NumStars
{
statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_stars!=(SELECT COUNT(*) FROM `star` WHERE repo_id=repo.id)"),
Expand Down Expand Up @@ -259,7 +249,6 @@ func UpdateRepoStats(ctx context.Context, id int64) error {
var err error

for _, f := range []func(ctx context.Context, id int64) error{
repoStatsCorrectNumWatches,
repoStatsCorrectNumStars,
repoStatsCorrectNumIssues,
repoStatsCorrectNumPulls,
Expand Down
14 changes: 13 additions & 1 deletion models/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ type Repository struct {
DefaultBranch string
DefaultWikiBranch string

NumWatches int
NumWatches int `xorm:"-"`
NumStars int
NumForks int
NumIssues int
Expand Down Expand Up @@ -317,6 +317,18 @@ func (repo *Repository) LoadAttributes(ctx context.Context) error {
return nil
}

func (repo *Repository) LoadNumWatchers(ctx context.Context) error {
if repo.NumWatches > 0 {
return nil
}
cnt, err := CountRepoWatchers(ctx, repo.ID)
if err != nil {
return err
}
repo.NumWatches = int(cnt)
return nil
}

// FullName returns the repository full name
func (repo *Repository) FullName() string {
return repo.OwnerName + "/" + repo.Name
Expand Down
32 changes: 32 additions & 0 deletions models/repo/repo_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,38 @@ func (repos RepositoryList) LoadLanguageStats(ctx context.Context) error {
return nil
}

func (repos RepositoryList) LoadNumWatchers(ctx context.Context) error {
if len(repos) == 0 {
return nil
}

type results struct {
RepoID int64
NumWatchers int64
}
// Load watchers.
watches := make([]results, 0, len(repos))
if err := db.GetEngine(ctx).
Select("repo_id, COUNT(*) as num_watchers").
Table("watch").
In("repo_id", repos.IDs()).
And("`mode` <> ?", WatchModeDont).
GroupBy("repo_id").
Find(&watches); err != nil {
return fmt.Errorf("find watchers: %w", err)
}

watchesMap := make(map[int64]int, len(repos))
for _, watch := range watches {
watchesMap[watch.RepoID] = int(watch.NumWatchers)
}

for i := range repos {
repos[i].NumWatches = watchesMap[repos[i].ID]
}
return nil
}

// LoadAttributes loads the attributes for the given RepositoryList
func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
if err := repos.LoadOwners(ctx); err != nil {
Expand Down
16 changes: 6 additions & 10 deletions models/repo/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,6 @@ func watchRepoMode(ctx context.Context, watch Watch, mode WatchMode) (err error)

hadrec := watch.Mode != WatchModeNone
needsrec := mode != WatchModeNone
repodiff := 0

if IsWatchMode(mode) && !IsWatchMode(watch.Mode) {
repodiff = 1
} else if !IsWatchMode(mode) && IsWatchMode(watch.Mode) {
repodiff = -1
}

watch.Mode = mode

Expand All @@ -98,9 +91,6 @@ func watchRepoMode(ctx context.Context, watch Watch, mode WatchMode) (err error)
} else if _, err = db.DeleteByID[Watch](ctx, watch.ID); err != nil {
return err
}
if repodiff != 0 {
_, err = db.GetEngine(ctx).Exec("UPDATE `repository` SET num_watches = num_watches + ? WHERE id = ?", repodiff, watch.RepoID)
}
return err
}

Expand Down Expand Up @@ -162,6 +152,12 @@ func GetRepoWatchers(ctx context.Context, repoID int64, opts db.ListOptions) ([]
return users, sess.Find(&users)
}

func CountRepoWatchers(ctx context.Context, repoID int64) (int64, error) {
return db.GetEngine(ctx).Where("repo_id=?", repoID).
And("mode<>?", WatchModeDont).
Count(new(Watch))
}

// WatchIfAuto subscribes to repo if AutoWatchOnChanges is set
func WatchIfAuto(ctx context.Context, userID, repoID int64, isWrite bool) error {
if !isWrite || !setting.Service.AutoWatchOnChanges {
Expand Down
6 changes: 1 addition & 5 deletions models/repo/watch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ func TestGetWatchers(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
watches, err := repo_model.GetWatchers(db.DefaultContext, repo.ID)
assert.NoError(t, err)
// One watchers are inactive, thus minus 1
assert.Len(t, watches, repo.NumWatches-1)
for _, watch := range watches {
assert.EqualValues(t, repo.ID, watch.RepoID)
}
Expand All @@ -50,7 +48,6 @@ func TestRepository_GetWatchers(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
watchers, err := repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1})
assert.NoError(t, err)
assert.Len(t, watchers, repo.NumWatches)
for _, watcher := range watchers {
unittest.AssertExistsAndLoadBean(t, &repo_model.Watch{UserID: watcher.ID, RepoID: repo.ID})
}
Expand All @@ -69,11 +66,10 @@ func TestWatchIfAuto(t *testing.T) {

watchers, err := repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1})
assert.NoError(t, err)
assert.Len(t, watchers, repo.NumWatches)

setting.Service.AutoWatchOnChanges = false

prevCount := repo.NumWatches
prevCount := len(watchers)

// Must not add watch
assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 8, 1, true))
Expand Down
7 changes: 1 addition & 6 deletions models/unittest/consistency.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,7 @@ func init() {
AssertExistsAndLoadMap(t, "repository", builder.Eq{"id": repo.int("ForkID")})
}

actual := GetCountByCond(t, "watch", builder.Eq{"repo_id": repo.int("ID")}.
And(builder.Neq{"mode": modelsRepoWatchModeDont}))
assert.EqualValues(t, repo.int("NumWatches"), actual,
"Unexpected number of watches for repo id: %d", repo.int("ID"))

actual = GetCountByCond(t, "issue", builder.Eq{"is_pull": false, "repo_id": repo.int("ID")})
actual := GetCountByCond(t, "issue", builder.Eq{"is_pull": false, "repo_id": repo.int("ID")})
assert.EqualValues(t, repo.int("NumIssues"), actual,
"Unexpected number of issues for repo id: %d", repo.int("ID"))

Expand Down
8 changes: 7 additions & 1 deletion routers/api/v1/repo/subscriber.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ func ListSubscribers(ctx *context.APIContext) {
users[i] = convert.ToUser(ctx, subscriber, ctx.Doer)
}

ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumWatches))
total, err := repo_model.CountRepoWatchers(ctx, ctx.Repo.Repository.ID)
if err != nil {
ctx.Error(http.StatusInternalServerError, "CountRepoWatchers", err)
return
}

ctx.SetTotalCountHeader(total)
ctx.JSON(http.StatusOK, users)
}
14 changes: 7 additions & 7 deletions routers/web/explore/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
opts.PageSize = setting.UI.SitemapPagingNum
}

var (
repos []*repo_model.Repository
count int64
err error
orderBy db.SearchOrderBy
)
var orderBy db.SearchOrderBy

sortOrder := ctx.FormString("sort")
if sortOrder == "" {
Expand Down Expand Up @@ -95,7 +90,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
private := ctx.FormOptionalBool("private")
ctx.Data["IsPrivate"] = private

repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
repos, count, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: page,
PageSize: opts.PageSize,
Expand Down Expand Up @@ -133,6 +128,11 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
return
}

if err := repos.LoadNumWatchers(ctx); err != nil {
ctx.ServerError("LoadNumWatchers", err)
return
}

ctx.Data["Keyword"] = keyword
ctx.Data["Total"] = count
ctx.Data["Repos"] = repos
Expand Down
7 changes: 6 additions & 1 deletion routers/web/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,20 @@ func Action(ctx *context.Context) {
switch ctx.PathParam(":action") {
case "watch", "unwatch", "star", "unstar":
// we have to reload the repository because NumStars or NumWatching (used in the templates) has just changed
ctx.Data["Repository"], err = repo_model.GetRepositoryByName(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.Name)
ctx.Repo.Repository, err = repo_model.GetRepositoryByName(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.Name)
if err != nil {
ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.PathParam(":action")), err)
return
}
ctx.Data["Repository"] = ctx.Repo.Repository
}

switch ctx.PathParam(":action") {
case "watch", "unwatch":
if err := ctx.Repo.Repository.LoadNumWatchers(ctx); err != nil {
ctx.ServerError("LoadNumWatchers", err)
return
}
ctx.HTML(http.StatusOK, tplWatchUnwatch)
return
case "star", "unstar":
Expand Down
8 changes: 7 additions & 1 deletion routers/web/repo/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,13 @@ func RenderUserCards(ctx *context.Context, total int, getter func(opts db.ListOp
func Watchers(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.watchers")
ctx.Data["CardsTitle"] = ctx.Tr("repo.watchers")
RenderUserCards(ctx, ctx.Repo.Repository.NumWatches, func(opts db.ListOptions) ([]*user_model.User, error) {
numWatchers, err := repo_model.CountRepoWatchers(ctx, ctx.Repo.Repository.ID)
if err != nil {
ctx.ServerError("CountRepoWatchers", err)
return
}

RenderUserCards(ctx, int(numWatchers), func(opts db.ListOptions) ([]*user_model.User, error) {
return repo_model.GetRepoWatchers(ctx, ctx.Repo.Repository.ID, opts)
}, tplWatchers)
}
Expand Down
9 changes: 8 additions & 1 deletion services/convert/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR

repoLicenses, err := repo_model.GetRepoLicenses(ctx, repo)
if err != nil {
log.Error("GetRepoLicenses: %v", err)
return nil
}

numWatchers, err := repo_model.CountRepoWatchers(ctx, repo.ID)
if err != nil {
log.Error("CountRepoWatchers: %v", err)
return nil
}

Expand Down Expand Up @@ -206,7 +213,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
LanguagesURL: repoAPIURL + "/languages",
Stars: repo.NumStars,
Forks: repo.NumForks,
Watchers: repo.NumWatches,
Watchers: int(numWatchers),
OpenIssues: repo.NumOpenIssues,
OpenPulls: repo.NumOpenPulls,
Releases: int(numReleases),
Expand Down
12 changes: 0 additions & 12 deletions services/repository/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"time"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
Expand Down Expand Up @@ -72,17 +71,6 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
httpTransport *http.Transport,
) (*repo_model.Repository, error) {
repoPath := repo_model.RepoPath(u.Name, opts.RepoName)

if u.IsOrganization() {
t, err := organization.OrgFromUser(u).GetOwnerTeam(ctx)
if err != nil {
return nil, err
}
repo.NumWatches = t.NumMembers
} else {
repo.NumWatches = 1
}

migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second

if err := util.RemoveAll(repoPath); err != nil {
Expand Down
12 changes: 0 additions & 12 deletions services/user/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,6 @@ import (
func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) {
e := db.GetEngine(ctx)

// ***** START: Watch *****
watchedRepoIDs, err := db.FindIDs(ctx, "watch", "watch.repo_id",
builder.Eq{"watch.user_id": u.ID}.
And(builder.Neq{"watch.mode": repo_model.WatchModeDont}))
if err != nil {
return fmt.Errorf("get all watches: %w", err)
}
if err = db.DecrByIDs(ctx, watchedRepoIDs, "num_watches", new(repo_model.Repository)); err != nil {
return fmt.Errorf("decrease repository num_watches: %w", err)
}
// ***** END: Watch *****

// ***** START: Star *****
starredRepoIDs, err := db.FindIDs(ctx, "star", "star.repo_id",
builder.Eq{"star.uid": u.ID})
Expand Down
Loading