bravo-送礼

This commit is contained in:
khalil
2025-03-20 19:14:42 +08:00
parent 44507b6e4e
commit a72920cab8
37 changed files with 1560 additions and 48 deletions

View File

@@ -585,7 +585,10 @@ public class Constant {
* 大R定制礼物
*/
public static final byte CUSTOM_GIFT = GiftTypeEnum.CUSTOM.getType();
/**
* Bravo礼物
*/
public static final byte BRAVO_GIFT = GiftTypeEnum.BRAVO.getType();
}
public static class PayloadSkiptype {
@@ -1367,7 +1370,6 @@ public class Constant {
public static final String ROOM_RIGHT_BOTTOM_ICON_CONFIG = "room_right_bottom_icon_config";
public static final String GIFT_EARN_ALLOT_GUILD_CONFIG = "gift_earn_allot_guild_config";
public static final String APP_CAPTCHA_SWITCH = "app_captcha_switch";
/**
* 每月充值活动屏蔽财富等级
*/
@@ -1420,6 +1422,10 @@ public class Constant {
public static final String MINI_GAME_WEEK_JACKPOT_CONFIG = "mini_game_week_jackpot_config";
public static final String SHARE_LINK = "share_link";
public static final String APP_CAPTCHA_SWITCH = "app_captcha_switch";
public static final String BRAVO_GIFT_CONFIG = "bravo_gift_config";
}
public static class WithDrawStatus {

View File

@@ -25,7 +25,8 @@ public enum GiftTypeEnum {
COUNTRY((byte) 17, "国家"),
LUCKY_24((byte) 18, "幸运礼物"),
CP((byte) 19, "cp"),
CUSTOM((byte) 20, "大R定制");
CUSTOM((byte) 20, "大R定制"),
BRAVO((byte) 21, "Bravo");
private byte type;
private String desc;

View File

@@ -1437,6 +1437,16 @@ public enum RedisKey {
email_code,
email_send_interval,
//幸运24
bravo_stock,
bravo_user_meta,
bravo_user_pool,
bravo_user_history,
bravo_user_lock,
bravo_robot_push_msg,
bravo_status, // 礼物消息的状态
lock_bravo_message, // 消费送礼物消息锁
;
public String getKey() {

View File

@@ -0,0 +1,31 @@
package com.accompany.sharding.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@TableName(value = "bravo_record")
@Data
public class BravoRecord {
@TableId(type = IdType.AUTO)
private Long id;
private Integer partitionId;
private Long uid;
private Long receiverUid;
private Long roomUid;
private Integer giftId;
private Long giftGoldPrice;
private Integer giftNum;
private Integer poolId;
private Boolean isSupplement;
private BigDecimal drawMultiple;
private BigDecimal afterMultiple;
private BigDecimal winGoldNum;
private Date createTime;
private String messId;
}

View File

@@ -0,0 +1,57 @@
package com.accompany.sharding.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@AllArgsConstructor
@NoArgsConstructor
@Data
@ApiModel
public class BravoPersonalStat {
@ApiModelProperty("日期")
private String date;
@ApiModelProperty("分区id")
private Integer partitionId;
@ApiModelProperty("uid")
private Long uid;
@ApiModelProperty("erbanNO")
private Long erbanNo;
@ApiModelProperty("送礼金币总额")
private Long totalInput;
@ApiModelProperty("送礼返币总额")
private Long totalOutput;
@ApiModelProperty("相差")
private Long production;
@ApiModelProperty("投产比")
private BigDecimal productionRatio;
@ApiModelProperty("平均投入金额")
private BigDecimal avgInput;
@ApiModelProperty("参与次数")
private Long num;
@ApiModelProperty("中奖人数")
private Long winNum;
@ApiModelProperty("中奖率")
private BigDecimal winRate;
public BravoPersonalStat(String date, Integer partitionId, Long uid, Long erbanNo) {
this.date = date;
this.partitionId = partitionId;
this.uid = uid;
this.erbanNo = erbanNo;
this.totalInput = 0L;
this.totalOutput = 0L;
this.production = 0L;
this.productionRatio = BigDecimal.ZERO;
this.avgInput = BigDecimal.ZERO;
this.num = 0L;
this.winNum = 0L;
this.winRate = BigDecimal.ZERO;
}
}

View File

@@ -0,0 +1,50 @@
package com.accompany.sharding.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@AllArgsConstructor
@NoArgsConstructor
@Data
@ApiModel
public class BravoPlatformStat {
@ApiModelProperty("日期")
private String date;
@ApiModelProperty("分区id")
private Integer partitionId;
@ApiModelProperty("送礼金币总额")
private Long totalInput;
@ApiModelProperty("送礼返币总额")
private Long totalOutput;
@ApiModelProperty("投产比")
private BigDecimal productionRatio;
@ApiModelProperty("参与次数")
private Long num;
@ApiModelProperty("参与人数")
private Long count;
@ApiModelProperty("中奖次数")
private Long winNum;
@ApiModelProperty("中奖人数")
private Long winCount;
@ApiModelProperty("中奖率")
private BigDecimal winRate;
public BravoPlatformStat(String date, Integer partitionId) {
this.date = date;
this.partitionId = partitionId;
this.totalInput = 0L;
this.totalOutput = 0L;
this.productionRatio = BigDecimal.ZERO;
this.num = 0L;
this.count = 0L;
this.winNum = 0L;
this.winCount = 0L;
this.winRate = BigDecimal.ZERO;
}
}

View File

@@ -145,6 +145,9 @@ public class ShardingSphereConfig {
tableConfigs.add(getShardingTableRuleConfiguration("lucky_24_record",
"ds.lucky_24_record_$->{20240914..20250531}",
"create_time", "lucky24RecordStrategy"));
tableConfigs.add(getShardingTableRuleConfiguration("bravo_record",
"ds.bravo_record_$->{20250320..20250531}",
"create_time", "bravoRecordStrategy"));
Map<String, AlgorithmConfiguration> algorithmsConfigs = new HashMap<>();
@@ -178,6 +181,9 @@ public class ShardingSphereConfig {
//
AlgorithmConfiguration lucky24RecordShardingAlgorithm = getLucky24RecordShardingAlgorithmConfiguration();
algorithmsConfigs.put("lucky24RecordStrategy", lucky24RecordShardingAlgorithm);
//
AlgorithmConfiguration bravoRecordShardingAlgorithm = getBravoRecordShardingAlgorithmConfiguration();
algorithmsConfigs.put("bravoRecordStrategy", bravoRecordShardingAlgorithm);
ShardingRuleConfiguration config = new ShardingRuleConfiguration();
config.setTables(tableConfigs);
@@ -186,6 +192,10 @@ public class ShardingSphereConfig {
return config;
}
private AlgorithmConfiguration getBravoRecordShardingAlgorithmConfiguration() {
return getGiftSendRecordShardingAlgorithmConfiguration();
}
private AlgorithmConfiguration getBillRecordShardingAlgorithmConfiguration() {
return getGiftSendRecordShardingAlgorithmConfiguration();
}

View File

@@ -0,0 +1,22 @@
package com.accompany.sharding.mapper;
import com.accompany.sharding.model.BravoRecord;
import com.accompany.sharding.vo.BravoPersonalStat;
import com.accompany.sharding.vo.BravoPlatformStat;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
public interface BravoRecordMapper extends BaseMapper<BravoRecord> {
List<BravoPlatformStat> listPlatform(@Param("partitionId") Integer partitionId, @Param("startTime") Date startTime, @Param("endTime") Date endTime,
@Param("zoneIdHour") long zoneIdHour);
List<BravoPersonalStat> listPersonal(@Param("partitionId") Integer partitionId,
@Param("uid") Long uid,
@Param("startTime") Date startTime, @Param("endTime") Date endTime,
@Param("zoneIdHour") long zoneIdHour);
}

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.accompany.sharding.mapper.BravoRecordMapper">
<select id="listPlatform" resultType="com.accompany.sharding.vo.BravoPlatformStat">
select `date`, partition_id,
sum(`totalInput`) `totalInput`, sum(`totalOutput`) `totalOutput`,
sum(`totalOutput`) / sum(`totalInput`) `productionRatio`,
count(*) `count`, count((IF(`maxOutput` > 0, 1, null))) `winCount`,
sum(`num`) `num`, sum(`winNum`) `winNum`, sum(`winNum`) / sum(`num`) `winRate`
from (
select date(date_add(r.create_time, INTERVAL #{zoneIdHour} HOUR)) `date`,
partition_id,
sum(gift_num * gift_gold_price) `totalInput`,
sum(win_gold_num) `totalOutput`,
count(*) `num`,
count((case when win_gold_num > 0 then 1 end)) `winNum`,
max(win_gold_num) `maxOutput`
from bravo_record r
where r.create_time >= #{startTime} and r.create_time &lt;= #{endTime}
and r.partition_id = #{partitionId}
group by `date`, uid) l
group by `date`
</select>
<select id="listPersonal" resultType="com.accompany.sharding.vo.BravoPersonalStat">
select date(date_add(r.create_time, INTERVAL #{zoneIdHour} HOUR)) `date`, partition_id,
r.uid,
sum(gift_num * gift_gold_price) `totalInput`,
sum(win_gold_num) `totalOutput`,
sum(gift_num * gift_gold_price) - sum(win_gold_num) `production`,
sum(win_gold_num) / sum(gift_num * gift_gold_price) `productionRatio`,
sum(gift_num * gift_gold_price) / count(*) `avgInput`,
count(*) `num`,
count((case when win_gold_num > 0 then r.uid else null end)) `winNum`,
ifnull(count((case when win_gold_num > 0 then r.uid else null end)) / count(*),0) `winRate`
from bravo_record r
where r.create_time >= #{startTime} and r.create_time &lt;= #{endTime}
<if test="null != uid">
and r.uid = #{uid}
</if>
and r.partition_id = #{partitionId}
group by `date`, r.uid
</select>
</mapper>

View File

@@ -0,0 +1,35 @@
package com.accompany.business.constant;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.exception.ServiceException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Optional;
@AllArgsConstructor
@Getter
public enum BravoPoolTypeEnum {
NEW_USER_POOL(1, "新人奖池"),
NORMAL_POOL(2, "普通奖池"),
BLACK_POOL(3, "黑名单奖池"),
;
/**
* value
*/
private int type;
private String name;
public static BravoPoolTypeEnum get(int type) {
Optional<BravoPoolTypeEnum> result = Arrays.stream(BravoPoolTypeEnum.values()).filter(prizePoolTypeEnum ->
prizePoolTypeEnum.type == type).findFirst();
if (result.isPresent()) {
return result.get();
}
throw new ServiceException(BusiStatus.PARAMETERILLEGAL);
}
}

View File

@@ -0,0 +1,43 @@
package com.accompany.business.dto.lucky;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@Data
public class BravoGiftConfig {
//平台抽成比
private BigDecimal platformRatio;
//收礼者收益比
private BigDecimal receiverRatio;
//对比值n
private BigDecimal productionRatio_N;
private Map<Integer, BravoGiftConfig> ratioPartitionMap;
private Integer poolSize = 500;
private Integer newUserPoolCount = 0;
private BigDecimal specialTipMulti;
private BigDecimal allRoomChatToastValue;
private BigDecimal specialFloatMulti;
private BigDecimal specialFloatValue;
private Long warnMulti;
private List<Long> followUidList;
private Map<Long, BigDecimal> whiteUidProductionRatioMap;
private List<Long> blackUidList;
private String diamondIcon;
public BravoGiftConfig getRatioByPartitionId(Integer partitionId){
return ratioPartitionMap.getOrDefault(partitionId, this);
}
}

View File

@@ -0,0 +1,17 @@
package com.accompany.business.dto.lucky;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class BravoResult {
private Integer poolId;
private BigDecimal input;
private BigDecimal output;
private Boolean isSupplement;
}

View File

@@ -0,0 +1,27 @@
package com.accompany.business.message;
import com.accompany.mq.model.BaseMqMessage;
import lombok.Data;
import java.math.BigDecimal;
/**
* 礼物消息
*/
@Data
public class BravoMessage extends BaseMqMessage {
private Integer partitionId;
private Long uid;
private Long receiverUid;
private Long roomUid;
private Integer giftId;
private Long giftGoldPrice;
private Integer giftNum;
private Integer poolId;
private Boolean isSupplement;
private BigDecimal drawMultiple;
private BigDecimal afterMultiple;
private BigDecimal winGoldNum;
private Long createTime;
private String messId;
}

View File

@@ -0,0 +1,44 @@
package com.accompany.business.model.lucky;
import com.accompany.business.mybatis.typehandler.Lucky24PoolItemListTypeHandler;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@ApiModel
@TableName(value = "bravo_pool", autoResultMap = true)
@Data
public class BravoPool {
@TableId(type = IdType.INPUT)
private Integer id;
@ApiModelProperty("类型1=新手2=普通")
private Integer type;
@ApiModelProperty("期望值")
private BigDecimal expect;
@ApiModelProperty("奖率")
private BigDecimal winRate;
@ApiModelProperty("更新时间")
private Date updateTime;
@ApiModelProperty("池子列表")
@TableField(typeHandler = Lucky24PoolItemListTypeHandler.class)
private List<BravoPoolItem> itemList;
@ApiModel
@Data
public static class BravoPoolItem {
@ApiModelProperty("倍率")
private Integer multi;
@ApiModelProperty("数量")
private Integer num;
}
}

View File

@@ -0,0 +1,16 @@
package com.accompany.business.mybatis.typehandler;
import com.accompany.business.model.lucky.BravoPool;
import com.accompany.business.model.lucky.Lucky24Pool;
import com.accompany.core.mybatis.typehandler.ListTypeHandler;
import com.alibaba.fastjson.TypeReference;
import java.util.List;
public class BravoPoolItemListTypeHandler extends ListTypeHandler<BravoPool.BravoPoolItem> {
// 将ListTypeHandler<T>T为任意对象具体为特定的对象String
@Override
protected TypeReference<List<BravoPool.BravoPoolItem>> specificType() {
return new TypeReference<List<BravoPool.BravoPoolItem>>() {};
}
}

View File

@@ -0,0 +1,7 @@
package com.accompany.business.mybatismapper.lucky;
import com.accompany.business.model.lucky.BravoPool;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface BravoPoolMapper extends BaseMapper<BravoPool> {
}

View File

@@ -0,0 +1,23 @@
package com.accompany.business.mybatismapper.lucky;
import com.accompany.sharding.vo.BravoPersonalStat;
import com.accompany.sharding.vo.BravoPlatformStat;
import com.accompany.sharding.vo.Lucky24PersonalStat;
import com.accompany.sharding.vo.Lucky24PlatformStat;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BravoStatMapper {
int savePlatform(@Param("item") BravoPlatformStat item);
int savePersonal(@Param("item") BravoPersonalStat item);
List<BravoPlatformStat> listPlatformStat(@Param("partitionId") Integer partitionId, @Param("startDate") String startDate, @Param("endDate") String endDate);
List<BravoPersonalStat> listPersonalStat(@Param("partitionId") Integer partitionId,
@Param("uid") Long uid,
@Param("startDate") String startDate, @Param("endDate") String endDate);
}

View File

@@ -0,0 +1,169 @@
package com.accompany.business.service.gift;
import com.accompany.business.dto.lucky.BravoGiftConfig;
import com.accompany.business.dto.lucky.BravoResult;
import com.accompany.business.dto.lucky.Lucky24Result;
import com.accompany.business.dto.lucky.SuperLuckyGiftIncomeAllot;
import com.accompany.business.message.BravoMessage;
import com.accompany.business.model.Gift;
import com.accompany.business.service.lucky.*;
import com.accompany.business.service.mq.RocketMQService;
import com.accompany.common.constant.Constant;
import com.accompany.common.redis.RedisKey;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Room;
import com.accompany.core.service.SysConfService;
import com.accompany.core.service.common.JedisService;
import com.accompany.sharding.model.BravoRecord;
import com.accompany.sharding.model.BravoRecord;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class BravoGiftSendService {
@Autowired
private SysConfService sysConfService;
@Autowired
private BravoStockService stockService;
@Autowired
private BravoUserMetaService userMetaService;
@Autowired
private BravoPoolService poolService;
@Autowired
private BravoRecordService recordService;
@Autowired
private BravoIncomeAllotService incomeAllotService;
@Autowired
private BravoSettlementService settlementService;
@Autowired
private Lucky24RobotMsgService robotMsgService;
@Autowired
private RocketMQService rocketMQService;
@Autowired
private JedisService jedisService;
public void draw(long senderUid, Integer partitionId, Room room, List<Long> receiverList,
Gift gift, int everyGiftNum, Date sendGiftTime) {
BigDecimal everyoneGoldNum = BigDecimal.valueOf(everyGiftNum).multiply(BigDecimal.valueOf(gift.getGoldPrice()));
BravoGiftConfig config = getConfig();
BravoGiftConfig partitionConfig = config.getRatioByPartitionId(partitionId);
SuperLuckyGiftIncomeAllot incomeAllot = incomeAllotService.calculate(partitionConfig, gift, everyGiftNum, receiverList);
// 增加库存
BigDecimal afterStock = stockService.addStock(partitionId, incomeAllot.getRemainValue());
log.info("[lucky24] uid {}, partitionId {}, addStockGoldNum {}, afterStock {}",
senderUid, partitionId, incomeAllot.getRemainValue(), afterStock);
Map<Long, BravoRecord> recordMap = draw(config, senderUid, partitionId, gift, everyGiftNum, everyoneGoldNum, receiverList, room, sendGiftTime);
log.info("[lucky24] uid {}, totalWinGoldNum {}", senderUid, JSON.toJSONString(recordMap));
sendMq(recordMap);
}
public Map<Long, BravoRecord> draw(BravoGiftConfig config, Long senderUid, int partitionId,
Gift gift, int everyGiftNum, BigDecimal everyoneGoldNum,
List<Long> receiverList, Room room, Date sendGiftTime) {
return receiverList.parallelStream()
.collect(Collectors.toMap(receiverUid-> receiverUid,
receiverUid-> drawMultiple(config, senderUid, partitionId, gift, everyGiftNum, receiverUid, everyoneGoldNum, room, sendGiftTime)));
}
private void sendMq(Map<Long, BravoRecord> recordMap) {
Map<String, String> caches = new HashMap<>(recordMap.size());
List<BravoMessage> messageList = new ArrayList<>();
DefaultIdentifierGenerator idGenerator = DefaultIdentifierGenerator.getInstance();
for (BravoRecord record: recordMap.values()){
String id = idGenerator.nextUUID(null);
BravoMessage message = new BravoMessage();
message.setMessId(id);
message.setPartitionId(record.getPartitionId());
message.setUid(record.getUid());
message.setReceiverUid(record.getReceiverUid());
message.setRoomUid(record.getRoomUid());
message.setGiftId(record.getGiftId());
message.setGiftGoldPrice(record.getGiftGoldPrice());
message.setGiftNum(record.getGiftNum());
message.setPoolId(record.getPoolId());
message.setIsSupplement(record.getIsSupplement());
message.setDrawMultiple(record.getDrawMultiple());
message.setAfterMultiple(record.getAfterMultiple());
message.setWinGoldNum(record.getWinGoldNum());
message.setCreateTime(record.getCreateTime().getTime());
messageList.add(message);
caches.put(id, JSON.toJSONString(message));
}
jedisService.hwrite(RedisKey.bravo_status.getKey(), caches);
rocketMQService.sendBatchBravoMessage(messageList);
}
public BravoRecord drawMultiple(BravoGiftConfig config, long senderUid, int partitionId,
Gift gift, int giftNum, long receiverUid, BigDecimal everyoneGoldNum, Room room, Date sendGiftTime) {
BravoResult drawResult = poolService.drawMultipleFromPool(config, senderUid, partitionId);
return updateMeta(config, senderUid, partitionId, gift, giftNum, receiverUid, everyoneGoldNum, room, sendGiftTime, drawResult);
}
private BravoRecord updateMeta(BravoGiftConfig config, long senderUid, int partitionId,
Gift gift, int giftNum, long receiverUid, BigDecimal everyoneGoldNum, Room room, Date sendGiftTime,
BravoResult drawResult){
BigDecimal drawMultiple = drawResult.getOutput();
BigDecimal afterMultiple = drawMultiple;
// 平台库存
if (afterMultiple.compareTo(BigDecimal.ZERO) > 0L){
BigDecimal preWinGoldNum = afterMultiple.multiply(everyoneGoldNum);
if (!judgeStock(partitionId, preWinGoldNum, senderUid, receiverUid)){
afterMultiple = BigDecimal.ZERO;
}
}
BigDecimal winGoldNum = afterMultiple.multiply(everyoneGoldNum);
userMetaService.updateUserMeta(senderUid, everyoneGoldNum, winGoldNum);
if (winGoldNum.compareTo(BigDecimal.ZERO) > 0){
settlementService.syncSendReward(config, senderUid, room, gift, winGoldNum, afterMultiple);
}
return recordService.buildRecord(senderUid, partitionId, gift, giftNum, null != room? room.getUid(): null,
receiverUid, drawResult.getPoolId(), false,
drawMultiple, afterMultiple, sendGiftTime);
}
private boolean judgeStock(Integer partitionId, BigDecimal winGoldNum, Long senderUid, Long receiverUid){
BigDecimal afterStock = stockService.subStock(partitionId, winGoldNum);
boolean enough = afterStock.compareTo(BigDecimal.ZERO) >= 0;
if (!enough){
log.info("[lucky24] drawMultiple sender {} receiver {} 产出大于库存 winGoldNum {} afterStock {}",
senderUid, receiverUid, winGoldNum, afterStock);
afterStock = stockService.addStock(partitionId, winGoldNum);
robotMsgService.pushStockNotEnough(partitionId, afterStock);
}
return enough;
}
public BravoGiftConfig getConfig() {
String configStr = sysConfService.getSysConfValueById(Constant.SysConfId.BRAVO_GIFT_CONFIG);
if (!StringUtils.hasText(configStr)) {
throw new ServiceException(BusiStatus.ALREADY_NOTEXISTS_CONFIG);
}
return JSON.parseObject(configStr, BravoGiftConfig.class);
}
}

View File

@@ -0,0 +1,109 @@
package com.accompany.business.service.gift;
import com.accompany.business.dto.lucky.BravoGiftConfig;
import com.accompany.business.dto.lucky.SuperLuckyGiftIncomeAllot;
import com.accompany.business.message.BravoMessage;
import com.accompany.business.model.Gift;
import com.accompany.business.service.lucky.*;
import com.accompany.business.service.room.RoomService;
import com.accompany.common.redis.RedisKey;
import com.accompany.core.model.Room;
import com.accompany.core.service.base.BaseService;
import com.accompany.sharding.model.BravoRecord;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.Date;
@Slf4j
@Service
public class BravoMessageService extends BaseService {
@Autowired
private BravoRecordService recordService;
@Autowired
private BravoIncomeAllotService incomeAllotService;
@Autowired
private SuperLuckyGiftSendService superLuckyGiftSendService;
@Autowired
private Lucky24RobotMsgService robotMsgService;
@Autowired
private BravoGiftSendService sendService;
@Autowired
private RoomService roomService;
@Autowired
private GiftService giftService;
public void handleGiftMessage(BravoMessage giftMessage) {
// 防止消息被重复消费
if (!jedisLockService.isExist(RedisKey.lock_bravo_message.getKey(giftMessage.getMessId()), 30)) {
logger.warn("handleBravoMessage giftMessage had handle, mess: " + giftMessage);
return;
}
if (!jedisService.hexists(RedisKey.bravo_status.getKey(), giftMessage.getMessId())){
logger.warn("handleBravoMessage giftMessage had handle, mess: " + giftMessage);
return;
}
logger.info("【处理Bravo mq】 开始处理 giftMessage: {}", JSON.toJSONString(giftMessage));
Room room = null != giftMessage.getRoomUid()? roomService.getRoomByUid(giftMessage.getRoomUid()): null;
Gift gift = giftService.getGiftById(giftMessage.getGiftId());
Date createTime = new Date(giftMessage.getCreateTime());
BravoRecord record = insertRecord(giftMessage);
log.info("【处理Bravo mq】 record 插入成功 messId:{} recordId:{} record:{}",
giftMessage.getMessId(), record.getId(), JSON.toJSONString(record));
// 收礼者收益
BravoGiftConfig config = sendService.getConfig();
BravoGiftConfig partitionConfig = config.getRatioByPartitionId(giftMessage.getPartitionId());
SuperLuckyGiftIncomeAllot receiverIncomeAllot = incomeAllotService.calculate(partitionConfig, gift, giftMessage.getGiftNum(), Collections.singletonList(record.getReceiverUid()));
superLuckyGiftSendService.syncSettlement(giftMessage.getUid(), gift, giftMessage.getGiftNum(), giftMessage.getGiftNum(), room, receiverIncomeAllot, createTime);
logger.info("【处理Bravo mq】 收礼收益已发放 messId: {} incomeAllot: {}", giftMessage.getMessId(), JSON.toJSONString(receiverIncomeAllot));
// 后面都是异步发消息
// if (record.getAfterMultiple() >= config.getWarnMulti()){
// long totalGoldNum = giftMessage.getGiftNum() * giftMessage.getGiftGoldPrice();
// robotMsgService.pushSuperMulti(record.getUid(), record.getReceiverUid(), record.getAfterMultiple(), totalGoldNum, record.getWinGoldNum(),
// record.getRoomUid());
// }
if (CollectionUtils.isEmpty(config.getFollowUidList()) && config.getFollowUidList().contains(record.getUid())){
robotMsgService.pushFollowUser(record.getUid(), record.getReceiverUid(), record.getRoomUid());
}
// 删除该标识,表示消息已经消费过
jedisService.hdel(RedisKey.bravo_status.getKey(), giftMessage.getMessId());
}
private BravoRecord insertRecord(BravoMessage giftMessage) {
BravoRecord record = new BravoRecord();
record.setMessId(giftMessage.getMessId());
record.setPartitionId(giftMessage.getPartitionId());
record.setUid(giftMessage.getUid());
record.setReceiverUid(giftMessage.getReceiverUid());
record.setRoomUid(giftMessage.getRoomUid());
record.setGiftId(giftMessage.getGiftId());
record.setGiftGoldPrice(giftMessage.getGiftGoldPrice());
record.setGiftNum(giftMessage.getGiftNum());
record.setPoolId(giftMessage.getPoolId());
record.setIsSupplement(giftMessage.getIsSupplement());
record.setDrawMultiple(giftMessage.getDrawMultiple());
record.setAfterMultiple(giftMessage.getAfterMultiple());
record.setWinGoldNum(giftMessage.getWinGoldNum());
record.setCreateTime(new Date(giftMessage.getCreateTime()));
recordService.insertRecord(record);
return record;
}
}

View File

@@ -103,6 +103,8 @@ public class GiftSendService extends BaseService {
private GiftSendConsumeGoldService giftSendConsumeGoldService;
@Autowired
private Lucky24GiftSendService lucky24GiftSendService;
@Autowired
private BravoGiftSendService bravoGiftSendService;
private List<LuckyBagGiftPrizePoolFilter> filters;
@@ -483,7 +485,6 @@ public class GiftSendService extends BaseService {
giftNum, everyGoldNum, totalGiftNum, totalGoldNum,
giftSource, sendType, sendGiftTime);
// 福袋礼物
if (gift.getGiftType() == Constant.GiftType.LUCKY_BAG) {
return sendLuckyBagGift(sendUid, Arrays.asList(recvUids), room, gift, giftNum, giftSource, sendType, usersMap, sendGiftTime, u.getPartitionId(), after);
@@ -493,6 +494,8 @@ public class GiftSendService extends BaseService {
superLuckyGiftSendService.draw(sendUid, u.getPartitionId(), room, Arrays.asList(recvUids), gift, giftNum, sendGiftTime);
} else if (gift.getGiftType() == Constant.GiftType.LUCKY_24) {
lucky24GiftSendService.draw(sendUid, u.getPartitionId(), room, Arrays.asList(recvUids), gift, giftNum, sendGiftTime);
} else if (gift.getGiftType() == Constant.GiftType.BRAVO_GIFT) {
bravoGiftSendService.draw(sendUid, u.getPartitionId(), room, Arrays.asList(recvUids), gift, giftNum, sendGiftTime);
}
Double everyGiftValue = gift.getGiftType() == Constant.GiftType.SUPER_LUCKY ?

View File

@@ -124,7 +124,8 @@ public class GiftTabService implements InitializingBean {
return (userContext, giftVoList) -> giftVoList.stream()
.filter(giftVo -> Constant.GiftType.LUCKY_BAG == giftVo.getGiftType()
|| Constant.GiftType.LUCKY_BAG_LINEAR == giftVo.getGiftType()
|| Constant.GiftType.SUPER_LUCKY == giftVo.getGiftType())
|| Constant.GiftType.SUPER_LUCKY == giftVo.getGiftType()
|| Constant.GiftType.BRAVO_GIFT == giftVo.getGiftType())
.map(giftVo -> {
if (Constant.GiftType.SUPER_LUCKY != giftVo.getGiftType()) {
return giftVo;

View File

@@ -0,0 +1,51 @@
package com.accompany.business.service.lucky;
import com.accompany.business.dto.lucky.BravoGiftConfig;
import com.accompany.business.dto.lucky.SuperLuckyGiftIncomeAllot;
import com.accompany.business.model.Gift;
import com.accompany.core.enumeration.BillObjTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class BravoIncomeAllotService implements LuckyGiftIncomeAllotService {
public SuperLuckyGiftIncomeAllot calculate(BravoGiftConfig config, Gift gift, int giftNum, List<Long> receiverUids) {
BigDecimal giftNumB = BigDecimal.valueOf(giftNum);
BigDecimal totalNum = BigDecimal.valueOf(receiverUids.size()).multiply(giftNumB);
// 单价
BigDecimal giftValue = BigDecimal.valueOf(gift.getGoldPrice());
// 总价
BigDecimal everyTotalValue = giftValue.multiply(giftNumB);
BigDecimal totalValue = giftValue.multiply(totalNum);
// 收礼者收益单价
BigDecimal receiverIncome = everyTotalValue.multiply(config.getReceiverRatio());
BigDecimal receiverTotalIncome = totalValue.multiply(config.getReceiverRatio());
Map<Long, BigDecimal> receiverIncomeMap = new HashMap<>();
for (Long receiver: receiverUids){
receiverIncomeMap.put(receiver, receiverIncome);
}
// 平台抽成
BigDecimal platformGoldNum = totalValue.multiply(config.getPlatformRatio());
// 增加库存
BigDecimal addStockGoldNum = totalValue.subtract(platformGoldNum);
return new SuperLuckyGiftIncomeAllot(totalValue, receiverTotalIncome, receiverIncomeMap, BigDecimal.ZERO, addStockGoldNum);
}
@Override
public void addIncome(Long receiverUid, double income, BillObjTypeEnum billObjTypeEnum, Long senderUid, Long roomUid, Integer giftId, Integer everyGiftNum, Long giftTotalGoldNum, Date sendGiftTime) {
//todo
}
}

View File

@@ -0,0 +1,265 @@
package com.accompany.business.service.lucky;
import com.accompany.business.constant.BravoPoolTypeEnum;
import com.accompany.business.constant.Lucky24PoolTypeEnum;
import com.accompany.business.dto.lucky.BravoGiftConfig;
import com.accompany.business.dto.lucky.Lucky24GiftConfig;
import com.accompany.business.dto.lucky.BravoResult;
import com.accompany.business.model.lucky.BravoPool;
import com.accompany.business.model.lucky.Lucky24Pool;
import com.accompany.business.mybatismapper.lucky.BravoPoolMapper;
import com.accompany.business.mybatismapper.lucky.Lucky24PoolMapper;
import com.accompany.common.redis.RedisKey;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.common.utils.RandomUtil;
import com.accompany.core.enumeration.PartitionEnum;
import com.accompany.core.exception.ServiceException;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@Service
public class BravoPoolService {
@Autowired
private RedissonClient redissonClient;
@Autowired
private Lucky24UserMetaService userMetaService;
@Autowired
private BravoPoolMapper bravoPoolMapper;
public BravoResult drawMultipleFromPool(BravoGiftConfig config, Long uid, int partitionId){
RQueue<BravoResult> userPool = getUserPool(uid);
for (int i = 0; i < 3; i++) {
BravoResult result = userPool.poll();
if (null != result) {
userPool.expireAsync(Duration.of(14, ChronoUnit.DAYS));
return result;
}
genPool(config, uid, partitionId, userPool);
}
throw new ServiceException(BusiStatus.SERVERBUSY);
}
private void genPool(BravoGiftConfig config, Long uid, int partitionId, RQueue<BravoResult> userPool) {
boolean locked = false;
RLock lock = redissonClient.getLock(RedisKey.bravo_user_lock.getKey(uid.toString()));
try {
locked = lock.tryLock(5,3, TimeUnit.SECONDS);
if (!userPool.isEmpty()){
log.info("[bravo] genPool uid {} 已生成pool无需再生成", uid);
return;
}
if (!locked) {
throw new ServiceException(BusiStatus.SERVERBUSY);
}
BravoPoolTypeEnum poolType = selectPoolType(config, uid);
List<BravoPool> poolList = bravoPoolMapper.selectList(Wrappers.<BravoPool>lambdaQuery()
.eq(BravoPool::getType, poolType.getType()));
if (CollectionUtils.isEmpty(poolList)){
throw new ServiceException(BusiStatus.SEIZE_TREASURE_POOL_CONFIG_ERROR);
}
BravoGiftConfig partitionConfig = config.getRatioByPartitionId(partitionId);
BravoPool pool = selectPool(config, partitionConfig, uid, poolType, poolList);
buildPool(config, uid, userPool, pool);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
if (locked) {
lock.unlock();
}
}
}
private void buildPool(BravoGiftConfig config, Long uid, RQueue<BravoResult> userPool, BravoPool pool) {
List<BravoPool.BravoPoolItem> poolItemList = pool.getItemList().stream().filter(item->item.getNum()>0).collect(Collectors.toList());
List<Integer> winList = buildWinList(poolItemList);
int[] poolArray = new int[config.getPoolSize()];
for (int i = 0; i < config.getPoolSize(); i++) {
poolArray[i] = 0;
}
if (!winList.isEmpty()){
List<Integer> winIndexList = new ArrayList<>();
int winDistance = config.getPoolSize() / winList.size();
for (int i = 0; i < winList.size(); i++) {
int nextWinIndex = config.getPoolSize() - 1 - i * winDistance;
// 确保索引不会超出超集范围
if (nextWinIndex > 0) {
poolArray[nextWinIndex] = winList.get(i);
winIndexList.add(nextWinIndex);
}
}
log.info("[bravo] genPool buildPool uid {}, winIndexList {}", uid, JSON.toJSONString(winIndexList));
}
List<BravoResult> poolList = Arrays.stream(poolArray).boxed().map(output->{
BravoResult result = new BravoResult();
result.setPoolId(pool.getId());
result.setOutput(BigDecimal.valueOf(output));
return result;
}).collect(Collectors.toList());
userPool.addAll(poolList);
}
private List<Integer> buildWinList(List<BravoPool.BravoPoolItem> poolItemList) {
List<Integer> resultList = new ArrayList<>();
for (BravoPool.BravoPoolItem item : poolItemList) {
int multi = item.getMulti();
int num = item.getNum();
// 使用循环生成 num 个 multi 值,并添加到 resultList 中
for (int i = 0; i < num; i++) {
resultList.add(multi);
}
}
Collections.shuffle(resultList);
return resultList;
}
private BravoPool selectPool(BravoGiftConfig config, BravoGiftConfig partitionConfig,
Long uid,
BravoPoolTypeEnum poolType, List<BravoPool> poolList) {
if (BravoPoolTypeEnum.NEW_USER_POOL.equals(poolType)){
int randomIndex = RandomUtil.randomByRange(0, poolList.size());
BravoPool randomPool = poolList.get(randomIndex);
log.info("[bravo] genPool selectPool type {}, pooList {}, randomIndex {}, expect {}",
poolType, JSON.toJSONString(poolList.stream().map(BravoPool::getExpect).collect(Collectors.toList())), randomIndex, randomPool.getExpect());
return randomPool;
}
// 黑名单
if (!CollectionUtils.isEmpty(config.getBlackUidList())
&& config.getBlackUidList().contains(uid)){
List<BravoPool> balckPoolList = poolList.stream()
.sorted(Comparator.comparing(BravoPool::getExpect))
.limit(1L)
.collect(Collectors.toList());
int randomIndex = RandomUtil.randomByRange(0, balckPoolList.size());
BravoPool randomPool = balckPoolList.get(randomIndex);
log.info("[bravo] genPool selectPool type {}, blackPooList {}, randomIndex {}, expect {}",
poolType, JSON.toJSONString(balckPoolList.stream().map(BravoPool::getExpect).collect(Collectors.toList())), randomIndex, randomPool.getExpect());
return randomPool;
}
BigDecimal thisExpect = calExpect(config, partitionConfig, uid);
List<BravoPool> expectPoolList = BigDecimal.ZERO.compareTo(thisExpect) < 0 ?
poolList.stream().filter(pool->pool.getExpect().compareTo(thisExpect) > 0).collect(Collectors.toList()):
poolList.stream().filter(pool->thisExpect.negate().compareTo(pool.getExpect()) >= 0).collect(Collectors.toList());
int randomIndex = RandomUtil.randomByRange(0, expectPoolList.size());
BravoPool randomPool = expectPoolList.get(randomIndex);
log.info("[bravo] genPool selectPool type {}, pooList {}, randomIndex {}, expect {}",
poolType, JSON.toJSONString(expectPoolList.stream().map(BravoPool::getExpect).collect(Collectors.toList())), randomIndex, randomPool.getExpect());
return randomPool;
}
private BigDecimal calExpect(BravoGiftConfig config, BravoGiftConfig partitionConfig, Long uid) {
BigDecimal n = !CollectionUtils.isEmpty(config.getWhiteUidProductionRatioMap()) && config.getWhiteUidProductionRatioMap().containsKey(uid) ?
config.getWhiteUidProductionRatioMap().get(uid): partitionConfig.getProductionRatio_N();
BigDecimal userLast2000ProductionRatio = userMetaService.getUserLast2000ProductionRatio(uid);
if (userLast2000ProductionRatio.compareTo(n) <= 0){
BigDecimal thisExpect = n.add(n).subtract(userLast2000ProductionRatio);
log.info("[bravo] genPool calExpect uid {}, userLast2000ProductionRatio {} 小于等于配置基准 {},修正后期望值 {}",
uid, userLast2000ProductionRatio, n, thisExpect);
return thisExpect;
}
BigDecimal userProductionRatio = userMetaService.getUserProductionRatio(uid);
if (userProductionRatio.compareTo(n) <= 0){
BigDecimal thisExpect = n.add(n).subtract(userProductionRatio);
log.info("[bravo] genPool calExpect uid {}, userTotalProductionRatio {} 小于等于配置基准 {},修正后期望值 {}",
uid, userProductionRatio, n, thisExpect);
return thisExpect;
}
log.info("[bravo] genPool calExpect uid {}, userLast2000ProductionRation {}, userTotalProductionRatio {} 都大于配置基准 {},修正后期望值 {}",
uid, userLast2000ProductionRatio, userProductionRatio, n, n);
return n.negate();
}
private BravoPoolTypeEnum selectPoolType(BravoGiftConfig config, long senderUid) {
if (!CollectionUtils.isEmpty(config.getBlackUidList()) && config.getBlackUidList().contains(senderUid)){
log.info("[bravo] genPool selectPoolType uid {}, 黑名单", senderUid);
return BravoPoolTypeEnum.BLACK_POOL;
}
if (config.getNewUserPoolCount() <= 0){
log.info("[bravo] genPool selectPoolType uid {}, 配置里的newUserPoolCount小于等于0", senderUid);
return BravoPoolTypeEnum.NORMAL_POOL;
}
long userTimes = userMetaService.getTimes(senderUid);
BravoPoolTypeEnum typeEnum = userTimes < (long) config.getPoolSize() * config.getNewUserPoolCount()?
BravoPoolTypeEnum.NEW_USER_POOL:
BravoPoolTypeEnum.NORMAL_POOL;
log.info("[bravo] genPool selectPoolType uid {}, userTimes {}, type {}",
senderUid, userTimes, typeEnum);
return typeEnum;
}
private RDeque<BravoResult> getUserPool(Long uid) {
return redissonClient.getDeque(RedisKey.bravo_user_pool.getKey(uid.toString()));
}
public void updateUserMulti(Long uid) {
RDeque<BravoResult> userPool = getUserPool(uid);
if (userPool.isEmpty()){
log.info("[bravo] updateUserMulti uid {} 未生成pool", uid);
throw new ServiceException(BusiStatus.SERVERBUSY, "用户未生成奖池");
}
boolean locked = false;
RLock lock = redissonClient.getLock(RedisKey.bravo_user_lock.getKey(uid.toString()));
try {
locked = lock.tryLock(5,3, TimeUnit.SECONDS);
if (!locked) {
throw new ServiceException(BusiStatus.SERVERBUSY);
}
if (userPool.isEmpty()){
log.info("[bravo] updateUserMulti uid {} 未生成pool", uid);
throw new ServiceException(BusiStatus.SERVERBUSY, "用户未生成奖池");
}
List<BravoResult> list = userPool.poll(11);
for (int i = list.size() - 1; i >= 0; i--) {
BravoResult result = list.get(i);
if (i >= list.size() - 1) {
result.setIsSupplement(Boolean.TRUE);
result.setOutput(BigDecimal.valueOf(1000));
}
userPool.addFirst(result);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
if (locked) {
lock.unlock();
}
}
}
}

View File

@@ -0,0 +1,126 @@
package com.accompany.business.service.lucky;
import com.accompany.business.model.Gift;
import com.accompany.business.mybatismapper.lucky.BravoStatMapper;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil;
import com.accompany.core.exception.ServiceException;
import com.accompany.sharding.mapper.BravoRecordMapper;
import com.accompany.sharding.model.BravoRecord;
import com.accompany.sharding.vo.BravoPersonalStat;
import com.accompany.sharding.vo.BravoPlatformStat;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@Service
public class BravoRecordService extends ServiceImpl<BravoRecordMapper, BravoRecord> {
@Autowired
private BravoStatMapper statMapper;
@Resource(name = "bizExecutor")
private ThreadPoolExecutor bizExecutor;
public BravoRecord buildRecord(long senderUid, int partitionId, Gift gift, int giftNum, Long roomUid, long receiverUid, Integer poolId,
boolean isSupplement, BigDecimal drawMultiple, BigDecimal afterMultiple, Date sendGiftTime) {
BravoRecord record = new BravoRecord();
record.setUid(senderUid);
record.setPartitionId(partitionId);
record.setReceiverUid(receiverUid);
record.setRoomUid(roomUid);
record.setGiftId(gift.getGiftId());
record.setGiftNum(giftNum);
record.setGiftGoldPrice(gift.getGoldPrice());
record.setPoolId(poolId);
record.setIsSupplement(isSupplement);
record.setDrawMultiple(drawMultiple);
record.setAfterMultiple(afterMultiple);
BigDecimal input = BigDecimal.valueOf(gift.getGoldPrice()).multiply(BigDecimal.valueOf(giftNum));
BigDecimal output = afterMultiple.multiply(input);
record.setWinGoldNum(output);
record.setCreateTime(sendGiftTime);
return record;
}
@Async
public void saveRecord(long senderUid, int partitionId, Gift gift, int giftNum, long receiverUid, int poolId,
boolean isSupplement, BigDecimal drawMultiple, BigDecimal afterMultiple, Date sendGiftTime) {
BravoRecord record = new BravoRecord();
record.setUid(senderUid);
record.setPartitionId(partitionId);
record.setReceiverUid(receiverUid);
record.setGiftId(gift.getGiftId());
record.setGiftNum(giftNum);
record.setGiftGoldPrice(gift.getGoldPrice());
record.setPoolId(poolId);
record.setIsSupplement(isSupplement);
record.setDrawMultiple(drawMultiple);
record.setAfterMultiple(afterMultiple);
BigDecimal input = BigDecimal.valueOf(gift.getGoldPrice()).multiply(BigDecimal.valueOf(giftNum));
BigDecimal output = afterMultiple.multiply(input);
record.setWinGoldNum(output);
record.setCreateTime(sendGiftTime);
insertRecord(record);
}
public void insertRecord(BravoRecord record) {
for (int i = 0; i < 3; i++) {
try {
record.setId(null);
this.baseMapper.insert(record);
return;
} catch (DuplicateKeyException ignore) {
log.error("[insertBravoRecord] 插入送礼记录失败", ignore);
}
}
log.error(String.format("[insertBravoRecord] 插入送礼记录3次都失败 %s", JSON.toJSONString(record)));
throw new ServiceException(BusiStatus.SERVERBUSY);
}
public void statDate(Integer partitionId, Date startTime, Date endTime, long zoneIdHour) {
List<BravoPlatformStat> platformList = this.baseMapper.listPlatform(partitionId, startTime, endTime, zoneIdHour);
log.info("[BravoRecordStat] platform partitionId {} startTime {} endTime {} zoneIdHour {} platformList: {}",
partitionId, DateTimeUtil.convertDate(startTime, DateTimeUtil.DEFAULT_DATETIME_PATTERN),
DateTimeUtil.convertDate(endTime, DateTimeUtil.DEFAULT_DATETIME_PATTERN), zoneIdHour, JSON.toJSONString(platformList));
if (!CollectionUtils.isEmpty(platformList)) {
bizExecutor.execute(() -> {
for (BravoPlatformStat platformStat : platformList) {
statMapper.savePlatform(platformStat);
}
});
}
List<BravoPersonalStat> personalList = this.baseMapper.listPersonal(partitionId, null, startTime, endTime, zoneIdHour);
log.info("[BravoRecordStat] personal partitionId {} startTime {} endTime {} zoneIdHour {} personalList: {}",
partitionId, DateTimeUtil.convertDate(startTime, DateTimeUtil.DEFAULT_DATETIME_PATTERN),
DateTimeUtil.convertDate(endTime, DateTimeUtil.DEFAULT_DATETIME_PATTERN), zoneIdHour, JSON.toJSONString(personalList));
if (!CollectionUtils.isEmpty(personalList)) {
List<List<BravoPersonalStat>> list = Lists.partition(personalList, 20);
for (List<BravoPersonalStat> personalStatList : list) {
bizExecutor.execute(() -> {
for (BravoPersonalStat personalStat : personalStatList) {
statMapper.savePersonal(personalStat);
}
});
}
}
}
}

View File

@@ -0,0 +1,84 @@
package com.accompany.business.service.lucky;
import com.accompany.business.dto.lucky.BravoGiftConfig;
import com.accompany.business.dto.lucky.SuperLuckyGiftIncomeAllot;
import com.accompany.business.model.Gift;
import com.accompany.business.service.gift.SuperLuckyGiftSendService;
import com.accompany.business.service.purse.UserPurseService;
import com.accompany.core.enumeration.BillObjTypeEnum;
import com.accompany.core.model.Room;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
@Slf4j
@Service
public class BravoSettlementService {
@Autowired
private UserPurseService userPurseService;
@Autowired
private SuperLuckyGiftSendService superLuckyGiftSendService;
public void syncSendReward(BravoGiftConfig config, long senderUid, Room room, Gift gift, BigDecimal winGoldNum, BigDecimal afterMultiple){
sendReward(config, senderUid, room, gift, winGoldNum, afterMultiple);
}
@Async
public void sendReward(BravoGiftConfig config, long senderUid, Room room, Gift gift, BigDecimal winGoldNum, BigDecimal afterMultiple){
// 道具奖励
userPurseService.addDiamond(senderUid, winGoldNum.doubleValue(), BillObjTypeEnum.SUPER_LUCKY_GIFT_DIAMOND);
//飘屏
if (null != room){
superLuckyGiftSendService.sendTip(senderUid, room, winGoldNum, afterMultiple,
afterMultiple.compareTo(config.getSpecialTipMulti()) >= 0 ? 2 : 1);
if (winGoldNum.compareTo(config.getAllRoomChatToastValue()) > 0){
superLuckyGiftSendService.sendAllRoomScreen(senderUid, room, gift, winGoldNum);
}
//飘屏
if (winGoldNum.compareTo(config.getSpecialFloatValue()) >= 0
|| afterMultiple.compareTo(config.getSpecialFloatMulti()) >= 0) {
superLuckyGiftSendService.sendFloating(room, senderUid, gift, afterMultiple, winGoldNum);
}
}
}
public void settlement(BravoGiftConfig config, long senderUid, Room room, Gift gift, int everyGiftNum, int totalGiftNum,
Map<Long, Long> winGoldNumMap, SuperLuckyGiftIncomeAllot incomeAllot, Date sendGiftTime) {
//适配SuperLuckyGift的结算modal
/*Map<Long, Map<LuckyGiftReward, Integer>> userDrawResult = winGoldNumMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
entry-> {
long winGoldNum = entry.getValue();
LuckyGiftReward reward = new LuckyGiftReward();
if (winGoldNum > 0) {
reward.setRewardType(LuckyGiftRewardTypeEnum.DIAMOND.ordinal());
reward.setRewardPrice(winGoldNum);
reward.setRewardValue(winGoldNum);
reward.setRewardIcon(config.getDiamondIcon());
} else {
reward.setRewardType(LuckyGiftRewardTypeEnum.NONE.ordinal());
}
return Map.of(reward, 1);
}));*/
/*if (null != room) {
//superLuckyGiftSendService.sendRoomScreen(senderUid, room, gift, everyGiftNum, userDrawResult);
long outputValue = winGoldNumMap.values().stream().mapToLong(Long::longValue).sum();
if (outputValue >= config.getAllRoomChatToastValue()) {
superLuckyGiftSendService.sendAllRoomScreen(senderUid, room, gift, BigDecimal.valueOf(outputValue));
}
}*/
superLuckyGiftSendService.settlement(senderUid, gift, everyGiftNum, totalGiftNum, room, incomeAllot, sendGiftTime);
}
}

View File

@@ -0,0 +1,27 @@
package com.accompany.business.service.lucky;
import com.accompany.common.redis.RedisKey;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class BravoStockService implements StockService {
@Autowired
protected RedissonClient redissonClient;
@Override
public RedissonClient getRedissonClient() {
return redissonClient;
}
@Override
public RedisKey getRedisKey() {
return RedisKey.bravo_stock;
}
}

View File

@@ -0,0 +1,85 @@
package com.accompany.business.service.lucky;
import com.accompany.business.dto.lucky.BravoResult;
import com.accompany.business.dto.lucky.Lucky24Result;
import com.accompany.common.redis.RedisKey;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
@Slf4j
@Service
public class BravoUserMetaService {
private static final String TIMES_KEY = "times";
public static final String INPUT_KEY = "input";
public static final String OUTPUT_KEY = "output";
private static final int HISTORY_QUEUE_SIZE = 2000;
@Autowired
private RedissonClient redissonClient;
public Long getTimes(Long uid) {
return getUserMeta(uid).getOrDefault(TIMES_KEY, 0L).longValue();
}
public BigDecimal getUserLast2000ProductionRatio(Long uid) {
RList<BravoResult> historyQueue = getUserHistoryQueue(uid);
int size = historyQueue.size();
//保留20000条记录
int num = Math.min(size, HISTORY_QUEUE_SIZE);
List<BravoResult> historyResult = historyQueue.range(num);
BigDecimal historyInput = historyResult.stream().limit(num).map(BravoResult::getInput).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal historyOutput = historyResult.stream().limit(num).map(BravoResult::getOutput).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal productionRatio = num > 0 ? historyOutput.divide(historyInput,2, RoundingMode.HALF_UP): BigDecimal.ZERO;
log.info("[bravo] buildPool last2000 uid {}, historyInput {}, historyOutput {}, num {}, productionRatio {}",
uid, historyInput, historyOutput, num, productionRatio);
if (size > HISTORY_QUEUE_SIZE){
historyQueue.trim(0, HISTORY_QUEUE_SIZE);
}
return productionRatio;
}
public BigDecimal getUserProductionRatio(Long uid) {
RMap<String, Number> userMetaMap = getUserMeta(uid);
BigDecimal output = BigDecimal.valueOf(userMetaMap.getOrDefault(OUTPUT_KEY, 0L).longValue());
BigDecimal input = BigDecimal.valueOf(userMetaMap.getOrDefault(INPUT_KEY, 0L).longValue());
BigDecimal productionRatio = BigDecimal.ZERO.equals(output)? BigDecimal.ZERO: output.divide(input,2,RoundingMode.HALF_UP);
log.info("[bravo] buildPool total uid {}, totalOutput {}, totalInput {}, productionRatio {}",
uid, output, input, productionRatio);
return productionRatio;
}
public void updateUserMeta(long senderUid, BigDecimal input, BigDecimal output) {
RList<BravoResult> historyQueue = getUserHistoryQueue(senderUid);
historyQueue.add(0, new BravoResult(null, input, output, null));
historyQueue.expireAsync(Duration.of(14, ChronoUnit.DAYS));
RMap<String, Number> userMetaMap = getUserMeta(senderUid);
long times = userMetaMap.addAndGet(TIMES_KEY, 1L).longValue();
long totalInput = userMetaMap.addAndGet(INPUT_KEY, input).longValue();
long totalOutput = userMetaMap.addAndGet(OUTPUT_KEY, output).longValue();
log.info("[bravo] updateUserMeta uid {} times {} totalInput {} totalOutput {}",
senderUid, times, totalInput, totalOutput);
}
public RMap<String, Number> getUserMeta(Long uid) {
return redissonClient.getMap(RedisKey.bravo_user_meta.getKey(uid.toString()));
}
public RList<BravoResult> getUserHistoryQueue(Long uid) {
return redissonClient.getList(RedisKey.bravo_user_history.getKey(uid.toString()));
}
}

View File

@@ -3,17 +3,19 @@ package com.accompany.business.service.lucky;
import com.accompany.business.dto.lucky.Lucky24GiftConfig;
import com.accompany.business.dto.lucky.SuperLuckyGiftIncomeAllot;
import com.accompany.business.model.Gift;
import com.accompany.core.enumeration.BillObjTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class Lucky24IncomeAllotService extends SuperLuckyIncomeAllotService {
public class Lucky24IncomeAllotService implements LuckyGiftIncomeAllotService {
public SuperLuckyGiftIncomeAllot calculate(Lucky24GiftConfig config, Gift gift, int giftNum, List<Long> receiverUids) {
BigDecimal giftNumB = BigDecimal.valueOf(giftNum);
@@ -41,4 +43,9 @@ public class Lucky24IncomeAllotService extends SuperLuckyIncomeAllotService {
return new SuperLuckyGiftIncomeAllot(totalValue, receiverTotalIncome, receiverIncomeMap, BigDecimal.ZERO, addStockGoldNum);
}
@Override
public void addIncome(Long receiverUid, double income, BillObjTypeEnum billObjTypeEnum, Long senderUid, Long roomUid, Integer giftId, Integer everyGiftNum, Long giftTotalGoldNum, Date sendGiftTime) {
}
}

View File

@@ -11,24 +11,18 @@ import java.math.BigDecimal;
@Slf4j
@Service
public class Lucky24StockService {
public class Lucky24StockService implements StockService {
@Autowired
private RedissonClient redissonClient;
protected RedissonClient redissonClient;
public void setStock(Integer partitionId, BigDecimal value) {
getPartitionStock(partitionId).set(value.doubleValue());
@Override
public RedissonClient getRedissonClient() {
return redissonClient;
}
public BigDecimal addStock(Integer partitionId, BigDecimal value) {
return BigDecimal.valueOf(getPartitionStock(partitionId).addAndGet(value.doubleValue()));
}
public BigDecimal subStock(Integer partitionId, BigDecimal value) {
return BigDecimal.valueOf(getPartitionStock(partitionId).addAndGet(value.negate().doubleValue()));
}
private RAtomicDouble getPartitionStock(Integer partitionId) {
return redissonClient.getAtomicDouble(RedisKey.lucky_24_stock.getKey(partitionId.toString()));
@Override
public RedisKey getRedisKey() {
return RedisKey.lucky_24_stock;
}
}

View File

@@ -0,0 +1,49 @@
package com.accompany.business.service.lucky;
import com.accompany.business.event.ActivityOfDayConsumeEvent;
import com.accompany.business.event.SuperLuckyGiftDiamondIncomeMessageEvent;
import com.accompany.business.message.ActivityOfDayConsumeMessage;
import com.accompany.business.message.SuperLuckyGiftDiamondIncomeMessage;
import com.accompany.business.model.Gift;
import com.accompany.core.base.SpringContextHolder;
import com.accompany.core.enumeration.BillObjTypeEnum;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
public interface LuckyGiftIncomeAllotService {
default void send(long senderUid, Map<Long, BigDecimal> incomeMap, Long roomUid, BillObjTypeEnum billObjTypeEnum,
Gift gift, int everyGiftNum, long everyTotalGoldNum, Date sendGiftTime) {
for (Map.Entry<Long, BigDecimal> entry : incomeMap.entrySet()){
send(senderUid, entry.getKey(), roomUid, entry.getValue(), billObjTypeEnum,
gift.getGiftId(), everyGiftNum, everyTotalGoldNum, sendGiftTime);
}
}
default void send(long senderUid, Long receiverUid, Long roomUid, BigDecimal income, BillObjTypeEnum billObjTypeEnum,
int giftId, int everyGiftNum, long giftTotalGoldNum, Date sendGiftTime) {
addIncome(receiverUid, income.doubleValue(), billObjTypeEnum, senderUid, roomUid, giftId, everyGiftNum, giftTotalGoldNum, sendGiftTime);
SuperLuckyGiftDiamondIncomeMessage diamondIncomeMessage = new SuperLuckyGiftDiamondIncomeMessage(senderUid, receiverUid, roomUid, giftId, everyGiftNum, giftTotalGoldNum, income.doubleValue(), sendGiftTime);
SpringContextHolder.getApplicationContext().publishEvent(new SuperLuckyGiftDiamondIncomeMessageEvent(diamondIncomeMessage));
SpringContextHolder.getApplicationContext().publishEvent(new ActivityOfDayConsumeEvent(ActivityOfDayConsumeMessage.builder()
.sendUid(diamondIncomeMessage.getSenderUid())
.messTime(new Date(diamondIncomeMessage.getCreateTime().getTime()))
.totalDiamondNum(income.doubleValue()).consumeType("lucky gift").build()));
}
/*default void addIncome(Long receiverUid, double income, BillObjTypeEnum billObjTypeEnum,
Long senderUid, Long roomUid, Integer giftId, Integer everyGiftNum, Long giftTotalGoldNum, Date sendGiftTime){
//userPurseService.addGoldWithoutTx(receiverUid, income.doubleValue(), billObjTypeEnum,
userPurseService.addGold(receiverUid, income, billObjTypeEnum,
(userPurse)-> billRecordService.insertGiftSendBillRecord(receiverUid, senderUid, roomUid, null, billObjTypeEnum, income,
giftId, everyGiftNum, giftTotalGoldNum, sendGiftTime, userPurse));
}*/
void addIncome(Long receiverUid, double income, BillObjTypeEnum billObjTypeEnum,
Long senderUid, Long roomUid, Integer giftId, Integer everyGiftNum, Long giftTotalGoldNum, Date sendGiftTime);
}

View File

@@ -0,0 +1,31 @@
package com.accompany.business.service.lucky;
import com.accompany.common.redis.RedisKey;
import org.redisson.api.RAtomicDouble;
import org.redisson.api.RedissonClient;
import java.math.BigDecimal;
public interface StockService {
RedissonClient getRedissonClient();
RedisKey getRedisKey();
default void setStock(Integer partitionId, BigDecimal value) {
getPartitionStock(partitionId).set(value.doubleValue());
}
default BigDecimal addStock(Integer partitionId, BigDecimal value) {
return BigDecimal.valueOf(getPartitionStock(partitionId).addAndGet(value.doubleValue()));
}
default BigDecimal subStock(Integer partitionId, BigDecimal value) {
return BigDecimal.valueOf(getPartitionStock(partitionId).addAndGet(value.negate().doubleValue()));
}
default RAtomicDouble getPartitionStock(Integer partitionId) {
return getRedissonClient().getAtomicDouble(getRedisKey().getKey(partitionId.toString()));
}
}

View File

@@ -2,10 +2,6 @@ package com.accompany.business.service.lucky;
import com.accompany.business.dto.lucky.SuperLuckyGiftConfig;
import com.accompany.business.dto.lucky.SuperLuckyGiftIncomeAllot;
import com.accompany.business.event.ActivityOfDayConsumeEvent;
import com.accompany.business.event.SuperLuckyGiftDiamondIncomeMessageEvent;
import com.accompany.business.message.ActivityOfDayConsumeMessage;
import com.accompany.business.message.SuperLuckyGiftDiamondIncomeMessage;
import com.accompany.business.model.Gift;
import com.accompany.business.service.purse.UserPurseService;
import com.accompany.business.service.record.BillRecordService;
@@ -13,7 +9,6 @@ import com.accompany.core.enumeration.BillObjTypeEnum;
import com.accompany.core.model.Room;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@@ -24,14 +19,12 @@ import java.util.Map;
@Slf4j
@Service
public class SuperLuckyIncomeAllotService {
public class SuperLuckyIncomeAllotService implements LuckyGiftIncomeAllotService {
@Autowired
private UserPurseService userPurseService;
@Autowired
private BillRecordService billRecordService;
@Autowired
private ApplicationContext applicationContext;
public SuperLuckyGiftIncomeAllot calculate(SuperLuckyGiftConfig config, Gift gift, int giftNum, List<Long> receiverUids, Room room) {
BigDecimal giftNumB = BigDecimal.valueOf(giftNum);
@@ -59,27 +52,11 @@ public class SuperLuckyIncomeAllotService {
return new SuperLuckyGiftIncomeAllot(totalValue, receiverTotalIncome, receiverIncomeMap, roomOwnerTotalIncome, remainValue);
}
public void send(long senderUid, Map<Long, BigDecimal> incomeMap, Long roomUid, BillObjTypeEnum billObjTypeEnum,
Gift gift, int everyGiftNum, long everyTotalGoldNum, Date sendGiftTime) {
for (Map.Entry<Long, BigDecimal> entry : incomeMap.entrySet()){
send(senderUid, entry.getKey(), roomUid, entry.getValue(), billObjTypeEnum,
gift.getGiftId(), everyGiftNum, everyTotalGoldNum, sendGiftTime);
}
}
public void send(long senderUid, Long receiverUid, Long roomUid, BigDecimal income, BillObjTypeEnum billObjTypeEnum,
int giftId, int everyGiftNum, long giftTotalGoldNum, Date sendGiftTime) {
@Override
public void addIncome(Long receiverUid, double income, BillObjTypeEnum billObjTypeEnum, Long senderUid, Long roomUid, Integer giftId, Integer everyGiftNum, Long giftTotalGoldNum, Date sendGiftTime) {
//userPurseService.addGoldWithoutTx(receiverUid, income.doubleValue(), billObjTypeEnum,
userPurseService.addGold(receiverUid, income.doubleValue(), billObjTypeEnum,
(userPurse)-> billRecordService.insertGiftSendBillRecord(receiverUid, senderUid, roomUid, null, billObjTypeEnum, income.doubleValue(),
userPurseService.addGold(receiverUid, income, billObjTypeEnum,
(userPurse)-> billRecordService.insertGiftSendBillRecord(receiverUid, senderUid, roomUid, null, billObjTypeEnum, income,
giftId, everyGiftNum, giftTotalGoldNum, sendGiftTime, userPurse));
SuperLuckyGiftDiamondIncomeMessage diamondIncomeMessage = new SuperLuckyGiftDiamondIncomeMessage(senderUid, receiverUid, roomUid, giftId, everyGiftNum, giftTotalGoldNum, income.doubleValue(), sendGiftTime);
applicationContext.publishEvent(new SuperLuckyGiftDiamondIncomeMessageEvent(diamondIncomeMessage));
applicationContext.publishEvent(new ActivityOfDayConsumeEvent(ActivityOfDayConsumeMessage.builder()
.sendUid(diamondIncomeMessage.getSenderUid())
.messTime(new Date(diamondIncomeMessage.getCreateTime().getTime()))
.totalDiamondNum(income.doubleValue()).consumeType("lucky gift").build()));
}
}

View File

@@ -73,6 +73,18 @@ public class RocketMQService {
}
}
public void sendBatchBravoMessage(List<BravoMessage> bravoMessages) {
List<Message<String>> messageList = bravoMessages.stream()
.map(giftMessage -> MessageBuilder.withPayload(JSON.toJSONString(giftMessage)).build())
.collect(Collectors.toList());
SendResult sendResult = rocketMQTemplate.syncSend(MqConstant.BRAVO_TOPIC, messageList);
if (SendStatus.SEND_OK.equals(sendResult.getSendStatus())){
log.info("sendLucky24Message success result: {} message: {}", JSON.toJSONString(sendResult), messageList);
} else {
log.error("sendLucky24Message fail result: {} message: {}", JSON.toJSONString(sendResult), messageList);
}
}
/**
* 发送开箱子中奖消息
*/
@@ -120,4 +132,5 @@ public class RocketMQService {
log.error("sendYidunIMTextAntiMsg fail message: {}", JSON.toJSONString(msg), throwable);
});
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.accompany.business.mybatismapper.lucky.BravoPoolMapper">
</mapper>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.accompany.business.mybatismapper.lucky.BravoStatMapper">
<insert id="savePlatform">
insert into bravo_record_platform_stat
VALUES (#{item.date}, #{item.partitionId}, #{item.totalInput}, #{item.totalOutput}, #{item.productionRatio},
#{item.num}, #{item.count}, #{item.winNum}, #{item.winCount}, #{item.winRate})
ON DUPLICATE KEY UPDATE total_input = #{item.totalInput}, total_output = #{item.totalOutput}, production_ratio = #{item.productionRatio},
num = #{item.num}, `count` = #{item.count}, win_num = #{item.winNum}, win_count = #{item.winCount}, win_rate = #{item.winRate};
</insert>
<insert id="savePersonal">
insert into bravo_record_personal_stat
VALUES (#{item.date}, #{item.partitionId}, #{item.uid}, #{item.totalInput}, #{item.totalOutput},
#{item.production}, #{item.productionRatio}, #{item.avgInput},
#{item.num}, #{item.winNum}, #{item.winRate})
ON DUPLICATE KEY UPDATE total_input = #{item.totalInput}, total_output = #{item.totalOutput},
production = #{item.production}, production_ratio = #{item.productionRatio}, avg_input = #{item.avgInput},
num = #{item.num}, win_num = #{item.winNum}, win_rate = #{item.winRate};
</insert>
<select id="listPlatformStat" resultType="com.accompany.sharding.vo.Lucky24PlatformStat">
select * from bravo_record_platform_stat s
where s.date between #{startDate} and #{endDate}
and s.partition_id = #{partitionId}
</select>
<select id="listPersonalStat" resultType="com.accompany.sharding.vo.Lucky24PersonalStat">
select * from bravo_record_personal_stat s
where s.date between #{startDate} and #{endDate}
and s.partition_id = #{partitionId}
<if test="null != uid">
and s.uid = #{uid}
</if>
</select>
</mapper>

View File

@@ -38,4 +38,7 @@ public interface MqConstant {
String BILL_RECORD_TOPIC = "bill_record_topic";
String BILL_RECORD_CONSUME_GROUP = "bill_record_consume_group";
String BRAVO_TOPIC = "bravo_topic";
String BRAVO_CONSUME_GROUP = "bravo_consume_group";
}

View File

@@ -0,0 +1,30 @@
package com.accompany.mq.consumer;
import com.accompany.business.message.BravoMessage;
import com.accompany.business.message.Lucky24Message;
import com.accompany.business.service.gift.BravoMessageService;
import com.accompany.business.service.gift.Lucky24MessageService;
import com.accompany.mq.constant.MqConstant;
import com.accompany.mq.listener.AbstractMessageListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@ConditionalOnProperty(name = "spring.application.name", havingValue = "web")
@RocketMQMessageListener(topic = MqConstant.BRAVO_TOPIC, consumerGroup = MqConstant.BRAVO_CONSUME_GROUP)
public class BravoMessageConsumer extends AbstractMessageListener<BravoMessage> {
@Autowired
private BravoMessageService bravoMessageService;
@Override
public void onMessage(BravoMessage giftMessage) {
log.info("onMessage bravoMessage: {}", giftMessage.toString());
bravoMessageService.handleGiftMessage(giftMessage);
}
}