فهرست منبع

1、解决积分数据修改事务问题

rayson 1 سال پیش
والد
کامیت
b3cba17d49
14فایلهای تغییر یافته به همراه206 افزوده شده و 141 حذف شده
  1. 0 17
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/config/RulesConfiguration.java
  2. 18 0
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/core/PointRuleListener.java
  3. 58 0
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/mq/consumer/UserPointConsumer.java
  4. 41 0
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/mq/message/UserPointSendMessage.java
  5. 28 0
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/mq/producer/UserPointProducer.java
  6. 1 1
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/service/config/PointRuleConfigServiceImpl.java
  7. 51 65
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/service/event/EventTrackServiceImpl.java
  8. 5 0
      menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/service/record/PointRecordServiceImpl.java
  9. 4 0
      menduner/menduner-reward-biz/src/main/resources/application.yaml
  10. 0 12
      menduner/menduner-system-biz/src/main/resources/mapper/job/JobInterestedMapper.xml
  11. 0 10
      menduner/menduner-system-biz/src/main/resources/mapper/major/MajorMapper.xml
  12. 0 12
      menduner/menduner-system-biz/src/main/resources/mapper/person/PeopleCertificateMapper.xml
  13. 0 12
      menduner/menduner-system-biz/src/main/resources/mapper/person/PeopleInfoMapper.xml
  14. 0 12
      menduner/menduner-system-biz/src/main/resources/mapper/person/PeopleSkillMapper.xml

+ 0 - 17
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/config/RulesConfiguration.java

@@ -1,17 +0,0 @@
-package com.citu.module.menduner.reward.config;
-
-import org.jeasy.rules.api.RulesEngine;
-import org.jeasy.rules.core.DefaultRulesEngine;
-import org.springframework.context.annotation.Bean;
-
-/**
- * 规则配置
- * @author rayson
- **/
-public class RulesConfiguration {
-
-    @Bean
-    public RulesEngine rulesEngine() {
-        return new DefaultRulesEngine();
-    }
-}

+ 18 - 0
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/core/PointRuleListener.java

@@ -0,0 +1,18 @@
+package com.citu.module.menduner.reward.core;
+
+import org.jeasy.rules.api.Facts;
+import org.jeasy.rules.api.Rule;
+import org.jeasy.rules.api.RuleListener;
+
+/**
+ * @author rayson
+ * @description PointRuleListener
+ * @create 2024/6/27 上午10:24
+ **/
+public class PointRuleListener implements RuleListener {
+
+    @Override
+    public void onSuccess(Rule rule, Facts facts) {
+
+    }
+}

+ 58 - 0
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/mq/consumer/UserPointConsumer.java

@@ -0,0 +1,58 @@
+package com.citu.module.menduner.reward.mq.consumer;
+
+import com.baomidou.dynamic.datasource.annotation.DSTransactional;
+import com.citu.module.menduner.reward.enums.MathOperationEnum;
+import com.citu.module.menduner.reward.enums.record.PointBizTypeEnum;
+import com.citu.module.menduner.reward.mq.message.UserPointSendMessage;
+import com.citu.module.menduner.reward.service.event.EventRecordService;
+import com.citu.module.menduner.reward.service.record.PointRecordService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 用户积分 消费
+ **/
+@Slf4j
+@Component
+@RocketMQMessageListener(
+        topic = UserPointSendMessage.TOPIC,
+        consumerGroup = UserPointSendMessage.TOPIC + "_CONSUMER"
+)
+public class UserPointConsumer implements RocketMQListener<UserPointSendMessage>, RocketMQPushConsumerLifecycleListener {
+
+    @Resource
+    private PointRecordService pointRecordService;
+
+    @Resource
+    private EventRecordService eventRecordService;
+
+    @Override
+    @DSTransactional
+    public void onMessage(UserPointSendMessage message) {
+        log.info("接收到队列消息[{}]", message);
+        // 增加积分
+        pointRecordService.createPointRecord(
+                message.getUserId(),
+                message.getUrl(),
+                message.getTitle(),
+                message.getOperation(),
+                message.getPoint(),
+                message.getBizType(),
+                message.getBizId());
+        // 增加点击数
+        eventRecordService.createEventRecord( message.getUserId(), message.getUrl());
+        log.info("消息处理完备[{}]", message);
+    }
+
+    @Override
+    public void prepareStart(DefaultMQPushConsumer consumer) {
+        // 不重试,失败说明扣除失败,额度不足等
+        consumer.setMaxReconsumeTimes(0);
+    }
+}

