فهرست منبع

考试断点延时消息

wangliang 4 سال پیش
والد
کامیت
41a7b506d5

+ 2 - 2
themis-backend/src/main/java/com/qmth/themis/backend/api/TIeInvigilateController.java

@@ -693,13 +693,13 @@ public class TIeInvigilateController {
         Integer durationSeconds = Objects.isNull(ExamRecordCacheUtil.getDurationSeconds(recordId)) ? 0 : ExamRecordCacheUtil.getDurationSeconds(recordId);
         Integer durationSeconds = Objects.isNull(ExamRecordCacheUtil.getDurationSeconds(recordId)) ? 0 : ExamRecordCacheUtil.getDurationSeconds(recordId);
         Long endTime = Objects.isNull(ExamRecordCacheUtil.getEndTime(recordId)) ? 0 : ExamRecordCacheUtil.getEndTime(recordId);
         Long endTime = Objects.isNull(ExamRecordCacheUtil.getEndTime(recordId)) ? 0 : ExamRecordCacheUtil.getEndTime(recordId);
         if (Objects.nonNull(mode) && Objects.equals(mode, ExamModeEnum.ANYTIME)) {
         if (Objects.nonNull(mode) && Objects.equals(mode, ExamModeEnum.ANYTIME)) {
-            Long diffTime = maxDurationSeconds.longValue() - durationSeconds.longValue();
+            Long diffTime = (maxDurationSeconds.longValue() - durationSeconds.longValue()) * 1000;
             remainTime = diffTime.intValue() == 0 ? "00:00:00" : SystemConstant.getRemainTime(diffTime);
             remainTime = diffTime.intValue() == 0 ? "00:00:00" : SystemConstant.getRemainTime(diffTime);
         } else if (Objects.nonNull(mode) && Objects.equals(mode, ExamModeEnum.TOGETHER) && Objects.nonNull(forceFinish) && forceFinish.intValue() == 1) {
         } else if (Objects.nonNull(mode) && Objects.equals(mode, ExamModeEnum.TOGETHER) && Objects.nonNull(forceFinish) && forceFinish.intValue() == 1) {
             Long diffTime = endTime - System.currentTimeMillis();
             Long diffTime = endTime - System.currentTimeMillis();
             remainTime = diffTime.intValue() == 0 ? "00:00:00" : SystemConstant.getRemainTime(diffTime);
             remainTime = diffTime.intValue() == 0 ? "00:00:00" : SystemConstant.getRemainTime(diffTime);
         } else {
         } else {
-            Long diffTime = maxDurationSeconds.longValue() - durationSeconds.longValue();
+            Long diffTime = (maxDurationSeconds.longValue() - durationSeconds.longValue()) * 1000;
             remainTime = diffTime.intValue() == 0 ? "00:00:00" : SystemConstant.getRemainTime(diffTime);
             remainTime = diffTime.intValue() == 0 ? "00:00:00" : SystemConstant.getRemainTime(diffTime);
         }
         }
         return remainTime;
         return remainTime;

+ 2 - 0
themis-backend/src/main/java/com/qmth/themis/backend/start/StartRunning.java

@@ -80,6 +80,8 @@ public class StartRunning implements CommandLineRunner {
 
 
         //考试断点
         //考试断点
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakConcurrentlyImpl.class));
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_DELAY_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK_DELAY.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakDelayConcurrentlyImpl.class));
+
         SystemConstant.initTempFiles();
         SystemConstant.initTempFiles();
         log.info("服务器启动时执行 end");
         log.info("服务器启动时执行 end");
     }
     }

+ 3 - 1
themis-business/src/main/java/com/qmth/themis/business/enums/MqExecTypeEnum.java

