diff --git a/models/action.go b/models/action.go index 14e021389a393..ab08ee07d5059 100644 --- a/models/action.go +++ b/models/action.go @@ -361,6 +361,13 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, error) { actions := make([]*Action, 0, opts.PageSize) + // De-duplicate any action that has the same created unix, as actions are stored for each user + // who can see that action. This probably (though there is no guarantee) means that they were the same + // action. + if opts.RequestedRepo != nil { + sess = sess.In("`action`.id", builder.Select("min(id) as id").From("action").GroupBy("`action`.created_unix, `action`.op_type, `action`.act_user_id")) + } + if err := sess.Desc("`action`.created_unix").Find(&actions); err != nil { return nil, fmt.Errorf("Find: %v", err) } diff --git a/models/action_test.go b/models/action_test.go index 2d46bd3e80e11..e4d5aa21c8630 100644 --- a/models/action_test.go +++ b/models/action_test.go @@ -68,6 +68,7 @@ func TestGetFeedsForRepos(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) privRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) pubRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 8}).(*repo_model.Repository) + repoWithActions := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) // private repo & no login actions, err := GetFeeds(db.DefaultContext, GetFeedsOptions{ @@ -102,6 +103,16 @@ func TestGetFeedsForRepos(t *testing.T) { }) assert.NoError(t, err) assert.Len(t, actions, 1) + + // Check repository with four actions, all of them were created + // at the same time, but two of them are comments(one should be de-duped) + // the other one is closing a issue and the last one is also comment but by a different user. + // So in told there are 3 de-deduped actions. + actions, err = GetFeeds(db.DefaultContext, GetFeedsOptions{ + RequestedRepo: repoWithActions, + }) + assert.NoError(t, err) + assert.Len(t, actions, 3) } func TestGetFeeds2(t *testing.T) { diff --git a/models/fixtures/action.yml b/models/fixtures/action.yml index a75092feb0ecc..619fd62afa2e6 100644 --- a/models/fixtures/action.yml +++ b/models/fixtures/action.yml @@ -64,3 +64,38 @@ repo_id: 1700 # dangling intentional is_private: false created_unix: 1603011541 + +- id: 9 + user_id: 10 + op_type: 10 + act_user_id: 10 + repo_id: 1 + content: HelloWorld + is_private: false + created_unix: 1603011301 # same as 10, 11, 12 + +- id: 10 + user_id: 9 + op_type: 10 + act_user_id: 10 + repo_id: 1 + content: HelloWorld + is_private: false + created_unix: 1603011301 # same as id 9, 11, 12 + +- id: 11 + user_id: 9 + op_type: 12 # differ op_type + act_user_id: 10 + repo_id: 1 + is_private: false + created_unix: 1603011301 # same as id 9, 10, 12 + +- id: 12 + user_id: 9 + op_type: 10 + act_user_id: 9 # differ act_user_id + repo_id: 1 + content: HelloWorld + is_private: false + created_unix: 1603011301 # same as id 9, 10, 11 diff --git a/models/user_heatmap_test.go b/models/user_heatmap_test.go index 9361cb3452fa8..1ed387ccf8a3c 100644 --- a/models/user_heatmap_test.go +++ b/models/user_heatmap_test.go @@ -52,7 +52,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) { }, { "multiple actions performed with two grouped together", - 10, 10, 3, `[{"timestamp":1603009800,"contributions":1},{"timestamp":1603010700,"contributions":2}]`, + 10, 10, 4, `[{"timestamp":1603009800,"contributions":1},{"timestamp":1603010700,"contributions":3}]`, }, } // Prepare