diff --git a/internal/feed/entity.go b/internal/feed/entity.go index a5abe4b..56f0855 100644 --- a/internal/feed/entity.go +++ b/internal/feed/entity.go @@ -35,8 +35,8 @@ type ListLikesCountRequest struct { } type LikesCountCursor struct { - LikesCount int64 - ID uint + LikesCount int64 + ID uint } type ListLikesCountResponse struct { @@ -47,7 +47,8 @@ type ListLikesCountResponse struct { } type ListByFollowingRequest struct { - Limit int `json:"limit"` + Limit int `json:"limit"` + LatestTime int64 `json:"latest_time"` } type ListByFollowingResponse struct { diff --git a/internal/feed/handler.go b/internal/feed/handler.go index 98ab1ad..d440891 100644 --- a/internal/feed/handler.go +++ b/internal/feed/handler.go @@ -101,7 +101,11 @@ func (f *FeedHandler) ListByFollowing(c *gin.Context) { if err != nil { viewerAccountID = 0 } - feedItems, err := f.service.ListByFollowing(c.Request.Context(), req.Limit, viewerAccountID) + var latestTime time.Time + if req.LatestTime > 0 { + latestTime = time.Unix(req.LatestTime, 0) + } + feedItems, err := f.service.ListByFollowing(c.Request.Context(), req.Limit, latestTime, viewerAccountID) if err != nil { c.JSON(500, gin.H{"error": err.Error()}) return diff --git a/internal/feed/repo.go b/internal/feed/repo.go index 1f116d7..10f81ee 100644 --- a/internal/feed/repo.go +++ b/internal/feed/repo.go @@ -49,7 +49,7 @@ func (repo *FeedRepository) ListLikesCountWithCursor(ctx context.Context, limit return videos, nil } -func (repo *FeedRepository) ListByFollowing(ctx context.Context, limit int, viewerAccountID uint) ([]*video.Video, error) { +func (repo *FeedRepository) ListByFollowing(ctx context.Context, limit int, viewerAccountID uint, latestBefore time.Time) ([]*video.Video, error) { var videos []*video.Video query := repo.db.WithContext(ctx).Model(&video.Video{}). Order("create_time DESC") @@ -60,6 +60,9 @@ func (repo *FeedRepository) ListByFollowing(ctx context.Context, limit int, view Where("follower_id = ?", viewerAccountID) query = query.Where("author_id IN (?)", followingSubQuery) } + if !latestBefore.IsZero() { + query = query.Where("create_time < ?", latestBefore) + } if err := query.Limit(limit).Find(&videos).Error; err != nil { return nil, err } diff --git a/internal/feed/service.go b/internal/feed/service.go index 948406a..677db74 100644 --- a/internal/feed/service.go +++ b/internal/feed/service.go @@ -96,8 +96,27 @@ func (f *FeedService) ListLikesCount(ctx context.Context, limit int, cursor *Lik return resp, nil } -func (f *FeedService) ListByFollowing(ctx context.Context, limit int, viewerAccountID uint) (ListByFollowingResponse, error) { - videos, err := f.repo.ListByFollowing(ctx, limit, viewerAccountID) +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) if err != nil { return ListByFollowingResponse{}, err } @@ -117,6 +136,13 @@ func (f *FeedService) ListByFollowing(ctx context.Context, limit int, viewerAcco 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 }