Internal error occurred but is skipped: FindTagsByCommitIDs

Files
VLoop/internal/feed/service.go

174 lines
4.9 KiB
Go
Raw Normal View History

2025-12-07 22:46:45 +08:00
package feed
import (
"context"
2025-12-23 02:26:29 +08:00
"encoding/json"
rediscache "feedsystem_video_go/internal/redis"
2025-12-07 22:46:45 +08:00
"feedsystem_video_go/internal/video"
2025-12-23 02:26:29 +08:00
"fmt"
2025-12-07 22:46:45 +08:00
"time"
)
type FeedService struct {
repo *FeedRepository
likeRepo *video.LikeRepository
2025-12-23 02:26:29 +08:00
cache *rediscache.Client
cacheTTL time.Duration
2025-12-07 22:46:45 +08:00
}
2025-12-23 02:26:29 +08:00
func NewFeedService(repo *FeedRepository, likeRepo *video.LikeRepository, cache *rediscache.Client) *FeedService {
return &FeedService{repo: repo, likeRepo: likeRepo, cache: cache, cacheTTL: 5 * time.Second}
2025-12-07 22:46:45 +08:00
}
func (f *FeedService) ListLatest(ctx context.Context, limit int, latestBefore time.Time, viewerAccountID uint) (ListLatestResponse, error) {
2025-12-23 02:26:29 +08:00
var cacheKey string
if viewerAccountID == 0 && f.cache != nil {
before := int64(0)
if !latestBefore.IsZero() {
before = latestBefore.Unix()
}
cacheKey = fmt.Sprintf("feed:listLatest:limit=%d:before=%d", limit, before)
cacheCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond)
defer cancel()
b, err := f.cache.GetBytes(cacheCtx, cacheKey)
if err == nil {
var cached ListLatestResponse
if err := json.Unmarshal(b, &cached); err == nil {
return cached, nil
}
}
}
2025-12-07 22:46:45 +08:00
videos, err := f.repo.ListLatest(ctx, limit, latestBefore)
if err != nil {
return ListLatestResponse{}, err
2025-12-07 22:46:45 +08:00
}
var nextTime int64
2025-12-07 22:46:45 +08:00
if len(videos) > 0 {
nextTime = videos[len(videos)-1].CreateTime.Unix()
2025-12-07 22:46:45 +08:00
} else {
nextTime = 0
2025-12-07 22:46:45 +08:00
}
hasMore := len(videos) == limit
feedVideos, err := f.buildFeedVideos(ctx, videos, viewerAccountID)
if err != nil {
return ListLatestResponse{}, err
}
resp := ListLatestResponse{
VideoList: feedVideos,
NextTime: nextTime,
2025-12-07 22:46:45 +08:00
HasMore: hasMore,
}
2025-12-23 02:26:29 +08:00
if cacheKey != "" {
if b, err := json.Marshal(resp); err == nil {
cacheCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond)
defer cancel()
_ = f.cache.SetBytes(cacheCtx, cacheKey, b, f.cacheTTL)
}
}
2025-12-07 22:46:45 +08:00
return resp, nil
}
2025-12-16 14:02:17 +08:00
2025-12-23 02:26:29 +08:00
func (f *FeedService) ListLikesCount(ctx context.Context, limit int, cursor *LikesCountCursor, viewerAccountID uint) (ListLikesCountResponse, error) {
videos, err := f.repo.ListLikesCountWithCursor(ctx, limit, cursor)
2025-12-16 14:02:17 +08:00
if err != nil {
return ListLikesCountResponse{}, err
}
hasMore := len(videos) == limit
feedVideos, err := f.buildFeedVideos(ctx, videos, viewerAccountID)
if err != nil {
return ListLikesCountResponse{}, err
2025-12-16 14:02:17 +08:00
}
resp := ListLikesCountResponse{
2025-12-23 02:26:29 +08:00
VideoList: feedVideos,
HasMore: hasMore,
}
if len(videos) > 0 {
last := videos[len(videos)-1]
nextLikesCountBefore := last.LikesCount
nextIDBefore := last.ID
resp.NextLikesCountBefore = &nextLikesCountBefore
resp.NextIDBefore = &nextIDBefore
2025-12-16 14:02:17 +08:00
}
return resp, nil
}
2025-12-19 19:20:52 +08:00
func (f *FeedService) ListByFollowing(ctx context.Context, limit int, latestBefore time.Time, viewerAccountID uint) (ListByFollowingResponse, error) {
var cacheKey string
if viewerAccountID != 0 && f.cache != nil {
before := int64(0)
if !latestBefore.IsZero() {
before = latestBefore.Unix()
}
cacheKey = fmt.Sprintf("feed:listByFollowing:limit=%d:accountID=%d:before=%d", limit, viewerAccountID, before)
cacheCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond)
defer cancel()
b, err := f.cache.GetBytes(cacheCtx, cacheKey)
if err == nil {
var cached ListByFollowingResponse
if err := json.Unmarshal(b, &cached); err == nil {
return cached, nil
}
}
}
videos, err := f.repo.ListByFollowing(ctx, limit, viewerAccountID, latestBefore)
2025-12-19 19:20:52 +08:00
if err != nil {
return ListByFollowingResponse{}, err
}
var nextTime int64
if len(videos) > 0 {
nextTime = videos[len(videos)-1].CreateTime.Unix()
} else {
nextTime = 0
}
hasMore := len(videos) == limit
feedVideos, err := f.buildFeedVideos(ctx, videos, viewerAccountID)
if err != nil {
return ListByFollowingResponse{}, err
}
resp := ListByFollowingResponse{
VideoList: feedVideos,
NextTime: nextTime,
HasMore: hasMore,
}
if cacheKey != "" {
if b, err := json.Marshal(resp); err == nil {
cacheCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond)
defer cancel()
_ = f.cache.SetBytes(cacheCtx, cacheKey, b, f.cacheTTL)
}
}
return resp, nil
}
func (f *FeedService) buildFeedVideos(ctx context.Context, videos []*video.Video, viewerAccountID uint) ([]FeedVideoItem, error) {
2025-12-19 19:20:52 +08:00
feedVideos := make([]FeedVideoItem, 0, len(videos))
videoIDs := make([]uint, len(videos))
for i, v := range videos {
videoIDs[i] = v.ID
}
likedMap, err := f.likeRepo.BatchGetLiked(ctx, videoIDs, viewerAccountID)
if err != nil {
return nil, err
}
2025-12-19 19:20:52 +08:00
for _, video := range videos {
feedVideos = append(feedVideos, FeedVideoItem{
ID: video.ID,
Author: FeedAuthor{ID: video.AuthorID, Username: video.Username},
Title: video.Title,
Description: video.Description,
PlayURL: video.PlayURL,
CoverURL: video.CoverURL,
2025-12-23 02:26:29 +08:00
CreateTime: video.CreateTime.Unix(),
2025-12-19 19:20:52 +08:00
LikesCount: video.LikesCount,
IsLiked: likedMap[video.ID],
2025-12-19 19:20:52 +08:00
})
}
return feedVideos, nil
2025-12-19 19:20:52 +08:00
}