0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-07-26 11:04:27 -04:00
This commit is contained in:
wxiaoguang 2025-04-18 09:39:39 +08:00
parent a0080acc8f
commit c5f735ab72

View File

@ -6,7 +6,7 @@ package feed
import ( import (
"context" "context"
"fmt" "fmt"
"strconv" "strings"
activities_model "code.gitea.io/gitea/models/activities" activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -14,16 +14,10 @@ import (
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "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) { func GetFeedsForDashboard(ctx context.Context, opts activities_model.GetFeedsOptions) (activities_model.ActionList, int, error) {
opts.DontCount = opts.RequestedTeam == nil && opts.Date == "" opts.DontCount = opts.RequestedTeam == nil && opts.Date == ""
results, cnt, err := activities_model.GetFeeds(ctx, opts) results, cnt, err := activities_model.GetFeeds(ctx, opts)
@ -35,20 +29,25 @@ func GetFeeds(ctx context.Context, opts activities_model.GetFeedsOptions) (activ
return activities_model.GetFeeds(ctx, opts) return activities_model.GetFeeds(ctx, opts)
} }
const maxActionContentLength = 65535 // this is the max length of mysql text column, sqlite, postgres and mssql have a higher limit
// notifyWatchers creates batch of actions for every watcher. // notifyWatchers creates batch of actions for every watcher.
// It could insert duplicate actions for a repository action, like this: // It could insert duplicate actions for a repository action, like this:
// * Original action: UserID=1 (the real actor), ActUserID=1 // * Original action: UserID=1 (the real actor), ActUserID=1
// * Organization action: UserID=100 (the repo's org), 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 // * 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 { 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.
act.UserID = act.ActUserID // Sometimes the content is "field1|field2|field3", sometimes the content is JSON (ActionMirrorSyncPush, ActionCommitRepo, ActionPushTag, etc...)
if len(act.Content) > maxActionContentLength { if left, right := util.EllipsisDisplayStringX(act.Content, 65535); right != "" {
act.Content = util.EllipsisDisplayString(act.Content, maxActionContentLength) if strings.HasPrefix(act.Content, `{"`) && strings.HasSuffix(act.Content, `}`) {
log.Warn("Action [%d, %s]'s content is too long, truncated to %d bytes", act.RepoID, act.OpType, maxActionContentLength) // 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 { if err := db.Insert(ctx, act); err != nil {
return fmt.Errorf("insert new actioner: %w", err) return fmt.Errorf("insert new actioner: %w", err)
} }
@ -83,24 +82,18 @@ func notifyWatchers(ctx context.Context, act *activities_model.Action, watchers
if !permPR[i] { if !permPR[i] {
continue continue
} }
default:
} }
if err := db.Insert(ctx, act); err != nil { if err := db.Insert(ctx, act); err != nil {
return fmt.Errorf("insert new action: %w", err) 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 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 { func NotifyWatchers(ctx context.Context, acts ...*activities_model.Action) error {
return db.WithTx(ctx, func(ctx context.Context) error { return db.WithTx(ctx, func(ctx context.Context) error {
if len(acts) == 0 { if len(acts) == 0 {