diff --git a/internal/service/agent/agent_service.go b/internal/service/agent/agent_service.go index bdf10e9..7f862c0 100644 --- a/internal/service/agent/agent_service.go +++ b/internal/service/agent/agent_service.go @@ -185,11 +185,11 @@ func (s *AgentServiceV1) AgentPutInfoReq(ctx context.Context, req *v1.AgentPutIn oldBalance = utils.RevertBalance(user.Balance, user.Edges.Agent.Rate) tx.SysAgent.UpdateOne(user.Edges.Agent).SetLevel(req.Level).SetRate(req.Rate).SaveX(ctx) } + err = tx.Commit() //按照新费率计算余额 newBalance := utils.TransformBalance(oldBalance, req.Rate) // 6. 更新用户余额 balance.BalanceService.ChangeUserBalance(ctx, user.ID, newBalance.Sub(oldBalance)) - err = tx.Commit() utils.OkOrPanic(err, func(err error) error { return oops. WithContext(ctx). diff --git a/internal/service/balance/balance_service.go b/internal/service/balance/balance_service.go index d953d8c..89ae160 100644 --- a/internal/service/balance/balance_service.go +++ b/internal/service/balance/balance_service.go @@ -4,33 +4,38 @@ import ( "context" "likedream-goframe/internal/common/errors" "likedream-goframe/internal/db" + "likedream-goframe/internal/ent" "likedream-goframe/internal/ent/sysuser" "likedream-goframe/internal/utils" - "sync" - "github.com/samber/oops" "github.com/shopspring/decimal" ) -var BalanceService = &BalanceServiceV1{ - lock: sync.Mutex{}, -} +var BalanceService = &BalanceServiceV1{} type BalanceServiceV1 struct { - lock sync.Mutex } -func (v *BalanceServiceV1) ChangeUserBalance(ctx context.Context, userId int64, balance decimal.Decimal) { - v.lock.Lock() - defer v.lock.Unlock() - tx, err := db.Global.Tx(ctx) - utils.OkOrPanic(err, oops.WithContext(ctx).Wrap) - defer tx.Rollback() - user := tx.SysUser.Query().Where(sysuser.ID(userId)).WithRoles().OnlyX(ctx) - newBalance := user.Balance.Add(balance) - if newBalance.LessThan(decimal.Zero) { - utils.OkOrPanic(errors.NewBusinessError(400, "余额不足")) - } - tx.SysUser.Update().Where(sysuser.ID(userId)).SetBalance(newBalance).SaveX(ctx) - tx.Commit() +func (v *BalanceServiceV1) ChangeUserBalance(ctx context.Context, userId int64, balance decimal.Decimal) error { + return db.WithTx(ctx, func(c context.Context, tx *ent.Tx) { + // 使用 SELECT ... FOR UPDATE 锁定用户记录 + user, err := tx.SysUser.Query(). + Where(sysuser.ID(userId)). + ForUpdate(). + Only(ctx) + if err != nil { + utils.OkOrPanic(err) + } + + newBalance := user.Balance.Add(balance) + if newBalance.LessThan(decimal.Zero) { + utils.OkOrPanic(errors.NewBusinessError(400, "余额不足")) + } + + // 更新余额 + tx.SysUser.Update(). + Where(sysuser.ID(userId)). + SetBalance(newBalance). + ExecX(ctx) + }, nil) }