Browse Source

update cache.

deason 5 years ago
parent
commit
87ffdb5a74

+ 8 - 9
examcloud-core-questions-api-provider/src/main/java/cn/com/qmth/examcloud/core/questions/api/provider/ExtractConfigCloudServiceProvider.java

@@ -46,17 +46,16 @@ public class ExtractConfigCloudServiceProvider implements ExtractConfigCloudServ
     @PostMapping("getPaper")
     @Override
     public GetPaperResp getPaper(@RequestBody GetPaperReq paperReq) {
-        Long examId = paperReq.getExamId();
-        if (null == examId) {
-            throw new StatusException("Q-010053", "examId is null");
+        if (paperReq.getExamId() == null) {
+            throw new StatusException("400", "examId is null");
         }
-        String courseCode = paperReq.getCourseCode();
-        if (StringUtils.isBlank(courseCode)) {
-            throw new StatusException("Q-010057", "courseCode is null");
+
+        if (StringUtils.isBlank(paperReq.getCourseCode())) {
+            throw new StatusException("400", "courseCode is empty");
         }
-        String groupCode = paperReq.getGroupCode();
-        if (StringUtils.isBlank(groupCode)) {
-            throw new StatusException("Q-010061", "groupCode is null");
+
+        if (StringUtils.isBlank(paperReq.getGroupCode())) {
+            throw new StatusException("400", "groupCode is empty");
         }
 
         ExtractConfigPaper result = extractConfigExamService.getDefaultPaper(paperReq.getExamId(), paperReq.getCourseCode(), paperReq.getGroupCode());

+ 0 - 4
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/cache/Constants.java

@@ -6,10 +6,6 @@ public interface Constants {
 
     String CACHE_KEY_PAPER_FOR_DTO = "Q_PAPER:DTO_";
 
-    String CACHE_KEY_PAPER_FOR_BASE = "Q_PAPER:BASE_";
-
-    String CACHE_KEY_PAPER_FOR_EXTRACT_CONFIG = "Q_PAPER:EXTRACT_CONFIG_PAPER_";
-
     String CACHE_KEY_QUESTION = "Q_QUESTION:";
 
     int DEFAULT_TIME_OUT = 10 * 60;// N分钟

+ 98 - 112
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/ExtractConfigProviderServiceImpl.java

@@ -10,7 +10,6 @@ import cn.com.qmth.examcloud.core.questions.dao.*;
 import cn.com.qmth.examcloud.core.questions.dao.entity.*;
 import cn.com.qmth.examcloud.core.questions.service.*;
 import cn.com.qmth.examcloud.core.questions.service.bean.extract.ExtractConfigPaper;
-import cn.com.qmth.examcloud.core.questions.service.cache.Constants;
 import cn.com.qmth.examcloud.core.questions.service.config.SysProperty;
 import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
 import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
@@ -18,9 +17,10 @@ import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructur
 import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
 import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
 import cn.com.qmth.examcloud.question.commons.core.question.*;
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigPaperCacheBean;
-import cn.com.qmth.examcloud.web.redis.RedisClient;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -71,140 +71,130 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
     @Autowired
     private PaperService paperService;
 
-    @Autowired
-    private RedisClient redisClient;
-
     @Autowired
     private SysProperty sysProperty;
 
     @Override
     public ExtractConfigCacheBean getExtractConfig(Long examId, String courseCode, String groupCode) {
-        return null;
+        ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
+        if (extractConfig == null) {
+            throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
+        }
+
+        List<ExamPaper> examPapers = extractConfig.getExamPaperList();
+        if (CollectionUtils.isEmpty(examPapers)) {
+            throw new StatusException("500", "可供抽取的试卷集合为空!");
+        }
+
+        ExtractConfigCacheBean cacheBean = new ExtractConfigCacheBean();
+        cacheBean.setId(extractConfig.getId());
+        cacheBean.setExamId(examId);
+        cacheBean.setCourseCode(courseCode);
+        cacheBean.setSortQuestionOrder(extractConfig.getScrambling_the_question_order() == 0 ? false : true);
+        cacheBean.setSortOptionOrder(extractConfig.getScrambling_the_option_order() == 0 ? false : true);
+
+        List<ExtractConfigDetailCacheBean> details = new ArrayList<>();
+        for (ExamPaper examPaper : examPapers) {
+            details.add(new ExtractConfigDetailCacheBean(examPaper.getGroupCode(), examPaper.getPaper().getId(), examPaper.getWeight()));
+        }
+        cacheBean.setDetails(details);
+
+        return cacheBean;
     }
 
     @Override
     public ExtractConfigPaperCacheBean getExtractConfigPaper(Long examId, String courseCode, String groupCode, String paperId) {
-        return null;
+        DefaultPaper defaultPaper = this.buildDefaultByBasePaper(paperId, examId, courseCode, groupCode);
+
+        ExtractConfigPaperCacheBean cacheBean = new ExtractConfigPaperCacheBean();
+        cacheBean.setDefaultPaper(defaultPaper);
+        return cacheBean;
     }
 
     @Override
     public ExtractConfigPaper getDefaultPaper(Long examId, String courseCode, String groupCode) {
-        log.debug("调卷开始...");
+        log.info("调卷开始...");
 
-        log.debug("开始根据examId:" + examId + "和courseCode:" + courseCode + "获取调卷规则");
-        ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
-        if (extractConfig == null) {
-            log.error("该课程调卷规则未制定,请联系学校");
-            throw new StatusException("Q-020101", "该课程调卷规则未制定,请联系学校");
+        ExtractConfigCacheBean extractConfigCache = CacheHelper.getExtractConfig(examId, courseCode, groupCode);
+        if (extractConfigCache == null) {
+            throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
         }
 
-
-        log.debug("根据调卷规则中设置的概率获取类型为" + groupCode + "的试卷");
-        Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
-        if (paperMap.isEmpty()) {
-            log.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
-            throw new StatusException("Q-020109", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
+        final String msg = "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则!";
+        Map<String, String> paperTypeMaps = this.getExamPaperByProbability(extractConfigCache.getDetails());
+        if (paperTypeMaps.isEmpty()) {
+            throw new StatusException("500", msg);
         }
 
-        Paper basePaper = paperMap.get(groupCode);
-        if (basePaper == null) {
-            log.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
-            throw new StatusException("Q-020116", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
+        String basePaperId = paperTypeMaps.get(groupCode);
+        if (StringUtils.isEmpty(basePaperId)) {
+            throw new StatusException("500", msg);
         }
 
-        log.debug("将原始试卷:" + basePaper.getId() + "根据规则构建试卷结构");
-
-        //优先从缓存中取
-        String cacheKey = Constants.CACHE_KEY_PAPER_FOR_EXTRACT_CONFIG + String.format("%s_%s_%s_%s", examId, courseCode, groupCode, basePaper.getId());
-        DefaultPaper defaultPaper = redisClient.get(cacheKey, DefaultPaper.class, Constants.DEFAULT_TIME_OUT);
-        if (defaultPaper == null) {
-            defaultPaper = this.buildDefaultByBasePaper(basePaper, String.valueOf(examId), courseCode, groupCode);
+        log.info("构建试卷结构..." + basePaperId);
+        ExtractConfigPaperCacheBean extractConfigPaperCache = CacheHelper.getExtractConfigPaper(examId, courseCode, groupCode, basePaperId);
+        if (extractConfigPaperCache == null) {
+            throw new StatusException("500", msg);
         }
 
-        Short questionOrder = extractConfig.getScrambling_the_question_order();
-        Short optionOrder = extractConfig.getScrambling_the_option_order();
-
         ExtractConfigPaper result = new ExtractConfigPaper();
-        result.setPaperId(basePaper.getId());
-        result.setSortQuestionOrder(questionOrder == 0 ? false : true);
-        result.setSortOptionOrder(optionOrder == 0 ? false : true);
-        result.setDefaultPaper(defaultPaper);
+        result.setDefaultPaper(extractConfigPaperCache.getDefaultPaper());
+        result.setPaperId(basePaperId);
+        result.setSortQuestionOrder(extractConfigCache.getSortQuestionOrder());
+        result.setSortOptionOrder(extractConfigCache.getSortOptionOrder());
         return result;
     }
 
     /**
      * 每个试卷类型取出一套试卷
-     * {
-     * A:Paper,
-     * B:Paper
-     * }
-     * A是试卷类型   Paper是A类型下选定的试卷
-     *
-     * @param examPaperList
-     * @return
+     * {A:paperId,B:paperId} A是试卷类型,paperId是A类型下选定的试卷ID
      */
-    private Map<String, Paper> getExamPaperByProbability(List<ExamPaper> examPaperList) {
-        Map<String, Paper> paperByTypeMap = new HashMap<>();
-        if (examPaperList == null || examPaperList.size() == 0) {
-            throw new StatusException("Q-020114", "可供抽取的试卷集合为空,无法抽取试卷");
-        }
-
-        Map<String, List<ExamPaper>> examPaperMap = new HashMap<>();
-        for (int i = 0; i < examPaperList.size(); i++) {
-            ExamPaper examPaper = examPaperList.get(i);
-            if (!examPaperMap.containsKey(examPaper.getGroupCode())) {
-                if (examPaper.getPaper() != null) {
-                    List<ExamPaper> epList = new ArrayList<>();
-                    epList.add(examPaper);
-                    examPaperMap.put(examPaper.getGroupCode(), epList);
-                }
+    private Map<String, String> getExamPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
+        if (CollectionUtils.isEmpty(examPapers)) {
+            throw new StatusException("500", "可供抽取的试卷集合为空!");
+        }
+
+        Map<String, List<ExtractConfigDetailCacheBean>> examPaperMaps = new HashMap<>();
+        for (ExtractConfigDetailCacheBean examPaper : examPapers) {
+            if (examPaperMaps.containsKey(examPaper.getGroupCode())) {
+                examPaperMaps.get(examPaper.getGroupCode()).add(examPaper);
             } else {
-                if (examPaper.getPaper() != null) {
-                    List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
-                    epList.add(examPaper);
-                }
+                List<ExtractConfigDetailCacheBean> list = new ArrayList<>();
+                list.add(examPaper);
+                examPaperMaps.put(examPaper.getGroupCode(), list);
             }
         }
 
-        if (examPaperMap != null) {
-            Set<String> keys = examPaperMap.keySet();
-            Iterator<String> it = keys.iterator();
-            while (it.hasNext()) {
-                String key = it.next();
-                Paper paper = this.getPaperByProbability(examPaperMap.get(key));
+        Map<String, String> paperTypeMaps = new HashMap<>();
+        for (Map.Entry<String, List<ExtractConfigDetailCacheBean>> entry : examPaperMaps.entrySet()) {
+            List<ExtractConfigDetailCacheBean> list = examPaperMaps.get(entry.getKey());
 
-                if (paper == null) {
-                    continue;
-                }
-
-                //不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
-                Paper newPaper = Model.of(paperRepo.findById(paper.getId()));
-                paperByTypeMap.put(key, newPaper);
+            String paperId = this.getPaperByProbability(list);
+            if (StringUtils.isEmpty(paperId)) {
+                continue;
             }
+
+            paperTypeMaps.put(entry.getKey(), paperId);
         }
 
-        return paperByTypeMap;
+        return paperTypeMaps;
     }
 
     /**
      * 根据设定几率取出一套试卷
-     *
-     * @param examPaperList
-     * @return
      */
-    private Paper getPaperByProbability(List<ExamPaper> examPaperList) {
+    private String getPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
         int sum = 0;
-        for (int i = 0; i < examPaperList.size(); i++) {
-            sum += examPaperList.get(i).getWeight();
+        for (ExtractConfigDetailCacheBean examPaper : examPapers) {
+            sum += examPaper.getWeight();
         }
 
         // 从1开始  
-        Integer rand = new Random().nextInt(sum) + 1;
-        for (int i = 0; i < examPaperList.size(); i++) {
-            rand -= examPaperList.get(i).getWeight();
-            // 选中
-            if (rand <= 0) {
-                return examPaperList.get(i).getPaper();
+        int r = new Random().nextInt(sum) + 1;
+        for (ExtractConfigDetailCacheBean examPaper : examPapers) {
+            r -= examPaper.getWeight();
+            if (r <= 0) {
+                return examPaper.getPaperId();// 选中
             }
         }
 
@@ -213,33 +203,33 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
 
     /**
      * 根据paper对象构建DefaultPaper对象
-     *
-     * @param basePaper
-     * @return
      */
-    public DefaultPaper buildDefaultByBasePaper(Paper basePaper, String examId, String courseCode, String groupCode) {
+    public DefaultPaper buildDefaultByBasePaper(String basePaperId, Long examId, String courseCode, String groupCode) {
+        Paper basePaper = Model.of(paperRepo.findById(basePaperId));
+        return this.buildDefaultByBasePaper(basePaper, examId, courseCode, groupCode);
+    }
+
+    /**
+     * 根据paper对象构建DefaultPaper对象
+     */
+    public DefaultPaper buildDefaultByBasePaper(Paper basePaper, Long examId, String courseCode, String groupCode) {
         log.debug("开始包装网考需要的试卷结构...");
-        long beginTime = System.currentTimeMillis();
 
         //获取大题
         List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
-        log.debug("数据库取大题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
 
         //排序大题
         Collections.sort(paperDetails);
 
         //将小题全部取出来,只取一次,减少对数据库的查询
-        beginTime = System.currentTimeMillis();
         List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
         boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
-        log.debug("数据库取所有小题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
 
         //根据大题id将小题归类
-        beginTime = System.currentTimeMillis();
         Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream().collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
-        log.debug("获取大题与小题对应关系耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
 
         log.debug("循环大题,开始组装对象...");
+
         //生成新的分组集合
         List<DefaultQuestionGroup> questionGroupList = new ArrayList<>();
         for (int i = 0; i < paperDetails.size(); i++) {
@@ -250,9 +240,9 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
 
             //获取原小题的集合
             List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
-            if (paperDetailUnits == null || paperDetailUnits.size() < 1) {
-                log.error("试卷大题下面,没有小题");
-                throw new StatusException("Q-020241", "考试试卷有误,请联系老师");
+            if (CollectionUtils.isEmpty(paperDetailUnits)) {
+                log.warn("试卷大题下面没有小题!");
+                throw new StatusException("500", "考试试卷有误,请联系老师!");
             }
 
             //按题号顺序排序
@@ -270,8 +260,9 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
 
                 if (examId != null) {
                     //设置音频播放次数
-                    if (paperDetailUnit.getQuestion().getHasAudio() != null && paperDetailUnit.getQuestion().getHasAudio() == true) {
-                        AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, paperDetailUnit.getQuestion().getId()))));
+                    if (paperDetailUnit.getQuestion().getHasAudio() != null && paperDetailUnit.getQuestion().getHasAudio()) {
+                        AudioTimeConfig find = new AudioTimeConfig(examId.toString(), courseCode, groupCode, paperDetailUnit.getQuestion().getId());
+                        AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(find)));
                         if (audioTimeConfig != null) {
                             defaultQuestionStructureWrapper.setLimitedPlayTimes(audioTimeConfig.getPlayTime());
                         }
@@ -307,12 +298,6 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
         defaultPaper.setQuestionGroupList(questionGroupList);
         defaultPaper.setFullyObjective(fullyObjective);
 
-        if (examId != null) {
-            //存入缓存
-            String cacheKey = Constants.CACHE_KEY_PAPER_FOR_EXTRACT_CONFIG + String.format("%s_%s_%s_%s", examId, courseCode, groupCode, basePaper.getId());
-            redisClient.set(cacheKey, defaultPaper, Constants.DEFAULT_TIME_OUT);
-        }
-
         return defaultPaper;
     }
 
@@ -374,8 +359,9 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
 
         Question question = Model.of(quesRepo.findById(questionId));
         if (question == null) {
-            throw new StatusException("Q-020330", "question is null");
+            throw new StatusException("500", "试题不存在!");
         }
+
         quesService.formatQues(question);
         log.debug("查询单个试题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
 

+ 27 - 16
examcloud-core-questions-starter/src/main/java/cn/com/qmth/examcloud/core/questions/starter/DemoController.java

@@ -1,12 +1,12 @@
 package cn.com.qmth.examcloud.core.questions.starter;
 
 import cn.com.qmth.examcloud.core.questions.service.ExtractConfigProviderService;
-import cn.com.qmth.examcloud.core.questions.service.cache.BasePaperCache;
-import cn.com.qmth.examcloud.core.questions.service.cache.Constants;
-import cn.com.qmth.examcloud.core.questions.service.cache.QuestionCache;
-import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
+import cn.com.qmth.examcloud.core.questions.service.bean.extract.ExtractConfigPaper;
+import cn.com.qmth.examcloud.core.questions.service.cache.*;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.BasePaperCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigPaperCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.QuestionCacheBean;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.Naked;
@@ -33,6 +33,10 @@ public class DemoController {
     @Autowired
     private RedisClient redisClient;
     @Autowired
+    private ExtractConfigCache extractConfigCache;
+    @Autowired
+    private ExtractConfigPaperCache extractConfigPaperCache;
+    @Autowired
     private BasePaperCache basePaperCache;
     @Autowired
     private QuestionCache questionCache;
@@ -49,26 +53,33 @@ public class DemoController {
         String paperId = "f4e8b8a3-9f2f-4455-a3c1-62942f1ed171";
         String questionId = "5d5e109aef8fce4eeda1ee12";
 
-        //ExtractConfigPaper extractConfigPaper = extractConfigProviderService.getDefaultPaper(examId, courseCode, groupCode);
-        //log.info("调卷抽取的试卷结构:" + extractConfigPaper.getDefaultPaper().getName());
-        String cacheKey = Constants.CACHE_KEY_PAPER_FOR_EXTRACT_CONFIG + String.format("%s_%s_%s_%s", examId, courseCode, groupCode, paperId);
-        DefaultPaper defaultPaper = redisClient.get(cacheKey, DefaultPaper.class, Constants.DEFAULT_TIME_OUT);
-        log.info("--->缓存的试卷结构: " + defaultPaper.getName());
+        ExtractConfigPaper extractConfigPaper = extractConfigProviderService.getDefaultPaper(examId, courseCode, groupCode);
+        log.info("调卷的试卷结构缓存:" + extractConfigPaper.getDefaultPaper().getName());
+
+        ExtractConfigCacheBean extractConfigCacheBean = CacheHelper.getExtractConfig(examId, courseCode, groupCode);
+        log.info("--->调卷规则缓存: " + extractConfigCacheBean.getDetails().size());
+        //extractConfigCache.remove(examId, courseCode, groupCode);
+
+        ExtractConfigPaperCacheBean extractConfigPaperCacheBean = CacheHelper.getExtractConfigPaper(examId, courseCode, groupCode, paperId);
+        log.info("--->调卷规则的试卷结构缓存: " + extractConfigPaperCacheBean.getDefaultPaper().getName());
+        //extractConfigPaperCache.remove(examId, courseCode, groupCode, paperId);
 
         BasePaperCacheBean basePaperCacheBean = CacheHelper.getBasePaper(paperId);
-        log.info("--->缓存的试卷结构: " + basePaperCacheBean.getDefaultPaper().getName());
+        log.info("--->试卷结构缓存: " + basePaperCacheBean.getDefaultPaper().getName());
         //basePaperCache.remove(paperId);
 
         QuestionCacheBean questionCacheBean = CacheHelper.getQuestion(examId, courseCode, groupCode, questionId);
-        log.info("--->缓存的试题: " + questionCacheBean.getDefaultQuestion().getId());
+        log.info("--->试题缓存: " + questionCacheBean.getDefaultQuestion().getId());
         //questionCache.remove(examId, courseCode, groupCode, questionId);
 
 
-        //获取缓存KEYS
-        final String patternKey = Constants.CACHE_KEY_PAPER + "*" + paperId;
-        //final String patternKey = Constants.CACHE_KEY_QUESTION + "*" + questionId;
-        Set<String> keys = redisTemplate.keys(patternKey);
-        log.info(StringUtils.join(keys, ","));
+        final String pKeys = Constants.CACHE_KEY_PAPER + "*" + paperId;
+        Set<String> paperKeys = redisTemplate.keys(pKeys);
+        log.info(StringUtils.join(paperKeys, ","));
+
+        final String qKeys = Constants.CACHE_KEY_QUESTION + "*" + questionId;
+        Set<String> questionKeys = redisTemplate.keys(qKeys);
+        log.info(StringUtils.join(questionKeys, ","));
 
         return "ok";
     }