@@ -37,7 +37,9 @@ public enum MqExecTypeEnum {
 
 
     EXEC_MQ_CALCULATE_OBJECTIVE_SCORE_LOGIC("计算客观分逻辑", "execMqCalculateObjectiveScoreLogic"),
     EXEC_MQ_CALCULATE_OBJECTIVE_SCORE_LOGIC("计算客观分逻辑", "execMqCalculateObjectiveScoreLogic"),
 
 
-    EXEC_MQ_WEBSOCKET_UN_NORMAL_LOGIC("websocket非正常退出,延时消息逻辑", "execMqWebsocketUnNormalLogic");
+    EXEC_MQ_WEBSOCKET_UN_NORMAL_LOGIC("websocket非正常退出,延时消息逻辑", "execMqWebsocketUnNormalLogic"),
+
+    EXEC_MQ_EXAM_BREAK_DELAY_LOGIC("考试断点,延时消息逻辑", "execMqExamBreakDelayLogic");
 
 
     private String code;
     private String code;
     private String desc;
     private String desc;

+ 6 - 1
themis-business/src/main/java/com/qmth/themis/business/enums/MqGroupEnum.java

@@ -90,7 +90,12 @@ public enum MqGroupEnum {
     /**
     /**
      * 考试断点
      * 考试断点
      */
      */
-    EXAM_BREAK_GROUP("themis-group-exam-examBreak");
+    EXAM_BREAK_GROUP("themis-group-exam-examBreak"),
+
+    /**
+     * 考试断点延时消息
+     */
+    EXAM_BREAK_DELAY_GROUP("themis-group-exam-examBreakDelay");
 
 
     private MqGroupEnum(String code) {
     private MqGroupEnum(String code) {
         this.code = code;
         this.code = code;

+ 2 - 1
themis-business/src/main/java/com/qmth/themis/business/enums/MqTagEnum.java

@@ -47,7 +47,8 @@ public enum MqTagEnum {
     EXAM_STUDENT("考生一次性延时任务标签", "考生一次性延时任务", "normal", 35),
     EXAM_STUDENT("考生一次性延时任务标签", "考生一次性延时任务", "normal", 35),
     EXAM_STUDENT_EXPORT("考生导出任务标签", "考生导出任务", "normal", 36),
     EXAM_STUDENT_EXPORT("考生导出任务标签", "考生导出任务", "normal", 36),
     MARK_RESULT_SIMPLE_EXPORT("成绩查询简版导出任务标签", "成绩查询简版导出任务", "normal", 37),
     MARK_RESULT_SIMPLE_EXPORT("成绩查询简版导出任务标签", "成绩查询简版导出任务", "normal", 37),
-    MARK_RESULT_STANDARD_EXPORT("成绩查询标准版导出任务标签", "成绩查询标准版导出任务", "normal", 38);
+    MARK_RESULT_STANDARD_EXPORT("成绩查询标准版导出任务标签", "成绩查询标准版导出任务", "normal", 38),
+    EXAM_BREAK_DELAY("断点时间标签", "断点时间", "delay", 39);
 
 
     private MqTagEnum(String desc, String code, String type, int id) {
     private MqTagEnum(String desc, String code, String type, int id) {
         this.desc = desc;
         this.desc = desc;

+ 39 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -976,6 +976,45 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                 MqDtoService mqDtoService = SpringContextHolder.getBean(MqDtoService.class);
                 MqDtoService mqDtoService = SpringContextHolder.getBean(MqDtoService.class);
                 mqDtoService.assembleSendOneWayMsg(mqDtoBreak);
                 mqDtoService.assembleSendOneWayMsg(mqDtoBreak);
                 //考试断点异常原因 发送mq end
                 //考试断点异常原因 发送mq end
+
+                Long examId = ExamRecordCacheUtil.getExamId(recordId);
+                ExamCacheBean ec = examService.getExamCacheBean(examId);//考试缓存
+                Integer breakExpireSeconds = Objects.isNull(ec.getBreakExpireSeconds()) ? 0 : ec.getBreakExpireSeconds();
+                if (breakExpireSeconds > 0) {
+                    List<String> list = SystemConstant.mqDelayLevelList.subList(5, 15);
+                    String level = null;
+                    if (breakExpireSeconds <= 60) {
+                        level = "1m";
+                    } else {
+                        Integer time = breakExpireSeconds.intValue() / 60;
+                        if (time >= 30) {
+                            level = "30m";
+                        } else {
+                            for (String s : list) {
+                                Integer value = Integer.parseInt(s.substring(0, s.length() - 1));
+                                if (time.intValue() <= value.intValue()) {
+                                    level = value + "m";
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    Map<String, Object> tranMap = new HashMap<>();
+                    Integer time = SystemConstant.mqDelayLevel.get(level);
+                    LocalDateTime dt = LocalDateTime.now();
+                    if (level.contains("m")) {
+                        dt = dt.plusMinutes(Long.parseLong(level.replace("m", "")));
+                    } else {
+                        dt = dt.plusSeconds(Long.parseLong(level.replace("s", "")));
+                    }
+                    tranMap.put("recordId", recordId);
+                    tranMap.put("timeOut", time);
+                    tranMap.put("mqExecTime", dt.toInstant(ZoneOffset.of("+8")).toEpochMilli());
+                    //考试断点延时消息 发送mq start
+                    MqDto mqDtoBreakDelay = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK_DELAY.name(), MqTagEnum.EXAM_BREAK_DELAY, MqTagEnum.EXAM_BREAK_DELAY, String.valueOf(recordId), tranMap, String.valueOf(recordId));
+                    mqDtoService.assembleSendAsyncDelayMsg(mqDtoBreakDelay);
+                    //考试断点延时消息 发送mq end
+                }
                 //更新场次-考试记录缓存
                 //更新场次-考试记录缓存
                 ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId, new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId), ExamRecordCacheUtil.getStatus(recordId)));
                 ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId, new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId), ExamRecordCacheUtil.getStatus(recordId)));
             } catch (Exception e) {
             } catch (Exception e) {

+ 1 - 0
themis-exam/src/main/java/com/qmth/themis/exam/start/StartRunning.java

@@ -85,6 +85,7 @@ public class StartRunning implements CommandLineRunner {
 
 
         //考试断点
         //考试断点
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakConcurrentlyImpl.class));
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_DELAY_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK_DELAY.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakDelayConcurrentlyImpl.class));
         SystemConstant.initTempFiles();
         SystemConstant.initTempFiles();
         log.info("服务器启动时执行 end");
         log.info("服务器启动时执行 end");
     }
     }

