diff --git a/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java b/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java index 73258e983..80df40a20 100644 --- a/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java +++ b/accompany-admin/accompany-admin-web/src/main/java/com/accompany/admin/controller/api/MyApiController.java @@ -1,7 +1,9 @@ package com.accompany.admin.controller.api; +import cn.hutool.core.date.DateUtil; import com.accompany.admin.service.api.MyApiService; import com.accompany.business.service.activity.h5.ActivityUserLevelExpService; +import com.accompany.business.service.room.RoomHourDiamondNumService; import com.accompany.business.service.room.RoomService; import com.accompany.business.vo.RoomVo; import com.accompany.common.netease.neteaseacc.result.RoomMemberRet; @@ -308,6 +310,15 @@ public class MyApiController { return BusiResult.success(); } + @Autowired + private RoomHourDiamondNumService roomHourDiamondNumService; + + @GetMapping("/refreshRoomHourDiamondNum") + public BusiResult refreshRoomHourDiamondNum(String date, Integer partitionId) { + roomHourDiamondNumService.taskInsertData(DateUtil.parseDateTime(date), partitionId); + return BusiResult.success(); + } + @Autowired private GoogleTokenVerifier googleTokenVerifier; diff --git a/accompany-base/accompany-sharding/accompany-sharding-sdk/src/main/java/com/accompany/sharding/model/RoomHourDiamondNum.java b/accompany-base/accompany-sharding/accompany-sharding-sdk/src/main/java/com/accompany/sharding/model/RoomHourDiamondNum.java new file mode 100644 index 000000000..452163cca --- /dev/null +++ b/accompany-base/accompany-sharding/accompany-sharding-sdk/src/main/java/com/accompany/sharding/model/RoomHourDiamondNum.java @@ -0,0 +1,51 @@ +package com.accompany.sharding.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 房间小时流水数据实体类 + * + * @author + * @since 2025-07-09 + */ +@Data +public class RoomHourDiamondNum implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id" , type = IdType.AUTO) + private Long id; + /** + * 分区id + */ + private Integer partitionId; + /** + * 房间room_uid + */ + private Long roomUid; + /** + * 流水日期yyyy-MM-dd HH:00:00 + */ + private Date statDate; + /** + * 总送礼值 + */ + private BigDecimal diamondNum; + /** + * 金币流水 + */ + private BigDecimal goldNum; + /** + * 创建时间 + */ + private Date createTime; + private Date updateTime; + + +} diff --git a/accompany-base/accompany-sharding/accompany-sharding-service/src/main/java/com/accompany/sharding/config/ShardingSphereConfig.java b/accompany-base/accompany-sharding/accompany-sharding-service/src/main/java/com/accompany/sharding/config/ShardingSphereConfig.java index 1cbdd7f94..4f23b33c9 100644 --- a/accompany-base/accompany-sharding/accompany-sharding-service/src/main/java/com/accompany/sharding/config/ShardingSphereConfig.java +++ b/accompany-base/accompany-sharding/accompany-sharding-service/src/main/java/com/accompany/sharding/config/ShardingSphereConfig.java @@ -151,6 +151,11 @@ public class ShardingSphereConfig { "create_time", "joyGameStrategy")); + tableConfigs.add(getShardingTableRuleConfiguration("room_hour_diamond_num", + "ds.room_hour_diamond_num_${2025..2026}${['01','02','03', '04','05','06', '07','08','09', '10','11','12']}", + "stat_date", "roomHourStrategy")); + + Map algorithmsConfigs = new HashMap<>(); // 账单按天分表 AlgorithmConfiguration billRecordShardingAlgorithm = getBillRecordShardingAlgorithmConfiguration(); @@ -189,9 +194,13 @@ public class ShardingSphereConfig { AlgorithmConfiguration lucky25RecordShardingAlgorithm = getLucky25RecordShardingAlgorithmConfiguration(); algorithmsConfigs.put("lucky25RecordStrategy", lucky25RecordShardingAlgorithm); //游戏日志 - AlgorithmConfiguration joyGameShardingAlgorithm = getGameGoldLogShardingAlgorithmConfiguration(); + AlgorithmConfiguration joyGameShardingAlgorithm = getjoyGameShardingAlgorithmConfiguration(); algorithmsConfigs.put("joyGameStrategy", joyGameShardingAlgorithm); + //房间小时流水数据 + AlgorithmConfiguration roomHourShardingAlgorithm = getRoomHourDiamondShardingAlgorithmConfiguration(); + algorithmsConfigs.put("roomHourStrategy", roomHourShardingAlgorithm); + ShardingRuleConfiguration config = new ShardingRuleConfiguration(); config.setTables(tableConfigs); config.setAutoTables(autoTableConfigs); @@ -266,6 +275,11 @@ public class ShardingSphereConfig { return tableRuleConfiguration; } + private AlgorithmConfiguration getRoomHourDiamondShardingAlgorithmConfiguration() { + AlgorithmConfiguration algorithmConfiguration = getMonthShardingAlgorithmConfiguration(); + return algorithmConfiguration; + } + /** * =====账单表分表策略===== **/ diff --git a/accompany-base/accompany-sharding/accompany-sharding-service/src/main/java/com/accompany/sharding/mapper/RoomHourDiamondNumMapper.java b/accompany-base/accompany-sharding/accompany-sharding-service/src/main/java/com/accompany/sharding/mapper/RoomHourDiamondNumMapper.java new file mode 100644 index 000000000..9edd39b3b --- /dev/null +++ b/accompany-base/accompany-sharding/accompany-sharding-service/src/main/java/com/accompany/sharding/mapper/RoomHourDiamondNumMapper.java @@ -0,0 +1,14 @@ +package com.accompany.sharding.mapper; + +import com.accompany.sharding.model.RoomHourDiamondNum; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 房间小时流水数据 Mapper 接口 + * + * @author + * @since 2025-07-09 + */ +public interface RoomHourDiamondNumMapper extends BaseMapper { + +} diff --git a/accompany-base/accompany-sharding/accompany-sharding-service/src/main/resources/sharding/sqlmappers/RoomHourDiamondNumMapper.xml b/accompany-base/accompany-sharding/accompany-sharding-service/src/main/resources/sharding/sqlmappers/RoomHourDiamondNumMapper.xml new file mode 100644 index 000000000..c1cd0e098 --- /dev/null +++ b/accompany-base/accompany-sharding/accompany-sharding-service/src/main/resources/sharding/sqlmappers/RoomHourDiamondNumMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/accompany-business/accompany-business-sdk/src/main/java/com/accompany/business/constant/RoomConstant.java b/accompany-business/accompany-business-sdk/src/main/java/com/accompany/business/constant/RoomConstant.java index dbb908520..f88eb1cfe 100644 --- a/accompany-business/accompany-business-sdk/src/main/java/com/accompany/business/constant/RoomConstant.java +++ b/accompany-business/accompany-business-sdk/src/main/java/com/accompany/business/constant/RoomConstant.java @@ -14,6 +14,9 @@ public interface RoomConstant { room_manage_user,//用户管理房间列表 + room_hour_diamond_num,//仅用与统计数据,统计完删除 + + room_hour_gold_num,//仅用与统计数据,统计完删除 ; @Override diff --git a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/BravoGiftGoldIncomeListener.java b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/BravoGiftGoldIncomeListener.java index e41233b81..cf1c2c2cd 100644 --- a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/BravoGiftGoldIncomeListener.java +++ b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/BravoGiftGoldIncomeListener.java @@ -7,7 +7,6 @@ import com.accompany.business.service.rank.RankService; import com.accompany.business.service.room.*; import com.accompany.business.service.user.UsersService; import com.accompany.common.constant.Constant; -import com.accompany.core.enumeration.PartitionEnum; import com.accompany.core.model.Room; import com.accompany.core.model.Users; import com.alibaba.fastjson.JSONObject; @@ -65,9 +64,7 @@ public class BravoGiftGoldIncomeListener implements ApplicationListener { jsonObject.put("serialValue", RoomServiceFactory.getServiceByType(room.getType()).roomSerialValue(roomUid, partitionId)); sendSysMsgService.sendSingleRoomMessage(room.getRoomId(), String.valueOf(room.getUid()), Constant.DefMsgType.RANK, Constant.DefMsgType.RANK_UPDATE, jsonObject); } - if (PartitionEnum.ENGLISH2.getId() == partitionId || PartitionEnum.TURKEY.getId() == partitionId) { - roomDayDiamondNumService.addDiamondNum(partitionId, roomUid, date, giftMessage.getDiamondNum(), giftGoldNum.doubleValue()); - } + roomDayDiamondNumService.addDiamondNum(partitionId, roomUid, date, giftMessage.getDiamondNum(), giftGoldNum.doubleValue()); } catch (Exception e) { log.info("RankListener.updateAllRank-updateRoomRank:{}, e:{}", JSONObject.toJSONString(giftMessage), e.getMessage(), e); } diff --git a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/SuperLuckyGiftSendListener.java b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/SuperLuckyGiftSendListener.java index 4a07d4170..999fb6baf 100644 --- a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/SuperLuckyGiftSendListener.java +++ b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/event/listener/SuperLuckyGiftSendListener.java @@ -7,7 +7,6 @@ import com.accompany.business.service.rank.RankService; import com.accompany.business.service.room.*; import com.accompany.business.service.user.UsersService; import com.accompany.common.constant.Constant; -import com.accompany.core.enumeration.PartitionEnum; import com.accompany.core.model.Room; import com.accompany.core.model.Users; import com.alibaba.fastjson.JSONObject; @@ -17,7 +16,6 @@ import org.springframework.context.ApplicationListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import java.math.BigDecimal; import java.util.Date; @Slf4j @@ -69,9 +67,7 @@ public class SuperLuckyGiftSendListener implements ApplicationListener { + + void taskInsertData(Date statDate, Integer partitionId); + + /** + * 统计时间统一为东八区时间 + * @param partitionId + * @param roomUid + * @param statDate + * @param diamondNum + * @param goldNum + */ + void addRoomHourDiamondNumMap(Integer partitionId, Long roomUid, Date statDate, Double diamondNum, Double goldNum); + + RMap getRoomHourDiamondNumMap(Integer partitionId, String hourStr); + + RMap getRoomHourGoldNumMap(Integer partitionId, String hourStr); +} diff --git a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/room/impl/RoomDayDiamondNumServiceImpl.java b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/room/impl/RoomDayDiamondNumServiceImpl.java index 631c68826..6df1f1462 100644 --- a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/room/impl/RoomDayDiamondNumServiceImpl.java +++ b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/room/impl/RoomDayDiamondNumServiceImpl.java @@ -3,9 +3,11 @@ package com.accompany.business.service.room.impl; import com.accompany.business.model.room.RoomDayDiamondNum; import com.accompany.business.mybatismapper.room.RoomDayDiamondNumMapper; import com.accompany.business.service.room.RoomDayDiamondNumService; +import com.accompany.business.service.room.RoomHourDiamondNumService; import com.accompany.common.utils.DateTimeUtil; import com.accompany.core.enumeration.PartitionEnum; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; @@ -21,9 +23,18 @@ import java.util.Date; @Service public class RoomDayDiamondNumServiceImpl extends ServiceImpl implements RoomDayDiamondNumService { + @Autowired + private RoomHourDiamondNumService roomHourDiamondNumService; @Override public Integer addDiamondNum(Integer partitionId, Long roomUid, Date statDate, Double diamondNum, Double goldNum) { + + roomHourDiamondNumService.addRoomHourDiamondNumMap(partitionId, roomUid, statDate, diamondNum, goldNum); + + //日流水目前只统计了英语2区跟土耳其区的,英语2区设计金币发放 + if (!(PartitionEnum.ENGLISH2.getId() == partitionId || PartitionEnum.TURKEY.getId() == partitionId)) { + return 0; + } ZonedDateTime zonedDateTime = DateTimeUtil.convertWithZoneId(statDate, PartitionEnum.getByPartitionId(partitionId).getZoneId()); String format = zonedDateTime.format(DateTimeUtil.dateFormatter); return baseMapper.addDiamondNum(partitionId, roomUid, format, BigDecimal.valueOf(diamondNum), BigDecimal.valueOf(goldNum)); diff --git a/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/room/impl/RoomHourDiamondNumServiceImpl.java b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/room/impl/RoomHourDiamondNumServiceImpl.java new file mode 100644 index 000000000..c54308ebc --- /dev/null +++ b/accompany-business/accompany-business-service/src/main/java/com/accompany/business/service/room/impl/RoomHourDiamondNumServiceImpl.java @@ -0,0 +1,109 @@ +package com.accompany.business.service.room.impl; + +import cn.hutool.core.date.DateField; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.accompany.business.service.room.RoomHourDiamondNumService; +import com.accompany.sharding.mapper.RoomHourDiamondNumMapper; +import com.accompany.sharding.model.RoomHourDiamondNum; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.collections.CollectionUtils; +import org.redisson.api.RMap; +import org.redisson.api.RedissonClient; +import org.redisson.codec.TypedJsonJacksonCodec; +import org.springframework.beans.factory.annotation.Autowired; +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; +import java.util.stream.Collectors; + +import static com.accompany.business.constant.RoomConstant.RedisKey.room_hour_diamond_num; +import static com.accompany.business.constant.RoomConstant.RedisKey.room_hour_gold_num; +import static com.accompany.common.utils.DateTimeUtil.DATE_HOUR_PATTERN; + +/** + * 房间小时流水数据 服务实现类 + * + * @author + * @since 2025-07-09 + */ +@Service +public class RoomHourDiamondNumServiceImpl extends ServiceImpl implements RoomHourDiamondNumService { + + @Autowired + private RedissonClient redissonClient; + + @Override + public void taskInsertData(Date statDate, Integer partitionId) { + Date currentYYYYMMDDHHTime = getCurrentYYYYMMDDHHTime(statDate); + DateTime actStatDate = DateUtil.offsetHour(currentYYYYMMDDHHTime, -1); + String cacheKeyPatten = getCacheKeyPatten(actStatDate); + Map roomHourDiamondNumMap = new HashMap<>(); + + RMap hourDiamondNumCacheMap = getRoomHourDiamondNumMap(partitionId, cacheKeyPatten); + Map roomHourDiamondMap = hourDiamondNumCacheMap.readAllMap(); + roomHourDiamondMap.entrySet().forEach(entry -> { + RoomHourDiamondNum roomHourDiamondNum = new RoomHourDiamondNum(); + roomHourDiamondNum.setDiamondNum(BigDecimal.valueOf(entry.getValue())); + roomHourDiamondNum.setPartitionId(partitionId); + roomHourDiamondNum.setRoomUid(entry.getKey()); + roomHourDiamondNum.setStatDate(actStatDate); + roomHourDiamondNum.setCreateTime(statDate); + roomHourDiamondNum.setUpdateTime(statDate); + roomHourDiamondNumMap.put(entry.getKey(), roomHourDiamondNum); + + }); + + RMap hourGoldNumCacheMap = getRoomHourGoldNumMap(partitionId, cacheKeyPatten); + Map roomHourGoldMap = hourGoldNumCacheMap.readAllMap(); + roomHourGoldMap.entrySet().forEach(entry -> { + RoomHourDiamondNum roomHourDiamondNum = roomHourDiamondNumMap.getOrDefault(entry.getKey(), new RoomHourDiamondNum()); + roomHourDiamondNum.setGoldNum(BigDecimal.valueOf(entry.getValue())); + roomHourDiamondNum.setPartitionId(partitionId); + roomHourDiamondNum.setRoomUid(entry.getKey()); + roomHourDiamondNum.setStatDate(actStatDate); + roomHourDiamondNum.setCreateTime(statDate); + roomHourDiamondNum.setUpdateTime(statDate); + roomHourDiamondNumMap.put(entry.getKey(), roomHourDiamondNum); + }); + List resultList = roomHourDiamondNumMap.values().stream().collect(Collectors.toList()); + if (CollectionUtils.isEmpty(resultList)) { + return; + } + saveBatch(resultList); + hourDiamondNumCacheMap.delete(); + hourGoldNumCacheMap.delete(); + } + + @Override + public void addRoomHourDiamondNumMap(Integer partitionId, Long roomUid, Date statDate, Double diamondNum, Double goldNum) { + String cacheKeyPatten = this.getCacheKeyPatten(statDate); + this.getRoomHourDiamondNumMap(partitionId, cacheKeyPatten).addAndGet(roomUid, diamondNum); + this.getRoomHourDiamondNumMap(partitionId, cacheKeyPatten).addAndGet(roomUid, goldNum); + } + + @Override + public RMap getRoomHourDiamondNumMap(Integer partitionId, String hourDayStr) { + return redissonClient.getMap(room_hour_diamond_num.getKey(partitionId.toString(), hourDayStr), + new TypedJsonJacksonCodec(Long.class, Double.class)); + } + + @Override + public RMap getRoomHourGoldNumMap(Integer partitionId, String hourDayStr) { + return redissonClient.getMap(room_hour_gold_num.getKey(partitionId.toString(), hourDayStr), + new TypedJsonJacksonCodec(Long.class, Double.class)); + } + + private String getCacheKeyPatten(Date statDate) { + Date currentYYYYMMDDHHTime = getCurrentYYYYMMDDHHTime(statDate); + return DateUtil.format(currentYYYYMMDDHHTime, DATE_HOUR_PATTERN); + } + + private Date getCurrentYYYYMMDDHHTime(Date statDate) { + return DateUtil.truncate(statDate, DateField.HOUR_OF_DAY); + } +} diff --git a/accompany-scheduler/accompany-scheduler-service/src/main/java/com/accompany/scheduler/task/room/RoomHourDiamondTask.java b/accompany-scheduler/accompany-scheduler-service/src/main/java/com/accompany/scheduler/task/room/RoomHourDiamondTask.java new file mode 100644 index 000000000..8a27d1ced --- /dev/null +++ b/accompany-scheduler/accompany-scheduler-service/src/main/java/com/accompany/scheduler/task/room/RoomHourDiamondTask.java @@ -0,0 +1,34 @@ +package com.accompany.scheduler.task.room; + +import cn.hutool.core.date.DateUtil; +import com.accompany.business.service.room.RoomHourDiamondNumService; +import com.accompany.core.enumeration.PartitionEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Slf4j +@Component +public class RoomHourDiamondTask { + + + @Autowired + private RoomHourDiamondNumService roomHourDiamondNumService; + + /** + * 房间小时流水数据的数据 + */ + @Scheduled(cron = "0 1 * * * ?") + public void setRoomHourDiamond() { + Date date = new Date(); + log.info("RoomDayDiamondTask start,date:{}==============", DateUtil.formatDateTime(date)); + PartitionEnum[] values = PartitionEnum.values(); + for (PartitionEnum partitionEnum : values) { + roomHourDiamondNumService.taskInsertData(date, partitionEnum.getId()); + } + log.info("RoomDayDiamondTask end=============="); + } +}