Skip to content

Commit a675bfe

Browse files
committed
optimize heatmap
1 parent ae63568 commit a675bfe

File tree

8 files changed

+68
-21
lines changed

8 files changed

+68
-21
lines changed

models/activities/action.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ type GetFeedsOptions struct {
442442
OnlyPerformedBy bool // only actions performed by requested user
443443
IncludeDeleted bool // include deleted actions
444444
Date string // the day we want activity for: YYYY-MM-DD
445+
DontCount bool // do counting in GetFeeds
445446
}
446447

447448
// ActivityReadable return whether doer can read activities of user

models/activities/action_list.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,11 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err
243243
sess := db.GetEngine(ctx).Where(cond)
244244
sess = db.SetSessionPagination(sess, &opts)
245245

246-
count, err = sess.Desc("`action`.created_unix").FindAndCount(&actions)
246+
if opts.DontCount {
247+
err = sess.Desc("`action`.created_unix").Find(&actions)
248+
} else {
249+
count, err = sess.Desc("`action`.created_unix").FindAndCount(&actions)
250+
}
247251
if err != nil {
248252
return nil, 0, fmt.Errorf("FindAndCount: %w", err)
249253
}
@@ -257,11 +261,13 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err
257261
return nil, 0, fmt.Errorf("Find(actionsIDs): %w", err)
258262
}
259263

