122 lines
4.3 KiB
Go
122 lines
4.3 KiB
Go
package mysqldao
|
|
|
|
import (
|
|
"context"
|
|
|
|
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/global"
|
|
"git.lzcwy.cn/zhengchiliu/zt-closet-backend/internal/mysqlmodel"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// BenefitGrantTaskDao 权益发放补偿任务数据访问
|
|
type BenefitGrantTaskDao struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewBenefitGrantTaskDao 创建补偿任务 DAO
|
|
func NewBenefitGrantTaskDao() *BenefitGrantTaskDao {
|
|
return &BenefitGrantTaskDao{db: global.MysqlEngine}
|
|
}
|
|
|
|
// BenefitGrantTaskCreate 创建补偿任务,依赖唯一索引 (order_no, benefit_type) 防重复发放。
|
|
func (d *BenefitGrantTaskDao) BenefitGrantTaskCreate(ctx context.Context, task *mysqlmodel.BenefitGrantTask) error {
|
|
ctx, span := global.Tracer.Start(ctx, "mysqldao.BenefitGrantTaskCreate")
|
|
defer span.End()
|
|
|
|
if err := d.db.WithContext(ctx).Create(task).Error; err != nil {
|
|
span.RecordError(err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// BenefitGrantTaskGetByOrderNoAndType 按订单号+权益类型查询补偿任务。
|
|
func (d *BenefitGrantTaskDao) BenefitGrantTaskGetByOrderNoAndType(ctx context.Context, orderNo string, benefitType int8) (*mysqlmodel.BenefitGrantTask, error) {
|
|
ctx, span := global.Tracer.Start(ctx, "mysqldao.BenefitGrantTaskGetByOrderNoAndType")
|
|
defer span.End()
|
|
|
|
var task mysqlmodel.BenefitGrantTask
|
|
if err := d.db.WithContext(ctx).
|
|
Where("order_no = ? AND benefit_type = ?", orderNo, benefitType).
|
|
First(&task).Error; err != nil {
|
|
span.RecordError(err)
|
|
return nil, err
|
|
}
|
|
return &task, nil
|
|
}
|
|
|
|
// BenefitGrantTaskUpdateByID 按主键更新补偿任务字段。
|
|
func (d *BenefitGrantTaskDao) BenefitGrantTaskUpdateByID(ctx context.Context, id int64, updates map[string]any) error {
|
|
ctx, span := global.Tracer.Start(ctx, "mysqldao.BenefitGrantTaskUpdateByID")
|
|
defer span.End()
|
|
|
|
if err := d.db.WithContext(ctx).Model(&mysqlmodel.BenefitGrantTask{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
|
span.RecordError(err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// BenefitGrantTaskListPending 查询待发放的补偿任务(status=0),按主键升序。
|
|
func (d *BenefitGrantTaskDao) BenefitGrantTaskListPending(ctx context.Context, limit int) ([]mysqlmodel.BenefitGrantTask, error) {
|
|
ctx, span := global.Tracer.Start(ctx, "mysqldao.BenefitGrantTaskListPending")
|
|
defer span.End()
|
|
|
|
var list []mysqlmodel.BenefitGrantTask
|
|
if err := d.db.WithContext(ctx).
|
|
Where("status = ?", 0).
|
|
Order("id ASC").
|
|
Limit(limit).
|
|
Find(&list).Error; err != nil {
|
|
span.RecordError(err)
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
// BenefitGrantTaskReset 将失败任务重置为待发放(首次发放遇到 failed 记录时复用)。
|
|
// 保留 retry_count:不归零,保证重试上限与人工介入机制不被重置绕过;
|
|
// 调用方应配合冷却期使用,避免高频回调无限重置。
|
|
func (d *BenefitGrantTaskDao) BenefitGrantTaskReset(ctx context.Context, id int64) error {
|
|
ctx, span := global.Tracer.Start(ctx, "mysqldao.BenefitGrantTaskReset")
|
|
defer span.End()
|
|
|
|
if err := d.db.WithContext(ctx).Model(&mysqlmodel.BenefitGrantTask{}).
|
|
Where("id = ?", id).
|
|
Updates(map[string]any{"status": 0, "last_error": ""}).Error; err != nil {
|
|
span.RecordError(err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// BenefitGrantTaskClaim 条件认领任务(待发放/失败 -> 发放中),返回是否认领成功,防并发重复发放。
|
|
func (d *BenefitGrantTaskDao) BenefitGrantTaskClaim(ctx context.Context, id int64) (bool, error) {
|
|
ctx, span := global.Tracer.Start(ctx, "mysqldao.BenefitGrantTaskClaim")
|
|
defer span.End()
|
|
|
|
res := d.db.WithContext(ctx).Model(&mysqlmodel.BenefitGrantTask{}).
|
|
Where("id = ? AND status IN (?, ?)", id, 0, 2).
|
|
Update("status", 3)
|
|
if res.Error != nil {
|
|
span.RecordError(res.Error)
|
|
return false, res.Error
|
|
}
|
|
return res.RowsAffected > 0, nil
|
|
}
|
|
|
|
// BenefitGrantTaskRecoverStale 将「发放中」且超过一定时间未完成的任务重置为待发放(认领后崩溃的恢复)。
|
|
func (d *BenefitGrantTaskDao) BenefitGrantTaskRecoverStale(ctx context.Context, beforeUpdatedAt int64) (int64, error) {
|
|
ctx, span := global.Tracer.Start(ctx, "mysqldao.BenefitGrantTaskRecoverStale")
|
|
defer span.End()
|
|
|
|
res := d.db.WithContext(ctx).Model(&mysqlmodel.BenefitGrantTask{}).
|
|
Where("status = ? AND updated_at < ?", 3, beforeUpdatedAt).
|
|
Update("status", 0)
|
|
if res.Error != nil {
|
|
span.RecordError(res.Error)
|
|
return 0, res.Error
|
|
}
|
|
return res.RowsAffected, nil
|
|
}
|