}
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 {
}
// 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
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)
+}