260-
count, err = db.GetEngine(ctx).Where(cond).
261-
Table("action").
262-
Cols("`action`.id").Count()
263-
if err != nil {
264-
return nil, 0, fmt.Errorf("Count: %w", err)
264+
if !opts.DontCount {
265+
count, err = db.GetEngine(ctx).Where(cond).
266+
Table("action").
267+
Cols("`action`.id").Count()
268+
if err != nil {
269+
return nil, 0, fmt.Errorf("Count: %w", err)
270+
}
265271
}
266272

267273
if err := db.GetEngine(ctx).In("`action`.id", actionIDs).Desc("`action`.created_unix").Find(&actions); err != nil {
@@ -275,3 +281,9 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err
275281

276282
return actions, count, nil
277283
}
284+
285+
func CountUserFeeds(ctx context.Context, userID int64) (int64, error) {
286+
return db.GetEngine(ctx).Where("user_id = ?", userID).
287+
And("is_deleted = ?", false).
288+
Count(&Action{})
289+
}

models/activities/user_heatmap.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,7 @@ type UserHeatmapData struct {
1919
Contributions int64 `json:"contributions"`
2020
}
2121

22-
// GetUserHeatmapDataByUser returns an array of UserHeatmapData
23-
func GetUserHeatmapDataByUser(ctx context.Context, user, doer *user_model.User) ([]*UserHeatmapData, error) {
24-
return getUserHeatmapData(ctx, user, nil, doer)
25-
}
26-
27-
// GetUserHeatmapDataByUserTeam returns an array of UserHeatmapData
28-
func GetUserHeatmapDataByUserTeam(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
29-
return getUserHeatmapData(ctx, user, team, doer)
30-
}
31-
32-
func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
22+
func GetUserHeatmapData(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*UserHeatmapData, error) {
3323
hdata := make([]*UserHeatmapData, 0)
3424

3525
if !ActivityReadable(user, doer) {

routers/api/v1/user/user.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func GetUserHeatmapData(ctx *context.APIContext) {
160160
// "404":
161161
// "$ref": "#/responses/notFound"
162162

163-
heatmap, err := activities_model.GetUserHeatmapDataByUser(ctx, ctx.ContextUser, ctx.Doer)
163+
heatmap, err := feed_service.GetUserHeatmapDataByUser(ctx, ctx.ContextUser, ctx.Doer)
164164
if err != nil {
165165
ctx.APIErrorInternal(err)
166166
return

routers/web/user/home.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func Dashboard(ctx *context.Context) {
109109
}
110110

111111
if setting.Service.EnableUserHeatmap {
112-
data, err := activities_model.GetUserHeatmapDataByUserTeam(ctx, ctxUser, ctx.Org.Team, ctx.Doer)
112+
data, err := feed_service.GetUserHeatmapDataByUserTeam(ctx, ctxUser, ctx.Org.Team, ctx.Doer)
113113
if err != nil {
114114
ctx.ServerError("GetUserHeatmapDataByUserTeam", err)
115115
return

routers/web/user/profile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func userProfile(ctx *context.Context) {
6565

6666
// prepare heatmap data
6767
if setting.Service.EnableUserHeatmap {
68-
data, err := activities_model.GetUserHeatmapDataByUser(ctx, ctx.ContextUser, ctx.Doer)
68+
data, err := feed_service.GetUserHeatmapDataByUser(ctx, ctx.ContextUser, ctx.Doer)
6969
if err != nil {
7070
ctx.ServerError("GetUserHeatmapDataByUser", err)
7171
return

services/feed/feed.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,27 @@ import (
1313
repo_model "code.gitea.io/gitea/models/repo"
1414
"code.gitea.io/gitea/models/unit"
1515
user_model "code.gitea.io/gitea/models/user"
16+
"code.gitea.io/gitea/modules/cache"
1617
"code.gitea.io/gitea/modules/setting"
1718
)
1819

20+
func userFeedCacheKey(userID int64) string {
21+
return fmt.Sprintf("user_feed_%d", userID)
22+
}
23+
1924
// GetFeeds returns actions according to the provided options
2025
func GetFeeds(ctx context.Context, opts activities_model.GetFeedsOptions) (activities_model.ActionList, int64, error) {
21-
return activities_model.GetFeeds(ctx, opts)
26+
opts.DontCount = opts.Actor != nil && opts.RequestedUser != nil && (opts.Actor.IsAdmin || opts.Actor.ID == opts.RequestedUser.ID)
27+
results, cnt, err := activities_model.GetFeeds(ctx, opts)
28+
if err != nil {
29+
return nil, 0, err
30+
}
31+
if opts.DontCount {
32+
cnt, err = cache.GetInt64(userFeedCacheKey(opts.Actor.ID), func() (int64, error) {
33+
return activities_model.CountUserFeeds(ctx, opts.Actor.ID)
34+
})
35+
}
36+
return results, cnt, err
2237
}
2338

2439
// notifyWatchers creates batch of actions for every watcher.
@@ -68,6 +83,13 @@ func notifyWatchers(ctx context.Context, act *activities_model.Action, watchers
6883
if err := db.Insert(ctx, act); err != nil {
6984
return fmt.Errorf("insert new action: %w", err)
7085
}
86+
87+
total, err := activities_model.CountUserFeeds(ctx, act.UserID)
88+
if err != nil {
89+
return fmt.Errorf("count user feeds: %w", err)
90+
}
91+
92+
cache.GetCache().Put(userFeedCacheKey(act.UserID), fmt.Sprintf("%d", total), setting.CacheService.TTLSeconds())
7193
}
7294

7395
return nil

services/feed/heatmap.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package feed
5+
6+
import (
7+
"context"
8+
9+
activities_model "code.gitea.io/gitea/models/activities"
10+
"code.gitea.io/gitea/models/organization"
11+
user_model "code.gitea.io/gitea/models/user"
12+
)
13+
14+
// GetUserHeatmapDataByUser returns an array of UserHeatmapData
15+
func GetUserHeatmapDataByUser(ctx context.Context, user, doer *user_model.User) ([]*activities_model.UserHeatmapData, error) {
16+
return activities_model.GetUserHeatmapData(ctx, user, nil, doer)
17+
}
18+
19+
// GetUserHeatmapDataByUserTeam returns an array of UserHeatmapData
20+
func GetUserHeatmapDataByUserTeam(ctx context.Context, user *user_model.User, team *organization.Team, doer *user_model.User) ([]*activities_model.UserHeatmapData, error) {
21+
return activities_model.GetUserHeatmapData(ctx, user, team, doer)
22+
}

0 commit comments

Comments
 (0)