Skip to content

Fix possible notify watch failure because the content is too long than database can store. #34233

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

Merged
merged 3 commits into from
Apr 20, 2025
Merged
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
30 changes: 15 additions & 15 deletions services/feed/feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,18 @@ package feed
import (
"context"
"fmt"
"strconv"
"strings"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)

func userFeedCacheKey(userID int64) string {
return fmt.Sprintf("user_feed_%d", userID)
}

func GetFeedsForDashboard(ctx context.Context, opts activities_model.GetFeedsOptions) (activities_model.ActionList, int, error) {
opts.DontCount = opts.RequestedTeam == nil && opts.Date == ""
results, cnt, err := activities_model.GetFeeds(ctx, opts)
Expand All @@ -40,7 +35,18 @@ func GetFeeds(ctx context.Context, opts activities_model.GetFeedsOptions) (activ
// * 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, act *activities_model.Action, watchers []*repo_model.Watch, permCode, permIssue, permPR []bool) error {
// Add feed for actioner.
// MySQL has TEXT length limit 65535.
// Sometimes the content is "field1|field2|field3", sometimes the content is JSON (ActionMirrorSyncPush, ActionCommitRepo, ActionPushTag, etc...)
if left, right := util.EllipsisDisplayStringX(act.Content, 65535); right != "" {
if strings.HasPrefix(act.Content, `{"`) && strings.HasSuffix(act.Content, `}`) {
// FIXME: at the moment we can do nothing if the content is JSON and it is too long
act.Content = "{}"
} else {
act.Content = left
}
}

// Add feed for actor.
act.UserID = act.ActUserID
if err := db.Insert(ctx, act); err != nil {
return fmt.Errorf("insert new actioner: %w", err)
Expand Down Expand Up @@ -76,24 +82,18 @@ func notifyWatchers(ctx context.Context, act *activities_model.Action, watchers
if !permPR[i] {
continue
}
default:
}

if err := db.Insert(ctx, act); err != nil {
return fmt.Errorf("insert new action: %w", err)
}

total, err := activities_model.CountUserFeeds(ctx, act.UserID)
if err != nil {
return fmt.Errorf("count user feeds: %w", err)
}

_ = cache.GetCache().Put(userFeedCacheKey(act.UserID), strconv.FormatInt(total, 10), setting.CacheService.TTLSeconds())
}

return nil
}

// NotifyWatchersActions creates batch of actions for every watcher.
// NotifyWatchers creates batch of actions for every watcher.
func NotifyWatchers(ctx context.Context, acts ...*activities_model.Action) error {
return db.WithTx(ctx, func(ctx context.Context) error {
if len(acts) == 0 {
Expand Down