package coin_manager import ( "context" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" pbMq "live-service/app/pb/mq" pbVars "live-service/app/pb/vars" "live-service/app/user_center/model" "live-service/app/user_center/rpc/internal/mq" "live-service/app/user_center/rpc/pb" "live-service/common/nerr" ) type ( Manager struct { userCoinModel model.UserCoinModel userMq *mq.UserMq logx.Logger } ChangeCoinReq struct { BattleId int64 // 战局ID UserId int64 // 用户ID Change int64 // 变化量(负数为减扣) } ChangeCoinResp struct { BattleId int64 // 战局ID UserId int64 // 用户ID Change int64 // 变化量(负数为减扣) Current int64 // 当前量 } ) func NewCoinManager(mod model.UserCoinModel, userMq *mq.UserMq) *Manager { return &Manager{ userCoinModel: mod, userMq: userMq, Logger: logx.WithContext(context.Background()), } } func (m *Manager) GetUserCoin(ctx context.Context, userId int64) (int64, error) { resp, err := m.userCoinModel.FindOne(ctx, nil, userId) if err != nil { return 0, err } return resp.Coin, err } func (m *Manager) TransferCoin(ctx context.Context, req *pb.TransferUserCoinReq) (*pb.TransferUserCoinResp, error) { if req.Transfer < 0 { req.Transfer = -req.Transfer } resp := &pb.TransferUserCoinResp{ UserId: req.UserId, TargetUserId: req.TargetUserId, } if err := m.userCoinModel.TransactCtx(ctx, nil, func(tx *gorm.DB) error { if req.UserId == 0 { return nerr.NewError(nerr.RequestParamError, "源用户ID为空") } if req.TargetUserId == 0 { return nerr.NewError(nerr.RequestParamError, "目标用户ID为空") } coin, err := m.userCoinModel.ChangeCoin(ctx, tx, req.UserId, -req.Transfer, false) if err != nil { return nerr.NewWithErr(err) } targetCoin, err := m.userCoinModel.ChangeCoin(ctx, tx, req.TargetUserId, req.Transfer, false) if err != nil { return nerr.NewWithErr(err) } resp.UserCoin = coin resp.TargetUserCoin = targetCoin // 通知 go func() { m.userMq.NotifyUserCoinChanged(&pbMq.MqUserCoinChanged{ UserId: req.UserId, Change: -req.Transfer, Current: coin, Reason: pbVars.UserCoinChangedReason_Transfer, }) m.userMq.NotifyUserCoinChanged(&pbMq.MqUserCoinChanged{ UserId: req.TargetUserId, Change: req.Transfer, Current: targetCoin, Reason: pbVars.UserCoinChangedReason_Transfer, }) }() return nil }); err != nil { return nil, err } return resp, nil } func (m *Manager) ChangeCoin(ctx context.Context, tx *gorm.DB, req *ChangeCoinReq, reason pbVars.UserCoinChangedReason) (*ChangeCoinResp, error) { coin, err := m.userCoinModel.ChangeCoin(ctx, tx, req.UserId, req.Change, false) if err != nil { return nil, err } // 通知 go m.userMq.NotifyUserCoinChanged(&pbMq.MqUserCoinChanged{ UserId: req.UserId, Change: req.Change, Current: coin, Reason: reason, }) return &ChangeCoinResp{ UserId: req.UserId, Change: req.Change, Current: coin, }, nil } func (m *Manager) ChangeCoinBatch(ctx context.Context, req []ChangeCoinReq, reason pbVars.UserCoinChangedReason) (map[int64]ChangeCoinResp, error) { resp := make(map[int64]ChangeCoinResp) if err := m.userCoinModel.TransactCtx(ctx, nil, func(tx *gorm.DB) error { for _, item := range req { coin, err := m.userCoinModel.ChangeCoin(ctx, tx, item.UserId, item.Change, false) if err != nil { return err } resp[item.UserId] = ChangeCoinResp{ BattleId: item.BattleId, UserId: item.UserId, Change: item.Change, Current: coin, } } return nil }); err != nil { return resp, err } go func() { for _, coinResp := range resp { m.userMq.NotifyUserCoinChanged(&pbMq.MqUserCoinChanged{ UserId: coinResp.UserId, Change: coinResp.Change, Current: coinResp.Current, Reason: reason, }) } }() return resp, nil }