2025-10-04 00:47:27 +08:00
|
|
|
|
package repository
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2025-11-05 23:00:07 +08:00
|
|
|
|
"context"
|
2025-10-04 00:47:27 +08:00
|
|
|
|
"fmt"
|
|
|
|
|
|
|
2025-10-04 01:02:40 +08:00
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
2025-11-05 23:00:07 +08:00
|
|
|
|
|
2025-10-04 00:47:27 +08:00
|
|
|
|
"gorm.io/gorm"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// UnitOfWork 定义了工作单元接口,用于抽象事务管理
|
|
|
|
|
|
type UnitOfWork interface {
|
|
|
|
|
|
// ExecuteInTransaction 在一个数据库事务中执行给定的函数。
|
|
|
|
|
|
// 如果函数返回错误,事务将被回滚;否则,事务将被提交。
|
|
|
|
|
|
// tx 参数是当前事务的 GORM DB 实例,应传递给所有仓库方法。
|
2025-11-05 23:00:07 +08:00
|
|
|
|
ExecuteInTransaction(ctx context.Context, fn func(tx *gorm.DB) error) error
|
2025-10-04 00:47:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// gormUnitOfWork 是 UnitOfWork 接口的 GORM 实现
|
|
|
|
|
|
type gormUnitOfWork struct {
|
2025-11-05 23:00:07 +08:00
|
|
|
|
ctx context.Context
|
|
|
|
|
|
db *gorm.DB
|
2025-10-04 00:47:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewGormUnitOfWork 创建一个新的 gormUnitOfWork 实例
|
2025-11-05 23:00:07 +08:00
|
|
|
|
func NewGormUnitOfWork(ctx context.Context, db *gorm.DB) UnitOfWork {
|
|
|
|
|
|
return &gormUnitOfWork{
|
|
|
|
|
|
ctx: ctx,
|
|
|
|
|
|
db: db,
|
|
|
|
|
|
}
|
2025-10-04 00:47:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ExecuteInTransaction 实现了 UnitOfWork 接口的事务执行逻辑
|
2025-11-05 23:00:07 +08:00
|
|
|
|
func (u *gormUnitOfWork) ExecuteInTransaction(ctx context.Context, fn func(tx *gorm.DB) error) error {
|
|
|
|
|
|
uowCtx, logger := logs.Trace(ctx, u.ctx, "ExecuteInTransaction")
|
|
|
|
|
|
|
|
|
|
|
|
tx := u.db.WithContext(uowCtx).Begin()
|
2025-10-04 00:47:27 +08:00
|
|
|
|
if tx.Error != nil {
|
2025-11-05 23:00:07 +08:00
|
|
|
|
logger.Errorf("开启数据库事务失败: %v", tx.Error) // 记录错误日志
|
2025-10-04 00:47:27 +08:00
|
|
|
|
return fmt.Errorf("开启事务失败: %w", tx.Error)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
|
|
tx.Rollback()
|
2025-11-05 23:00:07 +08:00
|
|
|
|
logger.Errorf("事务中发生 panic,已回滚: %v", r) // 记录 panic 日志
|
2025-10-04 00:47:27 +08:00
|
|
|
|
} else if tx.Error != nil { // 如果函数执行过程中返回错误,或者事务本身有错误,则回滚
|
|
|
|
|
|
tx.Rollback()
|
2025-11-05 23:00:07 +08:00
|
|
|
|
logger.Errorf("事务执行失败,已回滚: %v", tx.Error) // 记录错误日志
|
2025-10-04 00:47:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
// 执行业务逻辑函数
|
|
|
|
|
|
if err := fn(tx); err != nil {
|
|
|
|
|
|
tx.Rollback()
|
|
|
|
|
|
return err // 返回业务逻辑函数中的错误
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提交事务
|
|
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
2025-11-05 23:00:07 +08:00
|
|
|
|
logger.Errorf("提交数据库事务失败: %v", err) // 记录错误日志
|
2025-10-04 00:47:27 +08:00
|
|
|
|
return fmt.Errorf("提交事务失败: %w", err)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|