+ 41 - 0
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/mq/message/UserPointSendMessage.java

@@ -0,0 +1,41 @@
+package com.citu.module.menduner.reward.mq.message;
+
+import com.citu.module.menduner.reward.enums.MathOperationEnum;
+import com.citu.module.menduner.reward.enums.record.PointBizTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Schema(description = "用户积分消息")
+public class UserPointSendMessage {
+
+    public static final String TOPIC = "USER_POINT_TOPIC";
+
+    @Schema(description = "用户id")
+    private Long userId;
+
+    @Schema(description = "事件地址")
+    private String url;
+
+    @Schema(description = "事件标题")
+    private String title;
+
+    @Schema(description = "数据操作符")
+    private MathOperationEnum operation;
+
+    @Schema(description = "积分数量")
+    private Integer point;
+
+    @Schema(description = "业务类型")
+    private PointBizTypeEnum bizType;
+
+    @Schema(description = "业务id")
+    private String bizId;
+
+}

+ 28 - 0
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/mq/producer/UserPointProducer.java

@@ -0,0 +1,28 @@
+package com.citu.module.menduner.reward.mq.producer;
+
+import com.citu.module.menduner.reward.mq.message.UserPointSendMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 用户积分 Producer
+ *
+ * @author Rayson
+ */
+@Slf4j
+@Component
+public class UserPointProducer {
+
+    @Resource
+    private RocketMQTemplate rocketMQTemplate;
+
+    public void send(UserPointSendMessage content) {
+        Message<?> message = MessageBuilder.withPayload(content).build();
+        rocketMQTemplate.syncSend(UserPointSendMessage.TOPIC, message);
+    }
+}

+ 1 - 1
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/service/config/PointRuleConfigServiceImpl.java

