feat(social): cache trending hashtags in Redis
This commit is contained in:
parent
ae50f6956a
commit
7e171f1c1e
3 changed files with 39 additions and 3 deletions
|
|
@ -10,6 +10,9 @@ import (
|
|||
// setupSocialRoutes configure les routes sociales
|
||||
func (r *APIRouter) setupSocialRoutes(router *gin.RouterGroup) {
|
||||
socialService := socialcore.NewService(r.db.GormDB, r.logger)
|
||||
if r.config.CacheService != nil {
|
||||
socialService.SetCacheService(r.config.CacheService)
|
||||
}
|
||||
socialHandler := handlers.NewSocialHandler(socialService, r.logger)
|
||||
groupHandler := handlers.NewGroupHandler(socialService, r.logger)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
"github.com/google/uuid"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"veza-backend-api/internal/services"
|
||||
)
|
||||
|
||||
// SocialService gère les interactions sociales
|
||||
|
|
@ -30,8 +32,14 @@ type SocialService interface {
|
|||
|
||||
// Service implémente SocialService
|
||||
type Service struct {
|
||||
db *gorm.DB
|
||||
logger *zap.Logger
|
||||
db *gorm.DB
|
||||
logger *zap.Logger
|
||||
cacheService *services.CacheService // optional, for trending cache
|
||||
}
|
||||
|
||||
// SetCacheService définit le service de cache (optionnel, pour trending)
|
||||
func (s *Service) SetCacheService(cache *services.CacheService) {
|
||||
s.cacheService = cache
|
||||
}
|
||||
|
||||
// NewService crée une nouvelle instance du service social
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TrendingTag represents a hashtag with its occurrence count
|
||||
|
|
@ -16,8 +17,12 @@ type TrendingTag struct {
|
|||
// trendingHashtagRegex matches #word patterns in post content
|
||||
var trendingHashtagRegex = regexp.MustCompile(`#(\w+)`)
|
||||
|
||||
const trendingCacheKey = "trending:hashtags"
|
||||
const trendingCacheTTL = 15 * time.Minute
|
||||
const trendingCacheLimit = 50
|
||||
|
||||
// GetTrendingHashtags extracts hashtags from recent posts and returns them sorted by count.
|
||||
// Posts from the last 7 days are considered.
|
||||
// Posts from the last 7 days are considered. Uses Redis cache if available (15 min TTL).
|
||||
func (s *Service) GetTrendingHashtags(ctx context.Context, limit int) ([]TrendingTag, error) {
|
||||
if limit <= 0 {
|
||||
limit = 10
|
||||
|
|
@ -26,6 +31,17 @@ func (s *Service) GetTrendingHashtags(ctx context.Context, limit int) ([]Trendin
|
|||
limit = 50
|
||||
}
|
||||
|
||||
// Try cache first (cache stores top 50, we slice to limit)
|
||||
if s.cacheService != nil {
|
||||
var cached []TrendingTag
|
||||
if err := s.cacheService.Get(ctx, trendingCacheKey, &cached); err == nil {
|
||||
if len(cached) >= limit {
|
||||
return cached[:limit], nil
|
||||
}
|
||||
return cached, nil
|
||||
}
|
||||
}
|
||||
|
||||
var posts []Post
|
||||
if err := s.db.WithContext(ctx).
|
||||
Where("created_at > NOW() - INTERVAL '7 days'").
|
||||
|
|
@ -58,6 +74,15 @@ func (s *Service) GetTrendingHashtags(ctx context.Context, limit int) ([]Trendin
|
|||
return result[i].Tag < result[j].Tag
|
||||
})
|
||||
|
||||
// Cache full result (top 50) for future requests
|
||||
if s.cacheService != nil && len(result) > 0 {
|
||||
toCache := result
|
||||
if len(toCache) > trendingCacheLimit {
|
||||
toCache = toCache[:trendingCacheLimit]
|
||||
}
|
||||
_ = s.cacheService.Set(ctx, trendingCacheKey, toCache, trendingCacheTTL)
|
||||
}
|
||||
|
||||
if len(result) > limit {
|
||||
result = result[:limit]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue