]> source.dussan.org Git - gitea.git/commitdiff
Filter out duplicate action(activity) items for a repository (#30957) (#30976)
authorGiteabot <teabot@gitea.io>
Tue, 14 May 2024 14:14:39 +0000 (22:14 +0800)
committerGitHub <noreply@github.com>
Tue, 14 May 2024 14:14:39 +0000 (14:14 +0000)
Backport #30957

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
models/activities/action.go
models/activities/action_test.go

index 7e2ef4c9ae8e1179b3be23e00565789de69d69f6..d23f2bd986f3f11e987189cab6bbbb4f19328425 100644 (file)
@@ -524,7 +524,12 @@ func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.
        }
 
        if opts.RequestedRepo != nil {
-               cond = cond.And(builder.Eq{"repo_id": opts.RequestedRepo.ID})
+               // repo's actions could have duplicate items, see the comment of NotifyWatchers
+               // so here we only filter the "original items", aka: user_id == act_user_id
+               cond = cond.And(
+                       builder.Eq{"`action`.repo_id": opts.RequestedRepo.ID},
+                       builder.Expr("`action`.user_id = `action`.act_user_id"),
+               )
        }
 
        if opts.RequestedTeam != nil {
@@ -577,6 +582,10 @@ func DeleteOldActions(ctx context.Context, olderThan time.Duration) (err error)
 }
 
 // NotifyWatchers creates batch of actions for every watcher.
+// It could insert duplicate actions for a repository action, like this:
+// * Original action: UserID=1 (the real actor), ActUserID=1
+// * Organization action: UserID=100 (the repo's org), ActUserID=1
+// * Watcher action: UserID=20 (a user who is watching a repo), ActUserID=1
 func NotifyWatchers(ctx context.Context, actions ...*Action) error {
        var watchers []*repo_model.Watch
        var repo *repo_model.Repository
index 5467bd35fb855df58fdfbb34aab19fcecb24d2e9..557415dcda2fb68aaa77a11f65bc3962181bcec8 100644 (file)
@@ -318,3 +318,24 @@ func TestDeleteIssueActions(t *testing.T) {
        assert.NoError(t, activities_model.DeleteIssueActions(db.DefaultContext, issue.RepoID, issue.ID, issue.Index))
        unittest.AssertCount(t, &activities_model.Action{}, 0)
 }
+
+func TestRepoActions(t *testing.T) {
+       assert.NoError(t, unittest.PrepareTestDatabase())
+       repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
+       _ = db.TruncateBeans(db.DefaultContext, &activities_model.Action{})
+       for i := 0; i < 3; i++ {
+               _ = db.Insert(db.DefaultContext, &activities_model.Action{
+                       UserID:    2 + int64(i),
+                       ActUserID: 2,
+                       RepoID:    repo.ID,
+                       OpType:    activities_model.ActionCommentIssue,
+               })
+       }
+       count, _ := db.Count[activities_model.Action](db.DefaultContext, &db.ListOptions{})
+       assert.EqualValues(t, 3, count)
+       actions, _, err := activities_model.GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{
+               RequestedRepo: repo,
+       })
+       assert.NoError(t, err)
+       assert.Len(t, actions, 1)
+}