@@ -51,7 +51,7 @@ public class PointRuleConfigServiceImpl implements PointRuleConfigService {
 
     @Override
     @DSTransactional
-    @CacheEvict(value = RedisKeyConstants.POINT_RULE_CONFIG, key = "#updateReqVO.id")
+    @CacheEvict(value = RedisKeyConstants.POINT_RULE_CONFIG, key = "#updateReqVO.url")
     public void updatePointRuleConfig(PointRuleConfigSaveReqVO updateReqVO) {
         // 校验存在
         validatePointRuleConfigExists(updateReqVO.getId());

+ 51 - 65
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/service/event/EventTrackServiceImpl.java

@@ -1,6 +1,5 @@
 package com.citu.module.menduner.reward.service.event;
 
-import com.baomidou.dynamic.datasource.tx.LocalTxUtil;
 import com.citu.framework.security.core.LoginUser;
 import com.citu.module.menduner.common.util.LoginUserContext;
 import com.citu.module.menduner.reward.controller.base.common.TreeRespVO;
@@ -14,10 +13,11 @@ import com.citu.module.menduner.reward.dal.dataobject.config.Condition;
 import com.citu.module.menduner.reward.dal.dataobject.config.PointRuleConfigDO;
 import com.citu.module.menduner.reward.enums.MathOperationEnum;
 import com.citu.module.menduner.reward.enums.record.PointBizTypeEnum;
+import com.citu.module.menduner.reward.mq.message.UserPointSendMessage;
+import com.citu.module.menduner.reward.mq.producer.UserPointProducer;
 import com.citu.module.menduner.reward.rule.DynamicPointRule;
 import com.citu.module.menduner.reward.rule.DynamicRuleAction;
 import com.citu.module.menduner.reward.service.config.PointRuleConfigService;
-import com.citu.module.menduner.reward.service.record.PointRecordService;
 import com.citu.module.menduner.system.api.url.MendunerSystemUrlApi;
 import com.citu.module.menduner.system.api.url.UrlInfoRespVO;
 import lombok.extern.slf4j.Slf4j;
@@ -30,7 +30,6 @@ import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 import static com.citu.module.menduner.reward.enums.EasyRulesConstants.*;
@@ -52,12 +51,13 @@ public class EventTrackServiceImpl implements EventTrackService {
     @Resource
     private EventRecordService eventRecordService;
 
-    @Resource
-    private PointRecordService pointRecordService;
 
     @Resource
     private MendunerSystemUrlApi mendunerSystemUrlApi;
 
+    @Resource
+    private UserPointProducer userPointProducer;
+
     public static List<TreeRespVO<List<TreeRespVO<List<UrlInfoRespVO>>>>> convertUrlInfoListToTree(List<UrlInfoRespVO> urlInfoList) {
         // 首先按client分组,然后在每个client分组内部按module分组
         Map<String, Map<String, List<UrlInfoRespVO>>> groupedByClientAndModule = urlInfoList.stream()
@@ -104,71 +104,57 @@ public class EventTrackServiceImpl implements EventTrackService {
 
     @Override
     public EventTrackPointRespVO click(String url) throws Exception {
-        AtomicBoolean state = new AtomicBoolean(true);
-        String xid = LocalTxUtil.startTransaction();
+
         // 初始化响应对象
         EventTrackPointRespVO respVO = new EventTrackPointRespVO();
-        try {
+        // 获取当前登录用户信息
+        LoginUser loginUser = LoginUserContext.get2();
+        if (null == loginUser) {
+            // 如果用户未登录,返回空
+            return respVO;
+        }
 
-            // 获取当前登录用户信息
-            LoginUser loginUser = LoginUserContext.get2();
-            if (null == loginUser) {
-                // 如果用户未登录,返回空
-                return respVO;
-            }
+        // 根据URL获取积分规则配置信息
+        PointRuleConfigDO config = ruleConfigService.getByUrl(url);
+        if (null == config) {
+            // 如果配置信息不存在,返回空
+            return respVO;
+        }
 
-            // 根据URL获取积分规则配置信息
-            PointRuleConfigDO config = ruleConfigService.getByUrl(url);
-            if (null == config) {
-                // 如果配置信息不存在,返回空
-                return respVO;
-            }
+        // 获取触发参数映射
+        Map<String, Object> triggerMap =
+                getRuleContextMap(loginUser.getId(), config.getUrl(), config.getTriggerRule());
+
+        // 创建积分规则对象
+        PointRule pointRule = createPointRule(config, triggerMap, null);
+
+        // 设置响应对象的基本信息
+        respVO.setTitle(config.getTitle());
+        respVO.setOperation(pointRule.getOperation());
+        respVO.setType(config.getType());
+        respVO.setPoint(pointRule.getPoint());
+
+        // 执行规则匹配和响应处理
+        DynamicRuleAction<PointRule> action = (t) -> {
+            // 发送消息
+            userPointProducer.send(UserPointSendMessage.builder()
+                    .userId(loginUser.getId())
+                    .url(url)
+                    .title(config.getTitle())
+                    .operation(MathOperationEnum.ADD.getOperator().equals(config.getOperation())
+                            ? MathOperationEnum.ADD : MathOperationEnum.SUBTRACT)
+                    .point(t.getPoint())
+                    .bizType(PointBizTypeEnum.EVENT)
+                    .bizId(String.valueOf(config.getId()))
+                    .build()
+            );
+            // 标记匹配成功
+            respVO.match();
+
+        };
+        // 匹配
+        match(pointRule, action);
 
-            // 获取触发参数映射
-            Map<String, Object> triggerMap =
-                    getRuleContextMap(loginUser.getId(), config.getUrl(), config.getTriggerRule());
-
-            // 创建积分规则对象
-            PointRule pointRule = createPointRule(config, triggerMap, null);
-
-            // 设置响应对象的基本信息
-            respVO.setTitle(config.getTitle());
-            respVO.setOperation(pointRule.getOperation());
-            respVO.setType(config.getType());
-            respVO.setPoint(pointRule.getPoint());
-
-            // 执行规则匹配和响应处理
-
-            DynamicRuleAction<PointRule> action = (t) -> {
-                try {
-                    // 增加积分
-                    pointRecordService.createPointRecord(
-                            loginUser.getId(),
-                            url,
-                            config.getTitle(),
-                            MathOperationEnum.ADD.getOperator().equals(config.getOperation())
-                                    ? MathOperationEnum.ADD : MathOperationEnum.SUBTRACT,
-                            t.getPoint(),
-                            PointBizTypeEnum.EVENT,
-                            String.valueOf(config.getId()));
-                    // 增加点击数
-                    eventRecordService.createEventRecord(loginUser.getId(), url);
-                    respVO.match();
-                }catch (Exception ex) {
-                    state.set(false);
-                    throw ex;
-                }
-            };
-            match(pointRule, action);
-        }catch (Exception ex) {
-            state.set(false);
-        }finally {
-            if (state.get()) {
-                LocalTxUtil.commit(xid);
-            } else {
-                LocalTxUtil.rollback(xid);
-            }
-        }
         // 返回响应对象
         return respVO;
     }

+ 5 - 0
menduner/menduner-reward-biz/src/main/java/com/citu/module/menduner/reward/service/record/PointRecordServiceImpl.java

@@ -63,8 +63,13 @@ public class PointRecordServiceImpl implements PointRecordService {
         }
 
         if (MathOperationEnum.SUBTRACT.equals(operation)) {
+            if (userPoint - point < 0) {
+                throw exception(USER_POINT_NOT_ENOUGH);
+            }
+            totalPoint = userPoint - point;
             // 减法
             point = -Math.abs(point);
+
         }
 
         // 2. 更新用户积分

+ 4 - 0
menduner/menduner-reward-biz/src/main/resources/application.yaml

@@ -95,6 +95,10 @@ easy-trans:
 --- #################### RPC 远程调用相关配置 ####################
 
 --- #################### MQ 消息队列相关配置 ####################
+rocketmq:
+  producer:
+    #生产者分组
+    group: ${spring.application.name}_PRODUCER
 
 --- #################### 定时任务相关配置 ####################
 

+ 0 - 12
menduner/menduner-system-biz/src/main/resources/mapper/job/JobInterestedMapper.xml

@@ -1,12 +0,0 @@
-<?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.citu.module.menduner.system.dal.mysql.job.JobInterestedMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>

+ 0 - 10
menduner/menduner-system-biz/src/main/resources/mapper/major/MajorMapper.xml

@@ -1,10 +0,0 @@
-<?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.citu.module.menduner.system.dal.mysql.major.MajorMapper">
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-</mapper>

+ 0 - 12
menduner/menduner-system-biz/src/main/resources/mapper/person/PeopleCertificateMapper.xml

@@ -1,12 +0,0 @@
-<?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.citu.module.menduner.system.dal.mysql.person.PersonCertificateMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>

+ 0 - 12
menduner/menduner-system-biz/src/main/resources/mapper/person/PeopleInfoMapper.xml

@@ -1,12 +0,0 @@
-<?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.citu.module.menduner.system.dal.mysql.person.PersonInfoMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>

+ 0 - 12
menduner/menduner-system-biz/src/main/resources/mapper/person/PeopleSkillMapper.xml

@@ -1,12 +0,0 @@
-<?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.citu.module.menduner.system.dal.mysql.person.PersonSkillMapper">
-
-    <!--
-        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
-        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
-        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
-        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
-     -->
-
-</mapper>