You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
3.8 KiB
Go

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
}