456 lines
14 KiB
Go
456 lines
14 KiB
Go
package examples
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
|
||
"go.uber.org/zap"
|
||
"gorm.io/gorm"
|
||
|
||
"tyapi-server/internal/domains/user/entities"
|
||
"tyapi-server/internal/domains/user/repositories"
|
||
"tyapi-server/internal/domains/user/repositories/queries"
|
||
"tyapi-server/internal/shared/database"
|
||
"tyapi-server/internal/shared/interfaces"
|
||
)
|
||
|
||
// ModernCachedUserRepository 现代化的用户仓储(使用新缓存方案)
|
||
type ModernCachedUserRepository struct {
|
||
*database.CachedBaseRepositoryImpl
|
||
}
|
||
|
||
// 编译时检查接口实现
|
||
var _ repositories.UserRepository = (*ModernCachedUserRepository)(nil)
|
||
|
||
// NewModernCachedUserRepository 创建现代化缓存用户仓储
|
||
func NewModernCachedUserRepository(db *gorm.DB, logger *zap.Logger) repositories.UserRepository {
|
||
return &ModernCachedUserRepository{
|
||
CachedBaseRepositoryImpl: database.NewCachedBaseRepositoryImpl(db, logger, "users"),
|
||
}
|
||
}
|
||
|
||
// ================ Repository[T] 接口实现 ================
|
||
|
||
// Create 创建用户(自动失效相关缓存)
|
||
func (r *ModernCachedUserRepository) Create(ctx context.Context, user entities.User) (entities.User, error) {
|
||
r.GetLogger().Info("创建用户", zap.String("phone", user.Phone))
|
||
|
||
// 使用基础创建方法,GORM插件会自动处理缓存失效
|
||
err := r.CreateEntity(ctx, &user)
|
||
return user, err
|
||
}
|
||
|
||
// GetByID 根据ID获取用户(自动缓存30分钟)
|
||
func (r *ModernCachedUserRepository) GetByID(ctx context.Context, id string) (entities.User, error) {
|
||
var user entities.User
|
||
|
||
// 使用智能缓存查询,自动缓存30分钟
|
||
err := r.SmartGetByID(ctx, id, &user)
|
||
return user, err
|
||
}
|
||
|
||
// Update 更新用户(自动失效相关缓存)
|
||
func (r *ModernCachedUserRepository) Update(ctx context.Context, user entities.User) error {
|
||
r.GetLogger().Info("更新用户", zap.String("user_id", user.ID))
|
||
|
||
// 使用基础更新方法,GORM插件会自动处理缓存失效
|
||
return r.UpdateEntity(ctx, &user)
|
||
}
|
||
|
||
// CreateBatch 批量创建用户
|
||
func (r *ModernCachedUserRepository) CreateBatch(ctx context.Context, users []entities.User) error {
|
||
r.GetLogger().Info("批量创建用户", zap.Int("count", len(users)))
|
||
return r.CreateBatchEntity(ctx, &users)
|
||
}
|
||
|
||
// GetByIDs 根据ID列表获取用户(带缓存)
|
||
func (r *ModernCachedUserRepository) GetByIDs(ctx context.Context, ids []string) ([]entities.User, error) {
|
||
var users []entities.User
|
||
|
||
// 使用批量缓存查询,缓存15分钟
|
||
err := r.BatchGetWithCache(ctx, ids, &users, 15*time.Minute)
|
||
return users, err
|
||
}
|
||
|
||
// UpdateBatch 批量更新用户
|
||
func (r *ModernCachedUserRepository) UpdateBatch(ctx context.Context, users []entities.User) error {
|
||
r.GetLogger().Info("批量更新用户", zap.Int("count", len(users)))
|
||
return r.UpdateBatchEntity(ctx, &users)
|
||
}
|
||
|
||
// DeleteBatch 批量删除用户
|
||
func (r *ModernCachedUserRepository) DeleteBatch(ctx context.Context, ids []string) error {
|
||
r.GetLogger().Info("批量删除用户", zap.Strings("ids", ids))
|
||
return r.DeleteBatchEntity(ctx, ids, &entities.User{})
|
||
}
|
||
|
||
// List 获取用户列表(智能缓存)
|
||
func (r *ModernCachedUserRepository) List(ctx context.Context, options interfaces.ListOptions) ([]entities.User, error) {
|
||
var users []entities.User
|
||
|
||
// 使用智能列表查询,根据查询复杂度自动选择缓存策略
|
||
err := r.SmartList(ctx, &users, options)
|
||
return users, err
|
||
}
|
||
|
||
// ================ BaseRepository 接口实现 ================
|
||
|
||
// Delete 删除用户
|
||
func (r *ModernCachedUserRepository) Delete(ctx context.Context, id string) error {
|
||
return r.DeleteEntity(ctx, id, &entities.User{})
|
||
}
|
||
|
||
// Exists 检查用户是否存在(带缓存)
|
||
func (r *ModernCachedUserRepository) Exists(ctx context.Context, id string) (bool, error) {
|
||
return r.ExistsEntity(ctx, id, &entities.User{})
|
||
}
|
||
|
||
// Count 统计用户数量(智能缓存)
|
||
func (r *ModernCachedUserRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) {
|
||
var count int64
|
||
|
||
// 计算缓存TTL
|
||
cacheTTL := 10 * time.Minute
|
||
if options.Search != "" {
|
||
cacheTTL = 2 * time.Minute // 搜索查询缓存时间更短
|
||
}
|
||
|
||
err := r.CountWithCache(ctx, &count, cacheTTL, &entities.User{}, "", nil)
|
||
return count, err
|
||
}
|
||
|
||
// SoftDelete 软删除用户
|
||
func (r *ModernCachedUserRepository) SoftDelete(ctx context.Context, id string) error {
|
||
return r.SoftDeleteEntity(ctx, id, &entities.User{})
|
||
}
|
||
|
||
// Restore 恢复用户
|
||
func (r *ModernCachedUserRepository) Restore(ctx context.Context, id string) error {
|
||
return r.RestoreEntity(ctx, id, &entities.User{})
|
||
}
|
||
|
||
// ================ 业务专用方法(使用新缓存API) ================
|
||
|
||
// GetByPhone 根据手机号获取用户(缓存15分钟)
|
||
func (r *ModernCachedUserRepository) GetByPhone(ctx context.Context, phone string) (*entities.User, error) {
|
||
var user entities.User
|
||
|
||
// 使用智能字段查询,自动缓存15分钟
|
||
err := r.SmartGetByField(ctx, &user, "phone", phone, 15*time.Minute)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &user, nil
|
||
}
|
||
|
||
// GetByUsername 根据用户名获取用户(缓存15分钟)
|
||
func (r *ModernCachedUserRepository) GetByUsername(ctx context.Context, username string) (*entities.User, error) {
|
||
var user entities.User
|
||
|
||
err := r.SmartGetByField(ctx, &user, "username", username, 15*time.Minute)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &user, nil
|
||
}
|
||
|
||
// GetByUserType 根据用户类型获取用户列表
|
||
func (r *ModernCachedUserRepository) GetByUserType(ctx context.Context, userType string) ([]*entities.User, error) {
|
||
var users []*entities.User
|
||
|
||
err := r.FindWithCache(ctx, &users, 30*time.Minute, "user_type = ?", userType)
|
||
return users, err
|
||
}
|
||
|
||
// ListUsers 获取用户列表(带分页和筛选)
|
||
func (r *ModernCachedUserRepository) ListUsers(ctx context.Context, query *queries.ListUsersQuery) ([]*entities.User, int64, error) {
|
||
var users []*entities.User
|
||
var total int64
|
||
|
||
// 构建查询条件
|
||
db := r.GetDB(ctx).Set("cache:enabled", true).Set("cache:ttl", 15*time.Minute)
|
||
|
||
// 应用筛选条件
|
||
if query.Phone != "" {
|
||
db = db.Where("phone LIKE ?", "%"+query.Phone+"%")
|
||
}
|
||
if query.StartDate != "" {
|
||
db = db.Where("created_at >= ?", query.StartDate)
|
||
}
|
||
if query.EndDate != "" {
|
||
db = db.Where("created_at <= ?", query.EndDate)
|
||
}
|
||
|
||
// 统计总数
|
||
if err := db.Model(&entities.User{}).Count(&total).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
// 应用分页
|
||
offset := (query.Page - 1) * query.PageSize
|
||
if err := db.Offset(offset).Limit(query.PageSize).Find(&users).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
return users, total, nil
|
||
}
|
||
|
||
// ValidateUser 验证用户登录
|
||
func (r *ModernCachedUserRepository) ValidateUser(ctx context.Context, phone, password string) (*entities.User, error) {
|
||
// 登录验证不使用缓存,确保安全性
|
||
var user entities.User
|
||
db := r.WithoutCache().GetDB(ctx)
|
||
|
||
err := db.Where("phone = ? AND password = ?", phone, password).First(&user).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &user, nil
|
||
}
|
||
|
||
// UpdateLastLogin 更新最后登录时间
|
||
func (r *ModernCachedUserRepository) UpdateLastLogin(ctx context.Context, userID string) error {
|
||
now := time.Now()
|
||
return r.GetDB(ctx).Model(&entities.User{}).
|
||
Where("id = ?", userID).
|
||
Updates(map[string]interface{}{
|
||
"last_login_at": &now,
|
||
"updated_at": now,
|
||
}).Error
|
||
}
|
||
|
||
// UpdatePassword 更新密码
|
||
func (r *ModernCachedUserRepository) UpdatePassword(ctx context.Context, userID string, newPassword string) error {
|
||
return r.GetDB(ctx).Model(&entities.User{}).
|
||
Where("id = ?", userID).
|
||
Update("password", newPassword).Error
|
||
}
|
||
|
||
// CheckPassword 检查密码
|
||
func (r *ModernCachedUserRepository) CheckPassword(ctx context.Context, userID string, password string) (bool, error) {
|
||
var count int64
|
||
err := r.GetDB(ctx).Model(&entities.User{}).
|
||
Where("id = ? AND password = ?", userID, password).
|
||
Count(&count).Error
|
||
|
||
return count > 0, err
|
||
}
|
||
|
||
// ActivateUser 激活用户
|
||
func (r *ModernCachedUserRepository) ActivateUser(ctx context.Context, userID string) error {
|
||
return r.GetDB(ctx).Model(&entities.User{}).
|
||
Where("id = ?", userID).
|
||
Update("active", true).Error
|
||
}
|
||
|
||
// DeactivateUser 停用用户
|
||
func (r *ModernCachedUserRepository) DeactivateUser(ctx context.Context, userID string) error {
|
||
return r.GetDB(ctx).Model(&entities.User{}).
|
||
Where("id = ?", userID).
|
||
Update("active", false).Error
|
||
}
|
||
|
||
// UpdateLoginStats 更新登录统计
|
||
func (r *ModernCachedUserRepository) UpdateLoginStats(ctx context.Context, userID string) error {
|
||
return r.GetDB(ctx).Model(&entities.User{}).
|
||
Where("id = ?", userID).
|
||
Updates(map[string]interface{}{
|
||
"login_count": gorm.Expr("login_count + 1"),
|
||
"last_login_at": time.Now(),
|
||
}).Error
|
||
}
|
||
|
||
// GetStats 获取用户统计信息
|
||
func (r *ModernCachedUserRepository) GetStats(ctx context.Context) (*repositories.UserStats, error) {
|
||
var stats repositories.UserStats
|
||
|
||
// 使用短期缓存获取统计信息
|
||
db := r.GetDB(ctx).Set("cache:enabled", true).Set("cache:ttl", 5*time.Minute)
|
||
|
||
// 总用户数
|
||
if err := db.Model(&entities.User{}).Count(&stats.TotalUsers).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 活跃用户数
|
||
if err := db.Model(&entities.User{}).Where("active = ?", true).Count(&stats.ActiveUsers).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 今日注册数
|
||
today := time.Now().Truncate(24 * time.Hour)
|
||
if err := db.Model(&entities.User{}).Where("created_at >= ?", today).Count(&stats.TodayRegistrations).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 今日登录数
|
||
if err := db.Model(&entities.User{}).Where("last_login_at >= ?", today).Count(&stats.TodayLogins).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &stats, nil
|
||
}
|
||
|
||
// GetStatsByDateRange 获取指定日期范围的用户统计
|
||
func (r *ModernCachedUserRepository) GetStatsByDateRange(ctx context.Context, startDate, endDate string) (*repositories.UserStats, error) {
|
||
var stats repositories.UserStats
|
||
|
||
db := r.GetDB(ctx).Set("cache:enabled", true).Set("cache:ttl", 10*time.Minute)
|
||
|
||
// 指定时间范围内的注册数
|
||
if err := db.Model(&entities.User{}).
|
||
Where("created_at >= ? AND created_at <= ?", startDate, endDate).
|
||
Count(&stats.TodayRegistrations).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 指定时间范围内的登录数
|
||
if err := db.Model(&entities.User{}).
|
||
Where("last_login_at >= ? AND last_login_at <= ?", startDate, endDate).
|
||
Count(&stats.TodayLogins).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &stats, nil
|
||
}
|
||
|
||
// GetActiveUsers 获取活跃用户(使用短期缓存)
|
||
func (r *ModernCachedUserRepository) GetActiveUsers(ctx context.Context) ([]entities.User, error) {
|
||
var users []entities.User
|
||
|
||
// 活跃用户查询使用短期缓存(5分钟)
|
||
err := r.WithShortCache().FindWithCache(ctx, &users, 5*time.Minute, "active = ?", true)
|
||
return users, err
|
||
}
|
||
|
||
// GetUsersByType 根据用户类型获取用户(使用中期缓存)
|
||
func (r *ModernCachedUserRepository) GetUsersByType(ctx context.Context, userType string) ([]entities.User, error) {
|
||
var users []entities.User
|
||
|
||
// 用户类型查询使用中期缓存(30分钟)
|
||
err := r.WithMediumCache().FindWithCache(ctx, &users, 30*time.Minute, "user_type = ?", userType)
|
||
return users, err
|
||
}
|
||
|
||
// GetRecentUsers 获取最近注册用户(禁用缓存,实时数据)
|
||
func (r *ModernCachedUserRepository) GetRecentUsers(ctx context.Context, limit int) ([]entities.User, error) {
|
||
var users []entities.User
|
||
|
||
// 最近用户查询禁用缓存,保证数据实时性
|
||
db := r.WithoutCache().GetDB(ctx)
|
||
err := db.Order("created_at DESC").Limit(limit).Find(&users).Error
|
||
|
||
return users, err
|
||
}
|
||
|
||
// GetPopularUsers 获取热门用户(使用长期缓存)
|
||
func (r *ModernCachedUserRepository) GetPopularUsers(ctx context.Context, limit int) ([]entities.User, error) {
|
||
var users []entities.User
|
||
|
||
// 热门用户查询使用长期缓存(2小时)
|
||
err := r.WithLongCache().GetDB(ctx).
|
||
Order("login_count DESC").
|
||
Limit(limit).
|
||
Find(&users).Error
|
||
|
||
return users, err
|
||
}
|
||
|
||
// SearchUsers 搜索用户(智能缓存策略)
|
||
func (r *ModernCachedUserRepository) SearchUsers(ctx context.Context, keyword string, limit int) ([]entities.User, error) {
|
||
var users []entities.User
|
||
|
||
// 搜索查询使用短期缓存,避免频繁的数据库查询
|
||
db := r.GetDB(ctx).
|
||
Set("cache:enabled", true).
|
||
Set("cache:ttl", 2*time.Minute). // 搜索结果缓存2分钟
|
||
Where("username LIKE ? OR phone LIKE ?", "%"+keyword+"%", "%"+keyword+"%").
|
||
Limit(limit)
|
||
|
||
err := db.Find(&users).Error
|
||
return users, err
|
||
}
|
||
|
||
// ================ 缓存管理方法 ================
|
||
|
||
// WarmupUserCache 预热用户缓存
|
||
func (r *ModernCachedUserRepository) WarmupUserCache(ctx context.Context) error {
|
||
r.GetLogger().Info("开始预热用户缓存")
|
||
|
||
// 定义预热查询
|
||
queries := []database.WarmupQuery{
|
||
{
|
||
Name: "active_users",
|
||
TTL: 30 * time.Minute,
|
||
Dest: &[]entities.User{},
|
||
},
|
||
{
|
||
Name: "user_types",
|
||
TTL: 60 * time.Minute,
|
||
Dest: &[]entities.User{},
|
||
},
|
||
{
|
||
Name: "recent_users",
|
||
TTL: 10 * time.Minute,
|
||
Dest: &[]entities.User{},
|
||
},
|
||
}
|
||
|
||
return r.WarmupCommonQueries(ctx, queries)
|
||
}
|
||
|
||
// RefreshUserCache 刷新用户缓存
|
||
func (r *ModernCachedUserRepository) RefreshUserCache(ctx context.Context) error {
|
||
r.GetLogger().Info("刷新用户缓存")
|
||
|
||
// 刷新用户相关的所有缓存
|
||
return r.RefreshCache(ctx, "users:*")
|
||
}
|
||
|
||
// GetUserCacheStats 获取用户缓存统计
|
||
func (r *ModernCachedUserRepository) GetUserCacheStats() map[string]interface{} {
|
||
stats := r.GetCacheInfo()
|
||
stats["specific_patterns"] = []string{
|
||
"gorm_cache:users:*",
|
||
"user:id:*",
|
||
"user:phone:*",
|
||
}
|
||
return stats
|
||
}
|
||
|
||
// ================ 使用示例 ================
|
||
|
||
// ExampleUsage 使用示例
|
||
func (r *ModernCachedUserRepository) ExampleUsage(ctx context.Context) {
|
||
// 1. 基础查询(自动缓存)
|
||
user, _ := r.GetByID(ctx, "user-123")
|
||
r.GetLogger().Info("获取用户", zap.String("username", user.Username))
|
||
|
||
// 2. 手动控制缓存
|
||
// 使用短期缓存查询
|
||
var activeUsers []entities.User
|
||
_ = r.WithShortCache().FindWithCache(ctx, &activeUsers, 5*time.Minute, "active = ?", true)
|
||
r.GetLogger().Info("活跃用户数", zap.Int("count", len(activeUsers)))
|
||
|
||
// 禁用缓存查询
|
||
var recentUsers []entities.User
|
||
_ = r.WithoutCache().FindWhere(ctx, &recentUsers, "created_at > ?", time.Now().AddDate(0, 0, -7))
|
||
r.GetLogger().Info("最近用户数", zap.Int("count", len(recentUsers)))
|
||
|
||
// 3. 智能缓存查询
|
||
options := interfaces.ListOptions{
|
||
Page: 1,
|
||
PageSize: 20,
|
||
Filters: map[string]interface{}{"active": true},
|
||
Sort: "created_at",
|
||
Order: "desc",
|
||
}
|
||
users, _ := r.List(ctx, options) // 自动根据查询复杂度选择缓存策略
|
||
r.GetLogger().Info("用户列表", zap.Int("count", len(users)))
|
||
|
||
// 4. 缓存预热
|
||
r.WarmupUserCache(ctx)
|
||
} |