add redis cache to results

This commit is contained in:
timka
2025-12-17 18:38:54 +03:00
parent 7bf909652b
commit f5f6c7850c
4 changed files with 89 additions and 17 deletions
+63 -3
View File
@@ -16,9 +16,15 @@ import (
)
const (
resultCachePrefix = "result:"
resultCachePrefix = "result:"
leaderboardCachePrefix = "leaderboard:"
)
type leaderboardCache struct {
Results []domain.Result `json:"results"`
TotalCount int `json:"total_count"`
}
type ResultRepository struct {
db *sql.DB
redisClient *redis.Client
@@ -37,6 +43,21 @@ func (r *ResultRepository) cacheKey(id string) string {
return resultCachePrefix + id
}
func (r *ResultRepository) leaderboardCacheKey(competitionID uuid.UUID, limit, offset int) string {
return fmt.Sprintf("%s%s:limit:%d:offset:%d", leaderboardCachePrefix, competitionID.String(), limit, offset)
}
func (r *ResultRepository) invalidateLeaderboardCache(ctx context.Context, competitionID uuid.UUID) {
if !r.cacheEnabled {
return
}
pattern := fmt.Sprintf("%s%s:*", leaderboardCachePrefix, competitionID.String())
keys, err := r.redisClient.Keys(ctx, pattern).Result()
if err == nil && len(keys) > 0 {
r.redisClient.Del(ctx, keys...).Err()
}
}
func (r *ResultRepository) Create(ctx context.Context, result *domain.Result) error {
metadataJSON, err := json.Marshal(result.Metadata)
if err != nil {
@@ -65,6 +86,7 @@ func (r *ResultRepository) Create(ctx context.Context, result *domain.Result) er
}
if r.cacheEnabled {
r.invalidateLeaderboardCache(ctx, result.CompetitionID)
data, err := json.Marshal(result)
if err == nil {
r.redisClient.Set(ctx, r.cacheKey(result.ID.String()), data, 10*time.Minute).Err()
@@ -160,6 +182,7 @@ func (r *ResultRepository) Update(ctx context.Context, result *domain.Result) er
}
if r.cacheEnabled {
r.invalidateLeaderboardCache(ctx, result.CompetitionID)
r.redisClient.Del(ctx, r.cacheKey(result.ID.String())).Err()
}
@@ -312,6 +335,16 @@ func (r *ResultRepository) GetByCompetitionAndUser(ctx context.Context, competit
}
func (r *ResultRepository) GetLeaderboard(ctx context.Context, competitionID uuid.UUID, limit int, offset int) ([]domain.Result, int, error) {
if r.cacheEnabled {
key := r.leaderboardCacheKey(competitionID, limit, offset)
val, err := r.redisClient.Get(ctx, key).Result()
if err == nil {
var cached leaderboardCache
if json.Unmarshal([]byte(val), &cached) == nil {
return cached.Results, cached.TotalCount, nil
}
}
}
countQuery := `SELECT COUNT(*) FROM results WHERE competition_id = $1 AND status = $2`
var total int
if err := r.db.QueryRowContext(ctx, countQuery, competitionID, domain.ResultStatusCompleted).Scan(&total); err != nil {
@@ -359,6 +392,15 @@ func (r *ResultRepository) GetLeaderboard(ctx context.Context, competitionID uui
results = append(results, result)
}
if r.cacheEnabled {
key := r.leaderboardCacheKey(competitionID, limit, offset)
cacheData := leaderboardCache{Results: results, TotalCount: total}
data, err := json.Marshal(cacheData)
if err == nil {
r.redisClient.Set(ctx, key, data, 1*time.Minute).Err()
}
}
return results, total, nil
}
@@ -382,7 +424,16 @@ func (r *ResultRepository) UpdateStatus(ctx context.Context, id uuid.UUID, statu
r.redisClient.Del(ctx, r.cacheKey(id.String())).Err()
}
return r.Get(ctx, id)
result, err := r.Get(ctx, id)
if err != nil {
return nil, err
}
if r.cacheEnabled {
r.invalidateLeaderboardCache(ctx, result.CompetitionID)
}
return result, nil
}
func (r *ResultRepository) RecalculateRanks(ctx context.Context, competitionID uuid.UUID) error {
@@ -425,5 +476,14 @@ func (r *ResultRepository) RecalculateRanks(ctx context.Context, competitionID u
}
}
return tx.Commit()
err = tx.Commit()
if err != nil {
return err
}
if r.cacheEnabled {
r.invalidateLeaderboardCache(ctx, competitionID)
}
return nil
}