package repositories import ( "context" "fmt" "time" "go.uber.org/zap" "gorm.io/gorm" "tyapi-server/internal/domains/user/entities" "tyapi-server/internal/shared/interfaces" ) // UserRepository 用户仓储实现 type UserRepository struct { db *gorm.DB cache interfaces.CacheService logger *zap.Logger } // NewUserRepository 创建用户仓储 func NewUserRepository(db *gorm.DB, cache interfaces.CacheService, logger *zap.Logger) *UserRepository { return &UserRepository{ db: db, cache: cache, logger: logger, } } // Create 创建用户 func (r *UserRepository) Create(ctx context.Context, entity *entities.User) error { if err := r.db.WithContext(ctx).Create(entity).Error; err != nil { r.logger.Error("Failed to create user", zap.Error(err)) return err } // 清除相关缓存 r.invalidateUserCaches(ctx, entity.ID) return nil } // GetByID 根据ID获取用户 func (r *UserRepository) GetByID(ctx context.Context, id string) (*entities.User, error) { // 先尝试从缓存获取 cacheKey := r.GetCacheKey(id) var user entities.User if err := r.cache.Get(ctx, cacheKey, &user); err == nil { return &user, nil } // 从数据库获取 if err := r.db.WithContext(ctx).Where("id = ? AND is_deleted = false", id).First(&user).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, fmt.Errorf("user not found") } return nil, err } // 缓存结果 r.cache.Set(ctx, cacheKey, &user, 1*time.Hour) return &user, nil } // Update 更新用户 func (r *UserRepository) Update(ctx context.Context, entity *entities.User) error { if err := r.db.WithContext(ctx).Save(entity).Error; err != nil { r.logger.Error("Failed to update user", zap.Error(err)) return err } // 清除相关缓存 r.invalidateUserCaches(ctx, entity.ID) return nil } // Delete 删除用户 func (r *UserRepository) Delete(ctx context.Context, id string) error { if err := r.db.WithContext(ctx).Delete(&entities.User{}, "id = ?", id).Error; err != nil { r.logger.Error("Failed to delete user", zap.Error(err)) return err } // 清除相关缓存 r.invalidateUserCaches(ctx, id) return nil } // CreateBatch 批量创建用户 func (r *UserRepository) CreateBatch(ctx context.Context, entities []*entities.User) error { if err := r.db.WithContext(ctx).CreateInBatches(entities, 100).Error; err != nil { r.logger.Error("Failed to create users in batch", zap.Error(err)) return err } // 清除列表缓存 r.cache.DeletePattern(ctx, "users:list:*") return nil } // GetByIDs 根据ID列表获取用户 func (r *UserRepository) GetByIDs(ctx context.Context, ids []string) ([]*entities.User, error) { var users []entities.User if err := r.db.WithContext(ctx). Where("id IN ? AND is_deleted = false", ids). Find(&users).Error; err != nil { return nil, err } // 转换为指针切片 result := make([]*entities.User, len(users)) for i := range users { result[i] = &users[i] } return result, nil } // UpdateBatch 批量更新用户 func (r *UserRepository) UpdateBatch(ctx context.Context, entities []*entities.User) error { return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { for _, entity := range entities { if err := tx.Save(entity).Error; err != nil { return err } } return nil }) } // DeleteBatch 批量删除用户 func (r *UserRepository) DeleteBatch(ctx context.Context, ids []string) error { if err := r.db.WithContext(ctx). Where("id IN ?", ids). Delete(&entities.User{}).Error; err != nil { return err } // 清除相关缓存 for _, id := range ids { r.invalidateUserCaches(ctx, id) } return nil } // List 获取用户列表 func (r *UserRepository) List(ctx context.Context, options interfaces.ListOptions) ([]*entities.User, error) { // 尝试从缓存获取 cacheKey := fmt.Sprintf("users:list:%d:%d:%s", options.Page, options.PageSize, options.Sort) var users []*entities.User if err := r.cache.Get(ctx, cacheKey, &users); err == nil { return users, nil } // 从数据库查询 query := r.db.WithContext(ctx).Where("is_deleted = false") // 应用过滤条件 if options.Search != "" { query = query.Where("username ILIKE ? OR email ILIKE ? OR first_name ILIKE ? OR last_name ILIKE ?", "%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%") } // 应用排序 if options.Sort != "" { order := options.Order if order == "" { order = "asc" } query = query.Order(fmt.Sprintf("%s %s", options.Sort, order)) } else { query = query.Order("created_at desc") } // 应用分页 if options.Page > 0 && options.PageSize > 0 { offset := (options.Page - 1) * options.PageSize query = query.Offset(offset).Limit(options.PageSize) } var userEntities []entities.User if err := query.Find(&userEntities).Error; err != nil { return nil, err } // 转换为指针切片 users = make([]*entities.User, len(userEntities)) for i := range userEntities { users[i] = &userEntities[i] } // 缓存结果 r.cache.Set(ctx, cacheKey, users, 30*time.Minute) return users, nil } // Count 统计用户数量 func (r *UserRepository) Count(ctx context.Context, options interfaces.CountOptions) (int64, error) { query := r.db.WithContext(ctx).Model(&entities.User{}).Where("is_deleted = false") // 应用过滤条件 if options.Search != "" { query = query.Where("username ILIKE ? OR email ILIKE ? OR first_name ILIKE ? OR last_name ILIKE ?", "%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%", "%"+options.Search+"%") } var count int64 if err := query.Count(&count).Error; err != nil { return 0, err } return count, nil } // Exists 检查用户是否存在 func (r *UserRepository) Exists(ctx context.Context, id string) (bool, error) { var count int64 if err := r.db.WithContext(ctx). Model(&entities.User{}). Where("id = ? AND is_deleted = false", id). Count(&count).Error; err != nil { return false, err } return count > 0, nil } // SoftDelete 软删除用户 func (r *UserRepository) SoftDelete(ctx context.Context, id string) error { if err := r.db.WithContext(ctx). Model(&entities.User{}). Where("id = ?", id). Update("is_deleted", true).Error; err != nil { return err } // 清除相关缓存 r.invalidateUserCaches(ctx, id) return nil } // Restore 恢复用户 func (r *UserRepository) Restore(ctx context.Context, id string) error { if err := r.db.WithContext(ctx). Model(&entities.User{}). Where("id = ?", id). Update("is_deleted", false).Error; err != nil { return err } // 清除相关缓存 r.invalidateUserCaches(ctx, id) return nil } // WithTx 使用事务 func (r *UserRepository) WithTx(tx interface{}) interfaces.Repository[*entities.User] { gormTx, ok := tx.(*gorm.DB) if !ok { return r } return &UserRepository{ db: gormTx, cache: r.cache, logger: r.logger, } } // InvalidateCache 清除缓存 func (r *UserRepository) InvalidateCache(ctx context.Context, keys ...string) error { return r.cache.Delete(ctx, keys...) } // WarmupCache 预热缓存 func (r *UserRepository) WarmupCache(ctx context.Context) error { // 预热热门用户数据 // 这里可以实现具体的预热逻辑 return nil } // GetCacheKey 获取缓存键 func (r *UserRepository) GetCacheKey(id string) string { return fmt.Sprintf("user:%s", id) } // FindByUsername 根据用户名查找用户 func (r *UserRepository) FindByUsername(ctx context.Context, username string) (*entities.User, error) { var user entities.User if err := r.db.WithContext(ctx). Where("username = ? AND is_deleted = false", username). First(&user).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, fmt.Errorf("user not found") } return nil, err } return &user, nil } // FindByEmail 根据邮箱查找用户 func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*entities.User, error) { var user entities.User if err := r.db.WithContext(ctx). Where("email = ? AND is_deleted = false", email). First(&user).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, fmt.Errorf("user not found") } return nil, err } return &user, nil } // invalidateUserCaches 清除用户相关缓存 func (r *UserRepository) invalidateUserCaches(ctx context.Context, userID string) { keys := []string{ r.GetCacheKey(userID), } r.cache.Delete(ctx, keys...) r.cache.DeletePattern(ctx, "users:list:*") }