mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 00:31:35 +00:00
287 lines
7.5 KiB
Go
287 lines
7.5 KiB
Go
package repositories
|
|
|
|
import (
|
|
"context"
|
|
"tercul/internal/models"
|
|
"time"
|
|
|
|
"tercul/internal/platform/cache"
|
|
"tercul/internal/platform/log"
|
|
)
|
|
|
|
// CachedWorkRepository wraps a WorkRepository with caching functionality
|
|
type CachedWorkRepository struct {
|
|
*CachedRepository[models.Work]
|
|
workRepo WorkRepository
|
|
}
|
|
|
|
// NewCachedWorkRepository creates a new CachedWorkRepository
|
|
func NewCachedWorkRepository(
|
|
workRepo WorkRepository,
|
|
cache cache.Cache,
|
|
keyGenerator cache.KeyGenerator,
|
|
cacheExpiry time.Duration,
|
|
) *CachedWorkRepository {
|
|
if keyGenerator == nil {
|
|
keyGenerator = &simpleKeyGenerator{prefix: "tercul:"}
|
|
}
|
|
|
|
if cacheExpiry == 0 {
|
|
cacheExpiry = 30 * time.Minute // Default expiry of 30 minutes
|
|
}
|
|
|
|
return &CachedWorkRepository{
|
|
CachedRepository: NewCachedRepository[models.Work](
|
|
workRepo,
|
|
cache,
|
|
keyGenerator,
|
|
"work",
|
|
cacheExpiry,
|
|
),
|
|
workRepo: workRepo,
|
|
}
|
|
}
|
|
|
|
// FindByTitle finds works by title (partial match)
|
|
func (r *CachedWorkRepository) FindByTitle(ctx context.Context, title string) ([]models.Work, error) {
|
|
if !r.cacheEnabled {
|
|
return r.workRepo.FindByTitle(ctx, title)
|
|
}
|
|
|
|
cacheKey := r.keyGenerator.QueryKey(r.entityType, "title", title)
|
|
|
|
var result []models.Work
|
|
err := r.cache.Get(ctx, cacheKey, &result)
|
|
if err == nil {
|
|
// Cache hit
|
|
log.LogDebug("Cache hit for FindByTitle",
|
|
log.F("entityType", r.entityType),
|
|
log.F("title", title))
|
|
return result, nil
|
|
}
|
|
|
|
// Cache miss, get from database
|
|
log.LogDebug("Cache miss for FindByTitle",
|
|
log.F("entityType", r.entityType),
|
|
log.F("title", title))
|
|
|
|
result, err = r.workRepo.FindByTitle(ctx, title)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store in cache
|
|
if err := r.cache.Set(ctx, cacheKey, result, r.cacheExpiry); err != nil {
|
|
log.LogWarn("Failed to cache FindByTitle result",
|
|
log.F("entityType", r.entityType),
|
|
log.F("title", title),
|
|
log.F("error", err))
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// FindByAuthor finds works by author ID
|
|
func (r *CachedWorkRepository) FindByAuthor(ctx context.Context, authorID uint) ([]models.Work, error) {
|
|
if !r.cacheEnabled {
|
|
return r.workRepo.FindByAuthor(ctx, authorID)
|
|
}
|
|
|
|
cacheKey := r.keyGenerator.QueryKey(r.entityType, "author", authorID)
|
|
|
|
var result []models.Work
|
|
err := r.cache.Get(ctx, cacheKey, &result)
|
|
if err == nil {
|
|
// Cache hit
|
|
log.LogDebug("Cache hit for FindByAuthor",
|
|
log.F("entityType", r.entityType),
|
|
log.F("authorID", authorID))
|
|
return result, nil
|
|
}
|
|
|
|
// Cache miss, get from database
|
|
log.LogDebug("Cache miss for FindByAuthor",
|
|
log.F("entityType", r.entityType),
|
|
log.F("authorID", authorID))
|
|
|
|
result, err = r.workRepo.FindByAuthor(ctx, authorID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store in cache
|
|
if err := r.cache.Set(ctx, cacheKey, result, r.cacheExpiry); err != nil {
|
|
log.LogWarn("Failed to cache FindByAuthor result",
|
|
log.F("entityType", r.entityType),
|
|
log.F("authorID", authorID),
|
|
log.F("error", err))
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// FindByCategory finds works by category ID
|
|
func (r *CachedWorkRepository) FindByCategory(ctx context.Context, categoryID uint) ([]models.Work, error) {
|
|
if !r.cacheEnabled {
|
|
return r.workRepo.FindByCategory(ctx, categoryID)
|
|
}
|
|
|
|
cacheKey := r.keyGenerator.QueryKey(r.entityType, "category", categoryID)
|
|
|
|
var result []models.Work
|
|
err := r.cache.Get(ctx, cacheKey, &result)
|
|
if err == nil {
|
|
// Cache hit
|
|
log.LogDebug("Cache hit for FindByCategory",
|
|
log.F("entityType", r.entityType),
|
|
log.F("categoryID", categoryID))
|
|
return result, nil
|
|
}
|
|
|
|
// Cache miss, get from database
|
|
log.LogDebug("Cache miss for FindByCategory",
|
|
log.F("entityType", r.entityType),
|
|
log.F("categoryID", categoryID))
|
|
|
|
result, err = r.workRepo.FindByCategory(ctx, categoryID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store in cache
|
|
if err := r.cache.Set(ctx, cacheKey, result, r.cacheExpiry); err != nil {
|
|
log.LogWarn("Failed to cache FindByCategory result",
|
|
log.F("entityType", r.entityType),
|
|
log.F("categoryID", categoryID),
|
|
log.F("error", err))
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// FindByLanguage finds works by language with pagination
|
|
func (r *CachedWorkRepository) FindByLanguage(ctx context.Context, language string, page, pageSize int) (*PaginatedResult[models.Work], error) {
|
|
if !r.cacheEnabled {
|
|
return r.workRepo.FindByLanguage(ctx, language, page, pageSize)
|
|
}
|
|
|
|
cacheKey := r.keyGenerator.QueryKey(r.entityType, "language", language, page, pageSize)
|
|
|
|
var result PaginatedResult[models.Work]
|
|
err := r.cache.Get(ctx, cacheKey, &result)
|
|
if err == nil {
|
|
// Cache hit
|
|
log.LogDebug("Cache hit for FindByLanguage",
|
|
log.F("entityType", r.entityType),
|
|
log.F("language", language),
|
|
log.F("page", page),
|
|
log.F("pageSize", pageSize))
|
|
return &result, nil
|
|
}
|
|
|
|
// Cache miss, get from database
|
|
log.LogDebug("Cache miss for FindByLanguage",
|
|
log.F("entityType", r.entityType),
|
|
log.F("language", language),
|
|
log.F("page", page),
|
|
log.F("pageSize", pageSize))
|
|
|
|
result_ptr, err := r.workRepo.FindByLanguage(ctx, language, page, pageSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store in cache
|
|
if err := r.cache.Set(ctx, cacheKey, result_ptr, r.cacheExpiry); err != nil {
|
|
log.LogWarn("Failed to cache FindByLanguage result",
|
|
log.F("entityType", r.entityType),
|
|
log.F("language", language),
|
|
log.F("page", page),
|
|
log.F("pageSize", pageSize),
|
|
log.F("error", err))
|
|
}
|
|
|
|
return result_ptr, nil
|
|
}
|
|
|
|
// GetWithTranslations gets a work with its translations
|
|
func (r *CachedWorkRepository) GetWithTranslations(ctx context.Context, id uint) (*models.Work, error) {
|
|
if !r.cacheEnabled {
|
|
return r.workRepo.GetWithTranslations(ctx, id)
|
|
}
|
|
|
|
cacheKey := r.keyGenerator.QueryKey(r.entityType, "with_translations", id)
|
|
|
|
var result models.Work
|
|
err := r.cache.Get(ctx, cacheKey, &result)
|
|
if err == nil {
|
|
// Cache hit
|
|
log.LogDebug("Cache hit for GetWithTranslations",
|
|
log.F("entityType", r.entityType),
|
|
log.F("id", id))
|
|
return &result, nil
|
|
}
|
|
|
|
// Cache miss, get from database
|
|
log.LogDebug("Cache miss for GetWithTranslations",
|
|
log.F("entityType", r.entityType),
|
|
log.F("id", id))
|
|
|
|
result_ptr, err := r.workRepo.GetWithTranslations(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store in cache
|
|
if err := r.cache.Set(ctx, cacheKey, result_ptr, r.cacheExpiry); err != nil {
|
|
log.LogWarn("Failed to cache GetWithTranslations result",
|
|
log.F("entityType", r.entityType),
|
|
log.F("id", id),
|
|
log.F("error", err))
|
|
}
|
|
|
|
return result_ptr, nil
|
|
}
|
|
|
|
// ListWithTranslations lists works with their translations
|
|
func (r *CachedWorkRepository) ListWithTranslations(ctx context.Context, page, pageSize int) (*PaginatedResult[models.Work], error) {
|
|
if !r.cacheEnabled {
|
|
return r.workRepo.ListWithTranslations(ctx, page, pageSize)
|
|
}
|
|
|
|
cacheKey := r.keyGenerator.QueryKey(r.entityType, "list_with_translations", page, pageSize)
|
|
|
|
var result PaginatedResult[models.Work]
|
|
err := r.cache.Get(ctx, cacheKey, &result)
|
|
if err == nil {
|
|
// Cache hit
|
|
log.LogDebug("Cache hit for ListWithTranslations",
|
|
log.F("entityType", r.entityType),
|
|
log.F("page", page),
|
|
log.F("pageSize", pageSize))
|
|
return &result, nil
|
|
}
|
|
|
|
// Cache miss, get from database
|
|
log.LogDebug("Cache miss for ListWithTranslations",
|
|
log.F("entityType", r.entityType),
|
|
log.F("page", page),
|
|
log.F("pageSize", pageSize))
|
|
|
|
result_ptr, err := r.workRepo.ListWithTranslations(ctx, page, pageSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store in cache
|
|
if err := r.cache.Set(ctx, cacheKey, result_ptr, r.cacheExpiry); err != nil {
|
|
log.LogWarn("Failed to cache ListWithTranslations result",
|
|
log.F("entityType", r.entityType),
|
|
log.F("page", page),
|
|
log.F("pageSize", pageSize),
|
|
log.F("error", err))
|
|
}
|
|
|
|
return result_ptr, nil
|
|
}
|