+ 8 - 0
themis-mq/src/main/java/com/qmth/themis/mq/service/MqLogicService.java

@@ -134,6 +134,14 @@ public interface MqLogicService {
      */
      */
     void execMqExamBreakLogic(MqDto mqDto, String key);
     void execMqExamBreakLogic(MqDto mqDto, String key);
 
 
+    /**
+     * 考试断点延时消息
+     *
+     * @param mqDto
+     * @param key
+     */
+    void execMqExamBreakDelayLogic(MqDto mqDto, String key);
+
     /**
     /**
      * 普通消息
      * 普通消息
      *
      *

+ 26 - 0
themis-mq/src/main/java/com/qmth/themis/mq/service/impl/MqLogicServiceImpl.java

@@ -789,6 +789,32 @@ public class MqLogicServiceImpl implements MqLogicService {
         redisUtil.delete(key, mqDto.getId());
         redisUtil.delete(key, mqDto.getId());
     }
     }
 
 
+    /**
+     * 考试断点延时消息
+     *
+     * @param mqDto
+     * @param key
+     */
+    @Override
+    @Transactional
+    public void execMqExamBreakDelayLogic(MqDto mqDto, String key) {
+        Gson gson = new Gson();
+        mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);//表示成功处理
+        Map<String, Object> tranMap = mqDto.getProperties();
+        Long recordId = Long.parseLong(String.valueOf(tranMap.get("recordId")));
+        ExamRecordStatusEnum statusEnum = ExamRecordCacheUtil.getStatus(recordId);
+        if (Objects.nonNull(statusEnum) && !Objects.equals(statusEnum, ExamRecordStatusEnum.FINISHED) && !Objects.equals(statusEnum, ExamRecordStatusEnum.PERSISTED) && !Objects.equals(statusEnum, ExamRecordStatusEnum.ANSWERING)) {
+            Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+            Integer durationSeconds = Objects.isNull(ExamRecordCacheUtil.getDurationSeconds(recordId)) ? 0 : ExamRecordCacheUtil.getDurationSeconds(recordId);
+            ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
+            teExamService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
+        }
+        TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
+        tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
+        tmRocketMessageService.saveOrUpdate(tmRocketMessage);
+        redisUtil.delete(key, mqDto.getId());
+    }
+
     /**
     /**
      * 普通消息
      * 普通消息
      *
      *

+ 29 - 0
themis-mq/src/main/java/com/qmth/themis/mq/templete/impl/ExamBreakDelayConcurrentlyImpl.java

@@ -0,0 +1,29 @@
+package com.qmth.themis.mq.templete.impl;
+
+import com.qmth.themis.business.constant.SpringContextHolder;
+import com.qmth.themis.business.enums.MqExecTypeEnum;
+import com.qmth.themis.mq.service.MqLogicService;
+import com.qmth.themis.mq.templete.Concurrently;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @Description: mq 延时消息监听 考试断点延时消息 并行消费监听
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2020/7/28
+ */
+@Service
+public class ExamBreakDelayConcurrentlyImpl implements Concurrently {
+
+    @Override
+    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
+        MqLogicService mqLogicService = SpringContextHolder.getBean(MqLogicService.class);
+        return mqLogicService.consumeMessageDelay(msgs, consumeConcurrentlyContext, MqExecTypeEnum.EXEC_MQ_EXAM_BREAK_DELAY_LOGIC);
+    }
+}

+ 1 - 0
themis-task/src/main/java/com/qmth/themis/task/start/StartRunning.java

@@ -113,6 +113,7 @@ public class StartRunning implements CommandLineRunner {
 
 
         //考试断点
         //考试断点
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakConcurrentlyImpl.class));
         rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakConcurrentlyImpl.class));
+        rocketMessageConsumer.setRocketMQConsumer(nameServer, MqGroupEnum.EXAM_BREAK_DELAY_GROUP.getCode(), MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK_DELAY.name(), MessageModel.CLUSTERING, SpringContextHolder.getBean(ExamBreakDelayConcurrentlyImpl.class));
         SystemConstant.initTempFiles();
         SystemConstant.initTempFiles();
         log.info("服务器启动时执行 end");
         log.info("服务器启动时执行 end");
     }
     }