Browse Source

Merge remote-tracking branch 'origin/release_v5.0.1'

deason 1 year ago
parent
commit
7d94f239a8
32 changed files with 106 additions and 2450 deletions
  1. 5 0
      examcloud-core-oe-task-api-provider/pom.xml
  2. 0 6
      examcloud-core-oe-task-service/pom.xml
  3. 3 0
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/CommonService.java
  4. 0 8
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/ExamCaptureQueueService.java
  5. 0 3
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/ExamCaptureService.java
  6. 0 11
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/ExamSyncCaptureService.java
  7. 0 343
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/FaceVerifyService.java
  8. 2 1
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamBossServiceImpl.java
  9. 15 13
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamCaptureQueueServiceImpl.java
  10. 0 26
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamCaptureServiceImpl.java
  11. 4 2
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamRecordDataServiceImpl.java
  12. 0 16
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamSyncCaptureServiceImpl.java
  13. 2 1
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamingSessionServiceImpl.java
  14. 31 6
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/AfterHandInExamJobHandler.java
  15. 8 6
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/BeforeHandInExamJobHandler.java
  16. 2 2
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/FaceVerifyJobHandler.java
  17. 10 8
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/SyncExamRecordDataJobHandler.java
  18. 0 123
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/AfterHandInExamExecutor.java
  19. 0 156
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/ClearExamDataCacheExecutor.java
  20. 0 182
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/DataGainExamExecutor.java
  21. 0 220
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/HandInExamExecutor.java
  22. 0 235
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/SyncExamDataExecutor.java
  23. 0 81
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/worker/BaiduFaceLivenessWorker.java
  24. 0 87
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/worker/FacePPCompareWorker.java
  25. 0 158
      examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/worker/FaceVerifyCounter.java
  26. 2 1
      examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ExamCloudResourceManager.java
  27. 0 160
      examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessBaiduFaceLivenessAlarmTask.java
  28. 0 155
      examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessBaiduFacelivenessTask.java
  29. 0 169
      examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessFaceCompareAlarmTask.java
  30. 0 157
      examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessFaceCompareQueueTask.java
  31. 0 113
      examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/StreamTaskExecutor.java
  32. 22 1
      jenkins.sh

+ 5 - 0
examcloud-core-oe-task-api-provider/pom.xml

@@ -17,6 +17,11 @@
             <artifactId>examcloud-core-oe-task-service</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>cn.com.qmth.examcloud.rpc</groupId>
+            <artifactId>examcloud-core-oe-task-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 0 - 6
examcloud-core-oe-task-service/pom.xml

@@ -28,15 +28,9 @@
             <artifactId>examcloud-core-oe-student-api-client</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <dependency>
-            <groupId>cn.com.qmth.examcloud.rpc</groupId>
-            <artifactId>examcloud-core-oe-task-api</artifactId>
-            <version>${project.version}</version>
-        </dependency>
         <dependency>
             <groupId>com.xuxueli</groupId>
             <artifactId>xxl-job-core</artifactId>
-            <version>2.3.1</version>
         </dependency>
     </dependencies>
 

+ 3 - 0
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/CommonService.java

@@ -88,6 +88,9 @@ public class CommonService {
         data.setFaceStrangerCount(examRecordData.getFaceStrangerCount());
         data.setFaceSuccessPercent(examRecordData.getFaceSuccessPercent());
 
+        data.setRandomPaper(examRecordData.getRandomPaper());
+        data.setPaperScore(examRecordData.getPaperScore());
+
         data.setTotalScore(examRecordData.getTotalScore());
         data.setObjectiveScore(examRecordData.getObjectiveScore());
         data.setObjectiveAccuracy(examRecordData.getObjectiveAccuracy());

+ 0 - 8
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/ExamCaptureQueueService.java

@@ -1,7 +1,5 @@
 package cn.com.qmth.examcloud.core.oe.task.service;
 
-import cn.com.qmth.examcloud.core.oe.student.dao.enums.ExamCaptureQueueStatus;
-
 /**
  * 处理考试抓拍队列
  */
@@ -9,10 +7,4 @@ public interface ExamCaptureQueueService {
 
     void handlerExamCaptureQueuesByExamRecordDataId(Long examRecordDataId) throws Exception;
 
-    /**
-     * 图片抓拍队列处理失败时,保存队列信息
-     */
-    @Deprecated
-    boolean saveExamCaptureQueueEntityByFailed(Long captureQueueId, String errorMsg, ExamCaptureQueueStatus status);
-
 }

+ 0 - 3
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/ExamCaptureService.java

@@ -1,7 +1,6 @@
 package cn.com.qmth.examcloud.core.oe.task.service;
 
 import cn.com.qmth.examcloud.core.oe.task.service.bean.CalculateFaceCheckResultInfo;
-import cn.com.qmth.examcloud.core.oe.task.service.bean.ExamCaptureQueueInfo;
 
 /**
  * @Description 照片处理结果
@@ -11,8 +10,6 @@ import cn.com.qmth.examcloud.core.oe.task.service.bean.ExamCaptureQueueInfo;
  */
 public interface ExamCaptureService {
 
-    void saveExamCaptureAndDeleteQueue(ExamCaptureQueueInfo examCaptureQueue);
-
     /**
      * 计算人脸检测结果
      *

+ 0 - 11
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/ExamSyncCaptureService.java

@@ -1,11 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service;
-
-/**
- * @Description 同步抓拍照片接口
- * @Author lideyin
- * @Date 2019/12/6 16:19
- * @Version 1.0
- */
-public interface ExamSyncCaptureService {
-
-}

+ 0 - 343
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/FaceVerifyService.java

@@ -1,343 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.helpers.JsonHttpResponseHolder;
-import cn.com.qmth.examcloud.core.oe.student.dao.ExamCaptureQueueRepo;
-import cn.com.qmth.examcloud.core.oe.student.dao.enums.ExamCaptureQueueStatus;
-import cn.com.qmth.examcloud.core.oe.task.service.bean.ExamCaptureQueueInfo;
-import cn.com.qmth.examcloud.core.oe.task.service.worker.FaceVerifyCounter;
-import cn.com.qmth.examcloud.support.Constants;
-import cn.com.qmth.examcloud.support.cache.CacheHelper;
-import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
-import cn.com.qmth.examcloud.support.enums.ExamProperties;
-import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
-import cn.com.qmth.examcloud.support.helper.ExamCacheTransferHelper;
-import cn.com.qmth.examcloud.web.baidu.BaiduClient;
-import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
-import cn.com.qmth.examcloud.web.facepp.FaceppClient;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import org.json.JSONException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Date;
-
-@Component
-public class FaceVerifyService {
-
-    private static final Logger log = LoggerFactory.getLogger(FaceVerifyService.class);
-
-    @Autowired
-    private ExamCaptureQueueRepo examCaptureQueueRepo;
-
-    @Autowired
-    private ExamCaptureService examCaptureService;
-
-    @Autowired
-    private ExamCaptureQueueService examCaptureQueueService;
-
-    @Autowired
-    private ExamRecordDataService examRecordDataService;
-
-    /**
-     * 处理单个考试抓拍照片数据
-     * 对图片进行人脸对比
-     */
-    @Deprecated
-    @Transactional
-    public void disposeFaceCompare(ExamCaptureQueueInfo examCaptureQueue) throws JSONException {
-        //将队列记录修改为处理中
-        examCaptureQueueRepo.updateExamCaptureQueueStatusWithProcessing(examCaptureQueue.getId());
-        examCaptureQueue.setFaceCompareStartTime(System.currentTimeMillis());
-
-        //facepp超时最大重试次数
-        int maxRetryTimes = PropertyHolder.getInt("facepp.compare.timeOut.maxRetryTimes", 3);
-        boolean retry = false;
-        JSONObject faceCompareResult;
-        //人脸比对超时次数
-        int faceCompareTimeOutTimes = 0;
-        do {
-            retry = false;
-
-            //仅用于日志时间计算
-            long startTime = System.currentTimeMillis();
-            log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对开始...");
-
-            //调用face++API执行人脸比对,得到返回结果
-            JsonHttpResponseHolder jsonHttpResponseHolder = null;
-            try {
-                jsonHttpResponseHolder = FaceppClient.getClient().
-                        compareWithTokenAndImageUrl(examCaptureQueue.getBaseFaceToken(),
-                                FileStorageUtil.realPath(examCaptureQueue.getFileUrl()),
-                                FileStorageUtil.realPathBackup(examCaptureQueue.getFileUrl()));
-
-                faceCompareResult = jsonHttpResponseHolder.getRespBody();
-
-            } catch (StatusException e) {
-                //如果错误码是801,802,803直接结束,不重试
-                if (e.getCode().equals("801") || e.getCode().equals("802") || e.getCode().equals("803")) {
-                    examCaptureQueue.setFaceCompareResult(e.getDesc());
-                    examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-
-                    log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对无法处理的图片地址,保存人脸检测最终结果并删除队列,errMsg=" + e.getDesc());
-                    return;
-                }
-                throw e;
-            }
-
-            if (log.isDebugEnabled()) {
-                log.debug("[DISPOSE_FACE_COMPARE] 调用face++API执行人脸比对,得到返回结果faceCompareResult:" + faceCompareResult);
-            }
-            examCaptureQueue.setFaceCompareResult(faceCompareResult.toString());
-
-            //人脸比对出错的处理
-            if (faceCompareResult.containsKey(Constants.ERROR_MSG)) {
-                String errMsg = faceCompareResult.getString(Constants.ERROR_MSG);
-
-                //如果API并发次数超过上限,则保存错误信息到队列,并抛出异常,用于协调满载队列线程
-                if (errMsg.contains(Constants.FACE_COMPARE_CONCURRENCY_LIMIT_EXCEEDED)) {
-
-                    log.error("[FaceCompareQueue] FacePlusPlus_QPS_CONCURRENCY_LIMITED");
-
-                    examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
-                            "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceCompareResult.toString(),
-                            ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
-
-                    throw new StatusException(Constants.FACE_COMPARE_CONCURRENCY_LIMIT_EXCEEDED, "face++ API接口超过最大并发次数");
-                }
-
-                //face++无需重试的错误信息
-                SysPropertyCacheBean objNotRetryErrMsg = CacheHelper.getSysProperty("facePlusPlus.faceCompare.notRetry.errMsg");
-                if (!objNotRetryErrMsg.getHasValue()) {
-                    throw new StatusException("100001", "未找到face++人脸比对错误消息的相关配置");
-                }
-                String objNotRetryErrMsgs = objNotRetryErrMsg.getValue().toString();
-                String[] notRetryErrMsgsArr = objNotRetryErrMsgs.split(",");
-                for (int i = 0; i < notRetryErrMsgsArr.length; i++) {
-                    //如果是配置中的无法处理的图片,则保存人脸检测最终结果并删除队列
-                    if (errMsg.contains(notRetryErrMsgsArr[i])) {
-                        examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-
-                        log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对无法处理的图片,保存人脸检测最终结果并删除队列,errMsg=" + errMsg);
-
-                        return;
-                    }
-                }
-
-                //超时错误特殊处理,重试3次后
-                if (errMsg.contains(Constants.FACE_COMPARE_IMAGE_DOWNLOAD_TIMEOUT)) {
-                    faceCompareTimeOutTimes++;
-
-                    log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对超时,将进行第" + faceCompareTimeOutTimes + "次重试");
-
-                    //如果没有达到最大重试次数,则继续重试
-                    if (faceCompareTimeOutTimes < maxRetryTimes) {
-                        retry = true;
-                        continue;
-                    }
-                    //超过最大重试次数,则直接保存最终结果
-                    examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-
-                    log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对超过最大检测次数:" + maxRetryTimes + ",停止重试,直接保存最终结果");
-                    return;
-                }
-
-                log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对出现错误,即将重试,errMsg:" + errMsg);
-                // 其它错误类型,保存错误信息到队列中,待自动重新服务处理
-                examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
-                        "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceCompareResult.toString(),
-                        ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED);
-                FaceVerifyCounter.increaseFaceCompareFailedCount();//增加错误次数
-                log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对出现错误,增加错误次数后failedCount:" +
-                        FaceVerifyCounter.getFaceCompareFailedCount() + ",totalCount=" +
-                        FaceVerifyCounter.getFaceCompareCount());
-            }
-            //人脸比对没有出错的情况
-            else {
-                //face++的结果检测到人脸,才执行百度活体检测
-                if (faceCompareResult.containsKey("confidence")) {
-                    examCaptureQueue.setPass(calculateFaceCompareIsPass(faceCompareResult));
-                    examCaptureQueue.setStranger(calculateFaceCompareIsStranger(examCaptureQueue.getExamRecordDataId(),
-                            examCaptureQueue.getStudentId(), faceCompareResult));
-                    //更新队列状态为face++比对完成
-                    examCaptureQueue.setStatus(ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_COMPLETE);
-                    disposeFaceCompareSuccessful(examCaptureQueue);
-
-                    log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对完成,即将进行百度活体检测,耗时:" + (System.currentTimeMillis() - startTime) + " ms");
-                }
-                //face++ 没有检测到人脸,直接保存人脸检测最终结果并删除队列
-                else {
-                    examCaptureQueue.setPass(false);
-                    examCaptureQueue.setStranger(false);
-                    examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-
-                    log.debug("[DISPOSE_FACE_COMPARE] face++人脸比对完成,且未检测到人脸,耗时:" + (System.currentTimeMillis() - startTime) + " ms");
-                }
-            }
-        } while (retry);
-    }
-
-    /**
-     * 对照片进行百度活体检测
-     *
-     * @param examCaptureQueue 抓拍照片队列表
-     */
-    @Deprecated
-    @Transactional
-    public void disposeBaiDuFaceLiveness(ExamCaptureQueueInfo examCaptureQueue) {
-        //活体检测超时次数
-        int facelivenessTimeOutTimes = 0;
-        //百度活检超时最大重试次数
-        int maxRetryTimes = PropertyHolder.getInt("baidu.faceliveness.timeOut.maxRetryTimes", 3);
-        boolean retry = false;
-        JSONObject faceLivenessResultJson;
-        do {
-            retry = false;
-
-            //仅用于日志时间计算
-            long startTime = System.currentTimeMillis();
-            log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测开始...");
-
-            //获取百度活检结果
-            JsonHttpResponseHolder jsonHttpResponseHolder = null;
-            try {
-                jsonHttpResponseHolder = BaiduClient.getClient().
-                        verifyFaceLiveness(FileStorageUtil.realPath(examCaptureQueue.getFileUrl()),
-                                FileStorageUtil.realPathBackup(examCaptureQueue.getFileUrl()));
-                faceLivenessResultJson = jsonHttpResponseHolder.getRespBody();
-            } catch (StatusException e) {
-                //如果错误码是901,902,903直接结束,不重试
-                if (e.getCode().equals("901") || e.getCode().equals("902") || e.getCode().equals("903")) {
-                    examCaptureQueue.setFacelivenessResult(e.getDesc());
-                    examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-
-                    log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活检无法处理的图片地址,保存人脸检测最终结果并删除队列,errMsg=" + e.getDesc());
-                    return;
-                }
-                throw e;
-            }
-            //            faceLivenessResultJson = faceLivenessService.getBaiduFaceLivenessResultJson(examCaptureQueue.getFileUrl());
-
-            //如果百度活体检测执行失败,调用队列失败处理,程序退出,失败的数据,后续会有自动服务重新处理
-            if (faceLivenessResultJson.containsKey(Constants.BAIDU_ERROR_CODE) &&
-                    !faceLivenessResultJson.getString(Constants.BAIDU_ERROR_CODE).equals(Constants.BAIDU_SUCCESS_ERROR_CODE_VALUE)) {
-                String errCode = faceLivenessResultJson.getString(Constants.BAIDU_ERROR_CODE);
-
-                //如果API并发次数超过上限,则保存错误信息到队列,并抛出异常,用于协调满载队列线程
-                if (errCode.equals(Constants.BAIDU_FACELIVENESS_QPS_LIMIT_EXCEEDED_CODE)) {
-                    log.error("[FaceLivenessQueue] Baidu_QPS_CONCURRENCY_LIMITED");
-
-                    examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
-                            "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceLivenessResultJson.toString(),
-                            ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED);
-
-                    throw new StatusException(Constants.BAIDU_FACELIVENESS_QPS_LIMIT_EXCEEDED_CODE, "百度在线活体API接口超过最大并发次数");
-                }
-
-                //百度无需重试的错误信息
-                SysPropertyCacheBean objNotRetryErrMsg = CacheHelper.getSysProperty("baidu.faceLiveness.notRetry.errCode");
-                if (!objNotRetryErrMsg.getHasValue()) {
-                    throw new StatusException("100002", "未找到百度活体检测错误代码的相关配置");
-                }
-                String objNotRetryErrMsgs = objNotRetryErrMsg.getValue().toString();
-                String[] notRetryErrMsgsArr = objNotRetryErrMsgs.split(",");
-                for (int i = 0; i < notRetryErrMsgsArr.length; i++) {
-                    //如果是配置中的无法处理的图片,则保存人脸检测最终结果并删除队列
-                    if (errCode.equals(notRetryErrMsgsArr[i])) {
-                        log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测,无法处理的图片,将保存人脸检测最终结果并删除队列,errCode=" + errCode);
-
-                        examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-                        return;
-                    }
-                }
-
-                //超时错误特殊处理,重试3次后
-                if (errCode.equals(Constants.BAIDU_FACELIVENESS_CONNECTION_OR_READ_DATA_TIME_OUT_CODE)) {
-                    facelivenessTimeOutTimes++;
-
-                    log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测超时,将进行第" + facelivenessTimeOutTimes + "次重试");
-
-                    //如果没有达到最大重试次数,则继续重试
-                    if (facelivenessTimeOutTimes < maxRetryTimes) {
-                        retry = true;
-                        continue;
-                    }
-
-                    //超过最大重试次数,则直接保存最终结果
-                    examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-
-                    log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测超过最大检测次数:" + maxRetryTimes + ",停止重试,直接保存最终结果");
-                    return;
-                }
-
-                log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测出现错误,即将重试,错误码:" + errCode);
-                // 其它错误类型,保存错误信息到队列中,待自动重新服务处理
-                examCaptureQueueService.saveExamCaptureQueueEntityByFailed(examCaptureQueue.getId(),
-                        "SatusCode:" + jsonHttpResponseHolder.getStatusCode() + " | " + faceLivenessResultJson.toString(), ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED);
-                FaceVerifyCounter.increaseFaceLivenessDetectFailedCount();//增加错误次数
-                log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测出现错误,增加错误次数后failedCount:" + FaceVerifyCounter.getFaceLivenessDetectFailedCount());
-            }
-            //百度活体检测成功,则保存最终检测结果,并删除临时的图片处理队列
-            else {
-                examCaptureQueue.setFacelivenessResult(faceLivenessResultJson.toString());
-                examCaptureService.saveExamCaptureAndDeleteQueue(examCaptureQueue);
-
-                log.debug("[DISPOSE_BAIDUFACELIVENESS] 百度活体检测完成,耗时:" + (System.currentTimeMillis() - startTime) + " ms");
-            }
-        } while (retry);
-    }
-
-    //人脸比较成功时的处理
-    private void disposeFaceCompareSuccessful(ExamCaptureQueueInfo examCaptureQueueInfo) {
-        examCaptureQueueRepo.saveExamCaptureQueueEntityBySuccessful(examCaptureQueueInfo.getId(),
-                examCaptureQueueInfo.getPass(), examCaptureQueueInfo.getStranger(),
-                examCaptureQueueInfo.getStatus().toString(), examCaptureQueueInfo.getFaceCompareResult(),
-                examCaptureQueueInfo.getFaceCompareStartTime(), new Date());
-    }
-
-    /**
-     * 校验是否有陌生人脸
-     */
-    private boolean calculateFaceCompareIsStranger(Long examRecordDataId, Long studentId, JSONObject jsonObject) {
-        JSONArray face2Array = jsonObject.getJSONArray("faces2");
-        //添加是否有陌生人开关功能
-        ExamRecordData examRecordDataCache = examRecordDataService.getExamRecordDataCache(examRecordDataId);
-        //默认开启了陌生人检测
-        String isStrangerEnableStr = "true";
-        if (examRecordDataCache != null) {
-            isStrangerEnableStr = ExamCacheTransferHelper.getCachedExamProperty(examRecordDataCache.getExamId(),
-                    studentId,
-                    ExamProperties.IS_STRANGER_ENABLE.name()).getValue();
-        }
-        boolean isStranger;
-        // 如果开启了陌生人检测才记录陌生人数据,否则认为没有陌生人
-        if (Constants.isTrue.equals(isStrangerEnableStr)) {
-            isStranger = face2Array.size() > 1;//是否有陌生人
-        } else {
-            isStranger = false;
-        }
-        return isStranger;
-    }
-
-    /**
-     * 计算人脸比对是否通过
-     */
-    private boolean calculateFaceCompareIsPass(JSONObject jsonObject) {
-        //比对结果置信度,范围 [0,100],小数点后3位有效数字,数字越大表示两个人脸越可能是同一个人。
-        double confidence = jsonObject.getDouble("confidence");
-        //一组用于参考的置信度阈值,包含以下三个字段。每个字段的值为一个 [0,100] 的浮点数,小数点后 3 位有效数字。
-        //1e-3:误识率为千分之一的置信度阈值;
-        //1e-4:误识率为万分之一的置信度阈值;
-        //1e-5:误识率为十万分之一的置信度阈值;
-        JSONObject thresholdsJsonObject = jsonObject.getJSONObject("thresholds");
-        double le4 = thresholdsJsonObject.getDouble("1e-4");
-        //如果置信值低于“千分之一”阈值则不建议认为是同一个人;如果置信值超过“十万分之一”阈值,则是同一个人的几率非常高。
-        return confidence >= le4;
-    }
-
-}

+ 2 - 1
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamBossServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.examcloud.core.oe.task.service.impl;
 
+import cn.com.qmth.examcloud.core.oe.student.base.OeConstants;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamBossService;
 import cn.com.qmth.examcloud.support.examing.ExamBoss;
 import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
@@ -22,7 +23,7 @@ public class ExamBossServiceImpl implements ExamBossService {
     @Override
     public void saveExamBoss(Long examStudentId, ExamBoss eb) {
         String key = RedisKeyHelper.getBuilder().examBossKey(examStudentId);
-        redisClient.set(key, eb, 2592000);
+        redisClient.set(key, eb, OeConstants.TIME_OUT_7_DAY);
     }
 
     @Override

+ 15 - 13
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamCaptureQueueServiceImpl.java

@@ -33,7 +33,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Example;
 import org.springframework.stereotype.Service;
 
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 
@@ -107,8 +106,23 @@ public class ExamCaptureQueueServiceImpl implements ExamCaptureQueueService {
 
             // 将抓拍照图片转成Base64格式
             String capturePhotoUrl = ossClient.valueOfOssFilePath(FileStorageUtil.realPath(queue.getFileUrl()));
+            if (StringUtils.isBlank(capturePhotoUrl)) {
+                // 删除错误无效数据
+                log.warn("人脸抓拍图片地址错误!examRecordDataId:{} queueId:{} imgUrl:{}",
+                        queue.getExamRecordDataId(), queue.getId(), queue.getFileUrl());
+                examCaptureQueueRepo.deleteById(queue.getId());
+                continue;
+            }
+
             byte[] capturePhotoBytes = ossClient.download(capturePhotoUrl);
             ImageParm capturePhoto = new ImageBase64Parm(Base64.encodeBase64String(capturePhotoBytes));
+            if (StringUtils.isBlank(capturePhoto.value())) {
+                // 删除错误无效数据
+                log.warn("人脸抓拍图片为空白!examRecordDataId:{} queueId:{} imgUrl:{}",
+                        queue.getExamRecordDataId(), queue.getId(), queue.getFileUrl());
+                examCaptureQueueRepo.deleteById(queue.getId());
+                continue;
+            }
 
             String extMsg = "";
             boolean errFace = false;
@@ -251,16 +265,4 @@ public class ExamCaptureQueueServiceImpl implements ExamCaptureQueueService {
         log.info("-->ExamCaptureQueue clear... examRecordDataId:{} fileName:{}", queue.getExamRecordDataId(), queue.getFileName());
     }
 
-    @Deprecated
-    @Override
-    public boolean saveExamCaptureQueueEntityByFailed(Long captureQueueId, String errorMsg, ExamCaptureQueueStatus status) {
-        try {
-            examCaptureQueueRepo.saveExamCaptureQueueEntityByFailed(captureQueueId, errorMsg, status.toString(), "000000", new Date());
-            return true;
-        } catch (Exception e) {
-            log.error("保存照片队列处理失败数据时出现异常!{}", e.getMessage());
-            return false;
-        }
-    }
-
 }

+ 0 - 26
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamCaptureServiceImpl.java

@@ -22,9 +22,7 @@ import org.json.JSONException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Example;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -58,30 +56,6 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
     @Autowired
     private RedisClient redisClient;
 
-    /**
-     * 保存人脸检测最终结果并删除队列
-     *
-     * @param examCapture      抓拍照片最终检测最终结果实体
-     * @param examCaptureQueue 抓拍照片队列表
-     */
-    @Override
-    @Transactional
-    public void saveExamCaptureAndDeleteQueue(ExamCaptureQueueInfo examCaptureQueue) {
-        ExamCaptureEntity examCapture = getExamCaptureFromQueue(examCaptureQueue);
-
-        //同一考试记录下如果有重复的照片,则直接跳过
-        ExamCaptureEntity query = new ExamCaptureEntity();
-        query.setExamRecordDataId(examCapture.getExamRecordDataId());
-        query.setFileName(examCapture.getFileName());
-        Example<ExamCaptureEntity> example = Example.of(query);
-        //照片处理结果中如果已存在,则以已有的数据为准
-        if (!examCaptureRepo.exists(example)) {
-            examCaptureRepo.save(examCapture);
-        }
-        //删除队列中的记录
-        examCaptureQueueRepo.deleteById(examCaptureQueue.getId());
-    }
-
     /**
      * 计算人脸检测结果
      * 相片数=0,系统判断为违纪,自动审核

+ 4 - 2
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamRecordDataServiceImpl.java

@@ -6,6 +6,7 @@ import cn.com.qmth.examcloud.core.oe.student.api.request.CalcExamScoreReq;
 import cn.com.qmth.examcloud.core.oe.student.api.request.CalcFaceBiopsyResultReq;
 import cn.com.qmth.examcloud.core.oe.student.api.response.CalcExamScoreResp;
 import cn.com.qmth.examcloud.core.oe.student.api.response.CalcFaceBiopsyResultResp;
+import cn.com.qmth.examcloud.core.oe.student.base.OeConstants;
 import cn.com.qmth.examcloud.core.oe.student.dao.ExamCaptureQueueRepo;
 import cn.com.qmth.examcloud.core.oe.student.dao.ExamRecordDataRepo;
 import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamRecordDataEntity;
@@ -13,6 +14,7 @@ import cn.com.qmth.examcloud.core.oe.task.service.ExamCaptureQueueService;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamCaptureService;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
 import cn.com.qmth.examcloud.core.oe.task.service.bean.CalculateFaceCheckResultInfo;
+import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.support.Constants;
 import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
 import cn.com.qmth.examcloud.support.enums.HandInExamType;
@@ -73,7 +75,7 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
     @Override
     public void saveExamRecordDataCache(Long examRecordDataId, ExamRecordData data) {
         String key = RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId);
-        redisClient.set(key, data, 2592000);
+        redisClient.set(key, data, OeConstants.TIME_OUT_7_DAY);
     }
 
     @Override
@@ -128,7 +130,7 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
             // 判断是否存在未处理的抓拍照片比对
             int queueSize = examCaptureQueueRepo.countByExamRecordDataId(examRecordData.getId());
             if (queueSize > 0) {
-                final String lockKey = Constants.FACE_COMPARE_LOCK_PREFIX + examRecordData.getId();
+                final String lockKey = CacheConstants.LOCK_FACE_COMPARE + examRecordData.getId();
                 try {
                     SequenceLockHelper.getLockSimple(lockKey);
 

+ 0 - 16
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamSyncCaptureServiceImpl.java

@@ -1,16 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.impl;
-
-import cn.com.qmth.examcloud.core.oe.task.service.ExamSyncCaptureService;
-import org.springframework.stereotype.Service;
-
-/**
- * @Description 同步抓拍照片
- * @Author lideyin
- * @Date 2019/12/6 16:20
- * @Version 1.0
- */
-@SuppressWarnings("ALL")
-@Service("examSyncCaptureService")
-public class ExamSyncCaptureServiceImpl implements ExamSyncCaptureService {
-
-}

+ 2 - 1
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/impl/ExamingSessionServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.examcloud.core.oe.task.service.impl;
 
+import cn.com.qmth.examcloud.core.oe.student.base.OeConstants;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamingSessionService;
 import cn.com.qmth.examcloud.support.examing.ExamingSession;
 import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
@@ -22,7 +23,7 @@ public class ExamingSessionServiceImpl implements ExamingSessionService {
     @Override
     public void saveExamingSession(Long studentId, ExamingSession examingSession) {
         String key = RedisKeyHelper.getBuilder().examingSessionKey(studentId);
-        redisClient.set(key, examingSession, 2592000);
+        redisClient.set(key, examingSession, OeConstants.TIME_OUT_7_DAY);
     }
 
     @Override

+ 31 - 6
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/AfterHandInExamJobHandler.java

@@ -3,7 +3,7 @@ package cn.com.qmth.examcloud.core.oe.task.service.job;
 import cn.com.qmth.examcloud.core.oe.student.dao.ExamRecordDataRepo;
 import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamRecordDataEntity;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
-import cn.com.qmth.examcloud.support.Constants;
+import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
 import cn.com.qmth.examcloud.support.examing.ExamRecordData;
 import cn.com.qmth.examcloud.web.exception.SequenceLockException;
@@ -50,7 +50,7 @@ public class AfterHandInExamJobHandler {
 
             int curTodoIndex = 0;
             for (ExamRecordDataEntity data : todoList) {
-                final String lockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + data.getStudentId();
+                final String lockKey = CacheConstants.LOCK_EXAM_CONTROL + data.getStudentId();
                 try {
                     SequenceLockHelper.getLockSimple(lockKey);
 
@@ -85,7 +85,7 @@ public class AfterHandInExamJobHandler {
     private void handler(Long examRecordDataId, int curTodoSize, int curTodoIndex) throws Exception {
         ExamRecordData examRecordDataCache = examRecordDataService.getExamRecordDataCache(examRecordDataId);
         if (examRecordDataCache == null) {
-            log.warn("redisKey OE_ERD:{} value not exist, Set examRecordStatus=EXAM_ERROR", examRecordDataId);
+            log.warn("redisKey {}{} value not exist, Set examRecordStatus=EXAM_ERROR", CacheConstants.CACHE_OE_RECORD, examRecordDataId);
             examRecordDataRepo.updateExamRecordStatusById(ExamRecordStatus.EXAM_ERROR, new Date(), examRecordDataId);
             return;
         }
@@ -101,9 +101,11 @@ public class AfterHandInExamJobHandler {
 
         // 交卷时间(手动交卷取endTime,自动交卷取cleanTime)
         Date handInTime = examRecordDataCache.getEndTime() != null ? examRecordDataCache.getEndTime() : examRecordDataCache.getCleanTime();
-        long diff = (System.currentTimeMillis() - handInTime.getTime()) / 1000;
-        log.warn("交卷类型:{} 交卷距离现在已{}秒, examRecordDataId:{}, studentId:{}, curTodoSize:{}, curTodoIndex:{}",
-                examRecordDataCache.getHandInExamType(), diff, examRecordDataId, examRecordDataCache.getStudentId(), curTodoSize, curTodoIndex);
+        long diffSecond = (System.currentTimeMillis() - handInTime.getTime()) / 1000L;
+        String warnMsg = (diffSecond / 3600L) >= 12L ? "【警告】交卷处理超过12小时!!!" : "";
+        log.warn("【{}】交卷距离现在已:{}, examRecordDataId:{}, studentId:{}, curTodoSize:{}, curTodoIndex:{} {}",
+                examRecordDataCache.getHandInExamType(), this.diff(diffSecond), examRecordDataId,
+                examRecordDataCache.getStudentId(), curTodoSize, curTodoIndex, warnMsg);
 
         try {
             // 处理人脸、活体、违纪、算分等
@@ -118,4 +120,27 @@ public class AfterHandInExamJobHandler {
         }
     }
 
+    /**
+     * 将相差多少秒 格式化为:xx小时xx分xx秒
+     */
+    private String diff(long diffSecond) {
+        long hour = diffSecond / 3600;
+        long minute = diffSecond / 60 - hour * 60;
+        long second = diffSecond - hour * 3600 - minute * 60;
+        StringBuilder result = new StringBuilder();
+        if (hour > 0) {
+            result.append(hour).append("小时");
+            result.append(minute).append("分");
+            result.append(second).append("秒");
+            return result.toString();
+        }
+        if (minute > 0) {
+            result.append(minute).append("分");
+            result.append(second).append("秒");
+            return result.toString();
+        }
+        result.append(second).append("秒");
+        return result.toString();
+    }
+
 }

+ 8 - 6
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/BeforeHandInExamJobHandler.java

@@ -6,12 +6,13 @@ import cn.com.qmth.examcloud.core.oe.student.dao.ExamRecordDataRepo;
 import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamRecordDataEntity;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamingSessionService;
-import cn.com.qmth.examcloud.support.Constants;
+import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
 import cn.com.qmth.examcloud.support.enums.HandInExamType;
 import cn.com.qmth.examcloud.support.examing.ExamRecordData;
 import cn.com.qmth.examcloud.support.examing.ExamingActivityTime;
 import cn.com.qmth.examcloud.support.examing.ExamingSession;
+import cn.com.qmth.examcloud.support.examing.ExamingStatus;
 import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
 import cn.com.qmth.examcloud.web.exception.SequenceLockException;
 import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
@@ -66,7 +67,7 @@ public class BeforeHandInExamJobHandler {
             }
 
             for (ExamRecordDataEntity data : todoList) {
-                final String lockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + data.getStudentId();
+                final String lockKey = CacheConstants.LOCK_EXAM_CONTROL + data.getStudentId();
                 try {
                     SequenceLockHelper.getLockSimple(lockKey);
 
@@ -100,7 +101,7 @@ public class BeforeHandInExamJobHandler {
     private void handler(Long examRecordDataId) throws Exception {
         ExamRecordData examRecordDataCache = examRecordDataService.getExamRecordDataCache(examRecordDataId);
         if (examRecordDataCache == null) {
-            log.warn("redisKey OE_ERD:{} value not exist, Set examRecordStatus=EXAM_ERROR", examRecordDataId);
+            log.warn("redisKey {}{} value not exist, Set examRecordStatus=EXAM_ERROR", CacheConstants.CACHE_OE_RECORD, examRecordDataId);
             examRecordDataRepo.updateExamRecordStatusById(ExamRecordStatus.EXAM_ERROR, new Date(), examRecordDataId);
             return;
         }
@@ -121,9 +122,10 @@ public class BeforeHandInExamJobHandler {
         }
 
         ExamingSession examingSession = examingSessionService.getExamingSession(examRecordDataCache.getStudentId());
-        if (examingSession == null) {
+        if (examingSession == null || ExamingStatus.INFORMAL.equals(examingSession.getExamingStatus())) {
             // 考试会话不存在,则自动交卷
-            log.warn("redisKey OE_SESSION:{} value not exist, do autoHandInExam, examRecordDataId:{}", examRecordDataCache.getStudentId(), examRecordDataId);
+            log.warn("redisKey {}{} value not exist, do autoHandInExam, examRecordDataId:{}",
+                    CacheConstants.CACHE_OE_SESSION, examRecordDataCache.getStudentId(), examRecordDataId);
             this.autoHandInExam(examRecordDataCache);
             return;
         }
@@ -153,7 +155,7 @@ public class BeforeHandInExamJobHandler {
 
         long activeTime;
         if (activeTimeCache == null) {
-            log.warn("redisKey OE_ACTIVE:{} value not exist, examReconnectTime:{} minutes",
+            log.warn("redisKey {}{} value not exist, examReconnectTime:{} minutes", CacheConstants.CACHE_OE_ACTIVE,
                     examingSession.getExamRecordDataId(), examingSession.getExamReconnectTime());
             activeTime = System.currentTimeMillis();
         } else {

+ 2 - 2
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/FaceVerifyJobHandler.java

@@ -2,7 +2,7 @@ package cn.com.qmth.examcloud.core.oe.task.service.job;
 
 import cn.com.qmth.examcloud.core.oe.student.dao.ExamCaptureQueueRepo;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamCaptureQueueService;
-import cn.com.qmth.examcloud.support.Constants;
+import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.web.exception.SequenceLockException;
 import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
 import org.apache.commons.collections4.CollectionUtils;
@@ -37,7 +37,7 @@ public class FaceVerifyJobHandler {
         }
 
         for (Long examRecordDataId : todoExamRecordDataIds) {
-            final String lockKey = Constants.FACE_COMPARE_LOCK_PREFIX + examRecordDataId;
+            final String lockKey = CacheConstants.LOCK_FACE_COMPARE + examRecordDataId;
             try {
                 SequenceLockHelper.getLockSimple(lockKey);
 

+ 10 - 8
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/job/SyncExamRecordDataJobHandler.java

@@ -6,12 +6,14 @@ import cn.com.qmth.examcloud.core.oe.admin.api.bean.ExamCaptureBean;
 import cn.com.qmth.examcloud.core.oe.admin.api.bean.ExamSyncCaptureBean;
 import cn.com.qmth.examcloud.core.oe.admin.api.request.AddExamScoreNoticeQueueReq;
 import cn.com.qmth.examcloud.core.oe.admin.api.request.SyncExamDataReq;
+import cn.com.qmth.examcloud.core.oe.student.base.OeConstants;
 import cn.com.qmth.examcloud.core.oe.student.dao.ExamRecordDataRepo;
 import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamRecordDataEntity;
 import cn.com.qmth.examcloud.core.oe.task.service.CommonService;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamBossService;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
 import cn.com.qmth.examcloud.core.oe.task.service.ExamingSessionService;
+import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.support.Constants;
 import cn.com.qmth.examcloud.support.enums.ExamProperties;
 import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
@@ -85,7 +87,7 @@ public class SyncExamRecordDataJobHandler {
             }
 
             for (ExamRecordDataEntity data : todoList) {
-                final String lockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + data.getStudentId();
+                final String lockKey = CacheConstants.LOCK_EXAM_CONTROL + data.getStudentId();
                 try {
                     SequenceLockHelper.getLockSimple(lockKey);
 
@@ -119,7 +121,7 @@ public class SyncExamRecordDataJobHandler {
     private void handler(Long examRecordDataId) throws Exception {
         ExamRecordData examRecordDataCache = examRecordDataService.getExamRecordDataCache(examRecordDataId);
         if (examRecordDataCache == null) {
-            log.warn("redisKey OE_ERD:{} value not exist, Set examRecordStatus=EXAM_ERROR", examRecordDataId);
+            log.warn("redisKey {}{} value not exist, Set examRecordStatus=EXAM_ERROR", CacheConstants.CACHE_OE_RECORD, examRecordDataId);
             examRecordDataRepo.updateExamRecordStatusById(ExamRecordStatus.EXAM_ERROR, new Date(), examRecordDataId);
             return;
         }
@@ -254,7 +256,7 @@ public class SyncExamRecordDataJobHandler {
                 if (CollectionUtils.isNotEmpty(examRecordDataIds)) {
                     examRecordDataIds.removeIf(e -> examRecordDataId.equals(e));
                     examBoss.setExamRecordDataIds(examRecordDataIds);
-                    redisClient.set(examBossKey, examBoss, 2592000);
+                    redisClient.set(examBossKey, examBoss, OeConstants.TIME_OUT_7_DAY);
                 }
             }
         }
@@ -265,9 +267,9 @@ public class SyncExamRecordDataJobHandler {
         // 清除心跳缓存
         redisClient.delete(RedisKeyHelper.getBuilder().examingHeartbeatKey(examRecordDataId));
 
-        // 清除当前学生的考试会话缓存
+        // 清除当前学生的考试会话缓存(交卷后,正好又重新开考“预处理阶段”时examingSession的examRecordDataId会为空!)
         ExamingSession examingSession = examingSessionService.getExamingSession(studentId);
-        if (examingSession != null && examingSession.getExamRecordDataId().equals(examRecordDataId)) {
+        if (examingSession != null && examRecordDataId.equals(examingSession.getExamRecordDataId())) {
             examingSessionService.deleteExamingSession(studentId);
         }
 
@@ -282,14 +284,14 @@ public class SyncExamRecordDataJobHandler {
         redisClient.delete(RedisKeyHelper.getBuilder().studentPaperKey(examRecordDataId));
 
         // 清除“违纪非法请求数据”缓存
-        redisClient.delete(Constants.OE_DISCIPLINE_ILLEGAL_DATA + examRecordDataId);
+        redisClient.delete(CacheConstants.CACHE_OE_DISCIPLINE_ILLEGAL_DATA + examRecordDataId);
 
         // 清除“违纪非法考生端应用”缓存
-        redisClient.delete(Constants.OE_DISCIPLINE_ILLEGAL_CLIENT + examRecordDataId);
+        redisClient.delete(CacheConstants.CACHE_OE_DISCIPLINE_ILLEGAL_CLIENT + examRecordDataId);
 
         // 最后设置过期“当前考试记录”缓存
         final String examRecordDataKey = RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId);
-        redisClient.expire(examRecordDataKey, 180, TimeUnit.SECONDS);
+        redisClient.expire(examRecordDataKey, OeConstants.TIME_OUT_5_MINUTE, TimeUnit.SECONDS);
 
         log.warn("clearUnusefulCacheData finished, examRecordDataId:{}, studentId:{}", examRecordDataId, studentId);
     }

+ 0 - 123
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/AfterHandInExamExecutor.java

@@ -1,123 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.pipeline;
-
-import cn.com.qmth.examcloud.commons.helpers.KeyValuePair;
-import cn.com.qmth.examcloud.commons.helpers.ObjectHolder;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.NodeExecuter;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.TaskContext;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
-import cn.com.qmth.examcloud.support.Constants;
-import cn.com.qmth.examcloud.support.cache.CacheHelper;
-import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
-import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
-import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-/**
- * @Description 交卷后续处理执行器
- * @Author lideyin
- * @Date 2019/12/17 16:39
- * @Version 1.0
- */
-@Deprecated
-@Component
-public class AfterHandInExamExecutor implements NodeExecuter<Long, ExamRecordData, Long, ExamRecordData> {
-
-    @Autowired
-    private ExamRecordDataService examRecordDataService;
-
-    private static Long DEFAULT_MAX_PROCESS_SECONDS = 30L;
-
-    private static final Logger LOG = LoggerFactory.getLogger(AfterHandInExamExecutor.class);
-
-    /**
-     * 执行
-     *
-     * @param key
-     * @param examRecordData
-     * @param outList
-     * @param removable
-     * @param context
-     * @throws Exception
-     * @author WANGWEI
-     */
-    @Override
-    public void execute(Long key, ExamRecordData examRecordData,
-                        List<KeyValuePair<Long, ExamRecordData>> outList,
-                        ObjectHolder<Boolean> removable, TaskContext context) throws Exception {
-
-        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + examRecordData.getStudentId();
-
-        long st = System.currentTimeMillis();
-
-        try {
-            this.debugLog("enter executor...", examRecordData.getId());
-
-            //添加考试控制全局锁
-            SequenceLockHelper.getLockSimple(sequenceLockKey);
-
-            this.debugLog("get locker success...", examRecordData.getId());
-
-            //针对已交卷的数据进行交卷后续处理
-            if (examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_HAND_IN ||
-                    examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_AUTO_HAND_IN) {
-
-                this.debugLog("prepare to execute after hand in ...", examRecordData.getId());
-
-                SysPropertyCacheBean maxProcessSecondsProperty = CacheHelper.getSysProperty("oe.task.maxProcessSeconds");
-                //本节点最大处理时长
-                Long maxProcessSeconds;
-                if (maxProcessSecondsProperty.getHasValue()) {
-                    maxProcessSeconds = Long.valueOf(maxProcessSecondsProperty.getValue().toString());
-                } else {
-                    maxProcessSeconds = DEFAULT_MAX_PROCESS_SECONDS;
-                }
-
-                //交卷时间戳
-                Long handInTime = (examRecordData.getEndTime() == null
-                        ? examRecordData.getCleanTime()
-                        : examRecordData.getEndTime()).getTime();
-                Long times = System.currentTimeMillis() - handInTime;
-
-                //如果交卷后超过指定时长内仍未处理完成,则交给下一节点进行处理
-                if (times > maxProcessSeconds * 1000) {
-                    outList.add(new KeyValuePair<>(key, examRecordData));
-
-                    this.debugLog("not complete in time and will retry in next node...", examRecordData.getId());
-
-                    return;
-                }
-
-                examRecordData = examRecordDataService.processAfterHandInExam(examRecordData.getId());
-
-                outList.add(new KeyValuePair<>(key, examRecordData));
-
-                this.debugLog("after hand in success..", examRecordData.getId());
-
-                return;
-            }
-
-            //其它状态数据,直接交给下一步
-            outList.add(new KeyValuePair<>(key, examRecordData));
-
-            this.debugLog("current status is '" + examRecordData.getExamRecordStatus().name() +
-                    "'.do nothing and go to the next node...", examRecordData.getId());
-        } finally {
-            SequenceLockHelper.releaseLockSimple(sequenceLockKey);
-            this.debugLog("T999 HandInExamExecutor合计耗时:" +
-                    (System.currentTimeMillis() - st) + " ms", examRecordData.getId());
-        }
-    }
-
-    private void debugLog(String msg, Long examRecordDataId) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("[AFTER-HAND-IN-EXAM-EXECUTOR-" + examRecordDataId + "]:" + msg);
-        }
-    }
-
-}

+ 0 - 156
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/ClearExamDataCacheExecutor.java

@@ -1,156 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.pipeline;
-
-import cn.com.qmth.examcloud.commons.helpers.KeyValuePair;
-import cn.com.qmth.examcloud.commons.helpers.ObjectHolder;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.NodeExecuter;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.TaskContext;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamingSessionService;
-import cn.com.qmth.examcloud.support.Constants;
-import cn.com.qmth.examcloud.support.enums.SyncStatus;
-import cn.com.qmth.examcloud.support.examing.ExamBoss;
-import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.support.examing.ExamingSession;
-import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
-import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
-import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
-import cn.com.qmth.examcloud.web.redis.RedisClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @Description 清理考试记录缓存
- * @Author lideyin
- * @Date 2019/12/24 18:07
- * @Version 1.0
- */
-@Deprecated
-@Component
-public class ClearExamDataCacheExecutor implements NodeExecuter<Long, ExamRecordData, Long, ExamRecordData> {
-
-    @Autowired
-    private RedisClient redisClient;
-
-    private static final Logger LOG = LoggerFactory.getLogger(ClearExamDataCacheExecutor.class);
-
-    @Autowired
-    private ExamingSessionService examingSessionService;
-
-    /**
-     * 执行
-     *
-     * @param key
-     * @param examRecordData
-     * @param outList
-     * @param removable
-     * @param context
-     * @throws Exception
-     */
-    @Override
-    public void execute(Long key, ExamRecordData examRecordData,
-                        List<KeyValuePair<Long, ExamRecordData>> outList,
-                        ObjectHolder<Boolean> removable, TaskContext context) throws Exception {
-
-        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + examRecordData.getStudentId();
-
-        long st = System.currentTimeMillis();
-
-        try {
-            Long examRecordDataId = examRecordData.getId();
-            debugLog("enter executor...", examRecordDataId);
-
-            //添加考试控制全局锁
-            SequenceLockHelper.getLockSimple(sequenceLockKey);
-
-            debugLog("get locker success...", examRecordDataId);
-
-            //只有已同步成功的数据,才执行清理操作
-            if (SyncStatus.SYNCED == examRecordData.getSyncStatus()) {
-
-                //清除考试次数相关缓存
-                clearExamBoss(examRecordData.getExamStudentId(), examRecordDataId);
-
-                //清除学生最后活动时间缓存
-                redisClient.delete(RedisKeyHelper.getBuilder().examingActiveTimeKey(examRecordDataId));
-
-                //清除心跳缓存
-                redisClient.delete(RedisKeyHelper.getBuilder().examingHeartbeatKey(examRecordDataId));
-
-                //清除考试会话缓存
-                ExamingSession examingSession = examingSessionService.getExamingSession(examRecordData.getStudentId());
-                if (null != examingSession && examingSession.getExamRecordDataId().equals(examRecordDataId)) {
-                    String sessionKey = RedisKeyHelper.getBuilder().examingSessionKey(examRecordData.getStudentId());
-                    redisClient.delete(sessionKey);
-                    this.infoLog(String.format("清理交卷未删除的会话:%s", sessionKey), examRecordDataId);
-                }
-
-                //清除文件作答和普通作答记录缓存
-                Integer quesCount = examRecordData.getQuestionCount();
-                for (int i = 1; i <= quesCount; i++) {
-                    redisClient.delete(RedisKeyHelper.getBuilder().studentFileAnswerKey(examRecordDataId, i));
-                    redisClient.delete(RedisKeyHelper.getBuilder().studentAnswerKey(examRecordDataId, i));
-                }
-
-                //清除网考试卷结构
-                redisClient.delete(RedisKeyHelper.getBuilder().studentPaperKey(examRecordDataId));
-
-                //清除考试记录缓存(设置缓存的过期时间)
-                Long defaultExpiredSeconds = PropertyHolder.getLong("oe.student.cache.expiredSeconds", 180);//缓存默认过期时间
-                redisClient.expire(RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId),
-                        defaultExpiredSeconds, TimeUnit.SECONDS);
-
-                redisClient.delete(Constants.OE_DISCIPLINE_ILLEGAL_DATA + examRecordDataId);
-                redisClient.delete(Constants.OE_DISCIPLINE_ILLEGAL_CLIENT + examRecordDataId);
-
-                this.debugLog("all is over.", examRecordDataId);
-
-                return;
-            }
-
-            this.debugLog("current status is '" + examRecordData.getExamRecordStatus().name() +
-                    "'.may be redundant data.", examRecordDataId);
-
-        } finally {
-            SequenceLockHelper.releaseLockSimple(sequenceLockKey);
-            this.debugLog("T999 ClearExamDataCacheExecutor合计耗时:" +
-                    (System.currentTimeMillis() - st) + " ms", examRecordData.getId());
-        }
-    }
-
-    private void clearExamBoss(Long examStudentId, Long examRecordDataId) {
-        String examBossKey = RedisKeyHelper.getBuilder().examBossKey(examStudentId);
-        ExamBoss examBoss = redisClient.get(examBossKey, ExamBoss.class);
-        if (null != examBoss) {
-            //如果开考次数==考试完结次数,则删除考试基础信息缓存
-            if (examBoss.getStartCount() == examBoss.getEndCount()) {
-                redisClient.delete(examBossKey);
-            }
-            //如果examBoss未清除,则清除当前的考试记录id
-            else {
-                List<Long> examRecordDataIds = examBoss.getExamRecordDataIds();
-                if (null != examRecordDataIds && !examRecordDataIds.isEmpty()) {
-                    examRecordDataIds.removeIf(p -> examRecordDataId.equals(p));
-                    examBoss.setExamRecordDataIds(examRecordDataIds);
-                    redisClient.set(examBossKey, examBoss);
-                }
-            }
-        }
-    }
-
-    private void debugLog(String msg, Long examRecordDataId) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("[CLEAR-EXAM-DATA-CACHE-EXECUTOR-" + examRecordDataId + "]:" + msg);
-        }
-    }
-
-    private void infoLog(String msg, Long examRecordDataId) {
-        if (LOG.isInfoEnabled()) {
-            LOG.info("[CLEAR-EXAM-DATA-CACHE-EXECUTOR-" + examRecordDataId + "]:" + msg);
-        }
-    }
-
-}

+ 0 - 182
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/DataGainExamExecutor.java

@@ -1,182 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.pipeline;
-
-import cn.com.qmth.examcloud.commons.helpers.KeyValuePair;
-import cn.com.qmth.examcloud.commons.helpers.ObjectHolder;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.NodeExecuter;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.TaskContext;
-import cn.com.qmth.examcloud.core.oe.student.api.ExamRecordDataCloudService;
-import cn.com.qmth.examcloud.core.oe.student.api.request.GetExamRecordDataIdsReq;
-import cn.com.qmth.examcloud.core.oe.student.api.request.UpdateExamRecordDataBatchNumReq;
-import cn.com.qmth.examcloud.core.oe.student.api.request.UpdateExamRecordStatusReq;
-import cn.com.qmth.examcloud.core.oe.student.api.response.GetExamRecordDataIdsResp;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
-import cn.com.qmth.examcloud.core.oe.task.service.bean.RecordDataSyncRule;
-import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
-import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.jdbc.core.BeanPropertyRowMapper;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Component;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * @Description 获取待处理数据
- * @Author xt
- * @Date 2019/12/17 16:39
- * @Version 1.0
- */
-@Deprecated
-@Component
-public class DataGainExamExecutor implements NodeExecuter<Long, ExamRecordData, Long, ExamRecordData> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(DataGainExamExecutor.class);
-
-    private final static Integer batchSize = 200;
-
-    private final static Long batchNum = new Date().getTime();
-
-    @Autowired
-    private ExamRecordDataCloudService examRecordDataCloudService;
-
-    @Autowired
-    private ExamRecordDataService examRecordDataService;
-
-    @Value("${examcloud.record.data.sync.allowOrgList}")
-    private String recordDataSyncAllowOrgList;
-
-    @Value("${examcloud.record.data.sync.limitOrgList}")
-    private String recordDataSyncLimitOrgList;
-
-    @Autowired
-    private JdbcTemplate jdbcTemplate;
-
-    @Override
-    public void execute(Long key, ExamRecordData value, List<KeyValuePair<Long, ExamRecordData>> outList,
-                        ObjectHolder<Boolean> removable, TaskContext context) throws Exception {
-        RecordDataSyncRule syncRule = new RecordDataSyncRule(recordDataSyncAllowOrgList, recordDataSyncLimitOrgList);
-        LOG.warn(syncRule.toString());
-
-        LOG.info("开始获取数据");
-        Date start = new Date();
-        // 获取考试信息id
-        Long startId = 0l;
-        GetExamRecordDataIdsReq req = new GetExamRecordDataIdsReq();
-        req.setBatchNum(batchNum);
-        req.setSize(batchSize);
-
-        for (; ; ) {
-            req.setStartId(startId);
-            GetExamRecordDataIdsResp res = null;
-
-            try {
-                res = examRecordDataCloudService.getExamRecordDataIds(req);
-            } catch (Exception e) {
-                Date end = new Date();
-                long times = end.getTime() - start.getTime();
-                LOG.error("获取数据库中考试信息出错 startId:" + startId + " 获取数据条数:" + outList.size() + " 耗时:" + times + "ms", e);
-                return;
-            }
-
-            List<Long> ids = res.getExamRecordDataIds();
-            if (ids == null || ids.size() == 0) {
-                Date end = new Date();
-                long times = end.getTime() - start.getTime();
-                LOG.info("获取数据条数:" + outList.size() + " 耗时:" + times + "ms");
-                return;
-            }
-
-            List<KeyValuePair<Long, ExamRecordData>> tempList = new ArrayList<>();
-            List<Long> newExamRecordDataIds = new ArrayList<>();
-
-            for (Long id : ids) {
-                // 根据id获取考试信息缓存
-                ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(id);
-
-                if (examRecordData == null) {
-                    LOG.error("获取Redis中考试信息为空 examRecordDataId:" + id);
-                    examRecordData = this.queryExamRecordData(id);
-
-                    if (examRecordData != null) {
-
-                        if (syncRule.getAllowOrgList().isEmpty()) {
-                            // 未配置“允许机构列表”值时,默认执行所有机构,但要跳过“限制机构列表”中的机构
-                            if (syncRule.isLimitOrg(examRecordData.getRootOrgId())) {
-                                continue;
-                            }
-
-                            updateExamRecordStatusError(id);
-                        } else {
-                            // 配置了“允许机构列表”值时,只执行“允许机构列表”范围内的机构
-                            if (syncRule.isAllowOrg(examRecordData.getRootOrgId())) {
-                                updateExamRecordStatusError(id);
-                            }
-                        }
-
-                    }
-                } else {
-
-                    if (syncRule.getAllowOrgList().isEmpty()) {
-                        // 未配置“允许机构列表”值时,默认执行所有机构,但要跳过“限制机构列表”中的机构
-                        if (syncRule.isLimitOrg(examRecordData.getRootOrgId())) {
-                            continue;
-                        }
-
-                        newExamRecordDataIds.add(id);
-                        tempList.add(new KeyValuePair<>(id, examRecordData));
-                    } else {
-                        // 配置了“允许机构列表”值时,只执行“允许机构列表”范围内的机构
-                        if (syncRule.isAllowOrg(examRecordData.getRootOrgId())) {
-                            newExamRecordDataIds.add(id);
-                            tempList.add(new KeyValuePair<>(id, examRecordData));
-                        }
-                    }
-
-                }
-            }
-
-            // 修改已获取过的考试信息batchNum
-            UpdateExamRecordDataBatchNumReq ureq = new UpdateExamRecordDataBatchNumReq();
-            ureq.setBatchNum(batchNum);
-            ureq.setIds(newExamRecordDataIds);
-            try {
-                examRecordDataCloudService.updateExamRecordDataBatchNum(ureq);
-            } catch (Exception e) {
-                Date end = new Date();
-                long times = end.getTime() - start.getTime();
-                LOG.error("修改考试记录batchNum出错 startId:" + startId + " 获取数据条数:" + outList.size() + " 耗时:" + times + "ms", e);
-                return;
-            }
-
-            outList.addAll(tempList);
-            startId = ids.get(ids.size() - 1);
-        }
-    }
-
-    private ExamRecordData queryExamRecordData(Long id) {
-        String sql = String.format("select id,root_org_id,exam_record_status,sync_status from ec_oes_exam_record_data where id = %s", id);
-        try {
-            return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(ExamRecordData.class));
-        } catch (Exception e) {
-            // ignore
-            return null;
-        }
-    }
-
-    private void updateExamRecordStatusError(Long id) {
-        try {
-            UpdateExamRecordStatusReq ureq = new UpdateExamRecordStatusReq();
-            ureq.setExamRecordStatus(ExamRecordStatus.EXAM_ERROR.name());
-            ureq.setId(id);
-            examRecordDataCloudService.updateExamRecordStatus(ureq);
-        } catch (Exception e) {
-            LOG.error("修改考试记录状态失败 examRecordDataId:" + id, e);
-        }
-    }
-
-}

+ 0 - 220
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/HandInExamExecutor.java

@@ -1,220 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.pipeline;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.helpers.KeyValuePair;
-import cn.com.qmth.examcloud.commons.helpers.ObjectHolder;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.NodeExecuter;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.TaskContext;
-import cn.com.qmth.examcloud.commons.util.JsonUtil;
-import cn.com.qmth.examcloud.core.oe.student.api.ExamRecordDataCloudService;
-import cn.com.qmth.examcloud.core.oe.student.api.request.HandInExamReq;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamingSessionService;
-import cn.com.qmth.examcloud.support.Constants;
-import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
-import cn.com.qmth.examcloud.support.enums.HandInExamType;
-import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.support.examing.ExamingActivityTime;
-import cn.com.qmth.examcloud.support.examing.ExamingHeartbeat;
-import cn.com.qmth.examcloud.support.examing.ExamingSession;
-import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
-import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
-import cn.com.qmth.examcloud.web.redis.RedisClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.Date;
-import java.util.List;
-
-/**
- * @Description 自动交卷执行器
- * @Author lideyin
- * @Date 2019/12/17 16:39
- * @Version 1.0
- */
-@Deprecated
-@Component
-public class HandInExamExecutor implements NodeExecuter<Long, ExamRecordData, Long, ExamRecordData> {
-
-    @Autowired
-    private ExamingSessionService examingSessionService;
-
-    @Autowired
-    private ExamRecordDataService examRecordDataService;
-
-    @Autowired
-    private RedisClient redisClient;
-
-    @Autowired
-    private ExamRecordDataCloudService examRecordDataCloudService;
-
-    private static final Logger LOG = LoggerFactory.getLogger(HandInExamExecutor.class);
-
-    /**
-     * 执行
-     *
-     * @param key
-     * @param uncertainExamRecordData 不确定的考试记录,数据有可能已变更
-     * @param outList
-     * @param removable
-     * @param context
-     * @throws Exception
-     * @author WANGWEI
-     */
-    @Override
-    public void execute(Long key, ExamRecordData uncertainExamRecordData,
-                        List<KeyValuePair<Long, ExamRecordData>> outList,
-                        ObjectHolder<Boolean> removable, TaskContext context) throws Exception {
-
-        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + uncertainExamRecordData.getStudentId();
-
-        try {
-
-            this.debugLog("enter executor...", uncertainExamRecordData.getId());
-
-            //添加考试控制全局锁
-            SequenceLockHelper.getLockSimple(sequenceLockKey);
-
-            this.debugLog("get locker success...", uncertainExamRecordData.getId());
-
-            //获取最新的考试记录状态
-            ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(uncertainExamRecordData.getId());
-
-            Long examRecordDataId = examRecordData.getId();
-
-            //处理正在进行中的考试
-            if (examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_ING) {
-
-                ExamingSession examingSession = examingSessionService.getExamingSession(examRecordData.getStudentId());
-
-                if (null == examingSession) {
-                    this.debugLog("examingSession is null...", examRecordDataId);
-                } else {
-                    this.debugLog("examingSession is not null and the json is..." + JsonUtil.toJson(examingSession),
-                            examRecordDataId);
-                }
-
-                // 如果考试会话不存在/超过断点续考时间,自动交卷
-                if (null == examingSession || isOverBreakpointTime(examingSession)) {
-
-                    try {
-
-                        this.debugLog("prepare to auto hand in...", examRecordDataId);
-
-                        //自动交卷
-                        HandInExamReq handInExamReq = new HandInExamReq();
-                        handInExamReq.setExamRecordDataId(examRecordDataId);
-                        handInExamReq.setHandInExamType(HandInExamType.AUTO);
-                        examRecordDataCloudService.handInExam(handInExamReq);
-
-                        //更改内存中的交卷状态
-                        examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_AUTO_HAND_IN);
-                        examRecordData.setCleanTime(new Date());
-
-                        //更新考试记录缓存
-                        examRecordDataService.saveExamRecordDataCache(examRecordDataId, examRecordData);
-
-                        // 删除考试会话
-                        if (null != examingSession) {
-                            examingSessionService.deleteExamingSession(examRecordData.getStudentId());
-                        }
-
-                        outList.add(new KeyValuePair<>(key, examRecordData));
-
-                        this.debugLog("auto hand in success...", examRecordDataId);
-
-                        return;
-
-                    } catch (Exception e) {
-                        //回滚自动交卷操作
-                        examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_ING);
-                        examRecordData.setCleanTime(null);
-                        examRecordDataService.saveExamRecordDataCache(examRecordDataId, examRecordData);
-
-                        outList.clear();
-                        removable.set(false);
-
-                        this.errorLog("auto hand in occurs error,to be retry...", e, examRecordDataId);
-
-                        throw new StatusException("300101", "自动交卷出现异常:" + e.getMessage());
-                    }
-                }
-
-                //如果不需要自动交卷,则需要下次轮循,继续处理
-                removable.set(false);
-                outList.clear();
-
-                this.debugLog("don't need auto hand in.to be retry...", examRecordDataId);
-
-                return;
-            }
-
-            //其它状态的数据,直接交给下一个节点处理
-            outList.add(new KeyValuePair<>(key, examRecordData));
-
-            this.debugLog("current status is '" + examRecordData.getExamRecordStatus().name() +
-                    "'.do nothing and go to the next node...", examRecordDataId);
-        } finally {
-            SequenceLockHelper.releaseLockSimple(sequenceLockKey);
-        }
-    }
-
-    /**
-     * 是否超过考试时长
-     *
-     * @param examingSession
-     * @return
-     */
-    private boolean isOverExamTime(ExamingSession examingSession) {
-        String examingHeartbeatKey = RedisKeyHelper.getBuilder()
-                .examingHeartbeatKey(examingSession.getExamRecordDataId());
-        ExamingHeartbeat examingHeartbeat = redisClient.get(examingHeartbeatKey,
-                ExamingHeartbeat.class);
-
-        //秒
-        long cost = null == examingHeartbeat ? 0 : examingHeartbeat.getCost();
-        return examingSession.getExamDuration() <= cost * 1000;
-    }
-
-    /**
-     * 是否超过断点续考时间
-     *
-     * @param examingSession
-     * @return
-     */
-    private boolean isOverBreakpointTime(ExamingSession examingSession) {
-        long now = System.currentTimeMillis();
-
-        String examingActiveTimeKey = RedisKeyHelper.getBuilder()
-                .examingActiveTimeKey(examingSession.getExamRecordDataId());
-        ExamingActivityTime examingActiveTime = redisClient.get(examingActiveTimeKey,
-                ExamingActivityTime.class);
-
-        if (null == examingActiveTime) {
-            this.debugLog("validating isOverBreakpointTime... and examingActiveTime is null...", examingSession.getExamRecordDataId());
-        } else {
-            this.debugLog("validating isOverBreakpointTime... and the json of examingActiveTime is..." + JsonUtil.toJson(examingActiveTime)
-                    , examingSession.getExamRecordDataId());
-        }
-
-        long activeTime = null == examingActiveTime
-                ? System.currentTimeMillis()
-                : examingActiveTime.getActiveTime();
-        return now - activeTime >= examingSession.getExamReconnectTime().intValue() * 60 * 1000;
-    }
-
-    private void debugLog(String msg, Long examRecordDataId) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("[HAND-IN-EXAM-EXECUTOR-" + examRecordDataId + "]:" + msg);
-        }
-    }
-
-    private void errorLog(String msg, Exception e, Long examRecordDataId) {
-        if (LOG.isErrorEnabled()) {
-            LOG.error("[HAND-IN-EXAM-EXECUTOR-" + examRecordDataId + "]:" + msg, e);
-        }
-    }
-
-}

+ 0 - 235
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/pipeline/SyncExamDataExecutor.java

@@ -1,235 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.pipeline;
-
-import cn.com.qmth.examcloud.commons.helpers.KeyValuePair;
-import cn.com.qmth.examcloud.commons.helpers.ObjectHolder;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.NodeExecuter;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.TaskContext;
-import cn.com.qmth.examcloud.core.oe.admin.api.ExamScoreNoticeQueueCloudService;
-import cn.com.qmth.examcloud.core.oe.admin.api.SyncExamDataCloudService;
-import cn.com.qmth.examcloud.core.oe.admin.api.bean.ExamCaptureBean;
-import cn.com.qmth.examcloud.core.oe.admin.api.bean.ExamSyncCaptureBean;
-import cn.com.qmth.examcloud.core.oe.admin.api.request.AddExamScoreNoticeQueueReq;
-import cn.com.qmth.examcloud.core.oe.admin.api.request.SyncExamDataReq;
-import cn.com.qmth.examcloud.core.oe.student.api.ExamRecordDataCloudService;
-import cn.com.qmth.examcloud.core.oe.student.api.request.UpdatePartialExamRecordReq;
-import cn.com.qmth.examcloud.core.oe.task.service.CommonService;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamBossService;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamRecordDataService;
-import cn.com.qmth.examcloud.support.Constants;
-import cn.com.qmth.examcloud.support.enums.ExamProperties;
-import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
-import cn.com.qmth.examcloud.support.enums.SyncStatus;
-import cn.com.qmth.examcloud.support.examing.ExamBoss;
-import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.support.helper.ExamCacheTransferHelper;
-import cn.com.qmth.examcloud.support.helper.FaceBiopsyHelper;
-import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-/**
- * @Description 同步考试数据执行器
- * @Author lideyin
- * @Date 2019/12/19 16:22
- * @Version 1.0
- */
-@Deprecated
-@Component
-public class SyncExamDataExecutor implements NodeExecuter<Long, ExamRecordData, Long, ExamRecordData> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SyncExamDataExecutor.class);
-
-    @Autowired
-    private SyncExamDataCloudService syncExamDataCloudService;
-
-    @Autowired
-    private ExamRecordDataService examRecordDataService;
-
-    @Autowired
-    private ExamRecordDataCloudService examRecordDataCloudService;
-
-    @Autowired
-    private ExamScoreNoticeQueueCloudService examScoreNoticeQueueCloudService;
-
-    @Autowired
-    private ExamBossService examBossService;
-
-    @Autowired
-    private CommonService commonService;
-
-    @Override
-    public void execute(Long key, ExamRecordData examRecordData,
-                        List<KeyValuePair<Long, ExamRecordData>> outList,
-                        ObjectHolder<Boolean> removable, TaskContext context) throws Exception {
-
-        Long studentId = examRecordData.getStudentId();
-        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + studentId;
-        long st = System.currentTimeMillis();
-
-        try {
-            //添加考试控制全局锁
-            SequenceLockHelper.getLockSimple(sequenceLockKey);
-
-            //如果已同步,直接交给下一节点
-            if (SyncStatus.SYNCED == examRecordData.getSyncStatus()) {
-                outList.add(new KeyValuePair<>(key, examRecordData));
-
-                LOG.info("syncExamData already synced, tempExamRecordDataId = {}, examStudentId = {}",
-                        examRecordData.getId(), examRecordData.getExamStudentId());
-                return;
-            }
-
-            //处理上一节点中,指定时间内仍未处理完成的数据
-            Long examRecordDataId = examRecordData.getId();
-            if (ExamRecordStatus.EXAM_HAND_IN == examRecordData.getExamRecordStatus() ||
-                    ExamRecordStatus.EXAM_AUTO_HAND_IN == examRecordData.getExamRecordStatus()) {
-
-                this.debugLog("prepare to execute last node's hand in data...", examRecordDataId);
-                long startTime = System.currentTimeMillis();
-                examRecordData = examRecordDataService.processAfterHandInExam(examRecordDataId);
-
-                this.debugLog("T001.execute last node's hand in data success...耗时:" +
-                        (System.currentTimeMillis() - startTime) + " ms", examRecordDataId);
-            }
-
-            //如果考试记录状态为完结状态,则开始同步数据到正式库
-            if (ExamRecordStatus.EXAM_END == examRecordData.getExamRecordStatus() ||
-                    ExamRecordStatus.EXAM_OVERDUE == examRecordData.getExamRecordStatus()) {
-
-                this.debugLog("prepare to sync data...", examRecordDataId);
-
-                //同步数据
-                SyncExamDataReq syncReq = new SyncExamDataReq();
-
-                syncReq.setExamRecordPaperStruct(commonService.getExamRecordPaperStruct(examRecordDataId));
-
-                syncReq.setExamRecordQuestions(commonService.getExamRecordQuestions(examRecordDataId));
-
-                syncReq.setExamContinuedRecords(commonService.getExamContinuedRecords(examRecordDataId));
-
-                syncReq.setExamProcessRecords(commonService.getExamProcessRecords(examRecordDataId));
-
-                //开启人脸检测相关数据赋值
-                Long rootOrgId = examRecordData.getRootOrgId();
-                Long examId = examRecordData.getExamId();
-                if (FaceBiopsyHelper.isFaceEnable(rootOrgId, examId, studentId)) {
-                    List<ExamCaptureBean> captures = commonService.getExamCaptures(examRecordDataId);
-                    syncReq.setExamCaptures(captures);
-
-                    ExamSyncCaptureBean syncCapture = commonService.getExamSyncCapture(examRecordDataId);
-                    syncReq.setExamSyncCapture(syncCapture);
-
-                    //虚拟摄像头进入待审核,且有虚拟摄像头的或者同步没有照片的,更新缓存
-                    boolean hasVirtualCamera = captures.stream().anyMatch(e -> e.getHasVirtualCamera() != null && e.getHasVirtualCamera());
-                    if (examRecordDataService.isVirtualToWaiting(examId) && hasVirtualCamera || syncCapture == null) {
-                        examRecordData.setIsWarn(true);
-                        examRecordDataService.saveExamRecordDataCache(examRecordDataId, examRecordData);
-                    }
-
-                    if (FaceBiopsyHelper.isFaceVerify(rootOrgId, examId, studentId)) {
-                        syncReq.setExamFaceLivenessVerifies(commonService.getExamFaceLivenessVerifies(examRecordDataId));
-
-                        syncReq.setFaceBiopsy(commonService.getFaceBiopsy(examRecordDataId));
-
-                        syncReq.setFaceLiveVerifyRecords(commonService.getFaceLiveVerifyRecords(examRecordDataId));
-                    }
-                }
-
-                syncReq.setExamRecordData(commonService.copyExamRecordDataFrom(examRecordData));
-
-                long startTime = System.currentTimeMillis();
-                //同步数据
-                syncExamDataCloudService.syncExamData(syncReq);
-                LOG.info("syncExamData ok, tempExamRecordDataId = {}, examStudentId = {}, cost {} ms",
-                        examRecordDataId, examRecordData.getExamStudentId(), System.currentTimeMillis() - startTime);
-
-                //考试完结次数加1
-                ExamBoss examBoss = examBossService.getExamBoss(examRecordData.getExamStudentId());
-                if (null != examBoss) {
-                    examBoss.setEndCount(examBoss.getEndCount() + 1);
-
-                    startTime = System.currentTimeMillis();
-
-                    examBossService.saveExamBoss(examRecordData.getExamStudentId(), examBoss);
-
-                    this.debugLog("T003.考试完结次数加1,并saveExamBoss耗时..." +
-                            (System.currentTimeMillis() - startTime) + " ms", examRecordDataId);
-                }
-
-                //设置并保存考试记录的同步状态
-                startTime = System.currentTimeMillis();
-
-                examRecordData.setSyncStatus(SyncStatus.SYNCED);
-                setAndSaveExamRecordDataSyncStatus(examRecordDataId);
-                this.debugLog("T004.设置并保存考试记录的同步状态,耗时..." +
-                        (System.currentTimeMillis() - startTime) + " ms", examRecordDataId);
-
-                //保存成绩通知队列
-                String isPushScore = ExamCacheTransferHelper.getCachedExamProperty(examRecordData.getExamId(),
-                        examRecordData.getStudentId(), ExamProperties.PUSH_SCORE.name()).getValue();
-                if (Constants.isTrue.equals(isPushScore)) {
-                    AddExamScoreNoticeQueueReq req = new AddExamScoreNoticeQueueReq();
-                    req.setRootOrgId(rootOrgId);
-                    examScoreNoticeQueueCloudService.addExamScoreNoticeQueue(req);
-                }
-
-                outList.add(new KeyValuePair<>(key, examRecordData));
-
-                this.debugLog("sync data and change status success...", examRecordDataId);
-
-                return;
-            }
-
-            //其它状态的数据,直接交给下一个节点处理
-            outList.add(new KeyValuePair<>(key, examRecordData));
-
-            this.debugLog("current status is '" + examRecordData.getExamRecordStatus().name() +
-                    "'.do nothing and go to the next node...", examRecordData.getId());
-        } finally {
-            SequenceLockHelper.releaseLockSimple(sequenceLockKey);
-            this.debugLog("T999 同步数据合计耗时:" + (System.currentTimeMillis() - st) + " ms", examRecordData.getId());
-        }
-    }
-
-    /**
-     * 设置并保存考试记录的同步状态
-     *
-     * @param examRecordDataId
-     */
-    private void setAndSaveExamRecordDataSyncStatus(Long examRecordDataId) {
-        ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(examRecordDataId);
-
-        if (SyncStatus.SYNCED == examRecordData.getSyncStatus()) {
-            return;
-        }
-
-        examRecordData.setSyncStatus(SyncStatus.SYNCED);
-        examRecordDataService.saveExamRecordDataCache(examRecordDataId, examRecordData);
-
-        try {
-            //同步更新数据库表中的同步状态
-            UpdatePartialExamRecordReq uperReq = new UpdatePartialExamRecordReq(examRecordDataId);
-            uperReq.setSyncStatus(SyncStatus.SYNCED.name());
-            examRecordDataCloudService.updatePartialExamRecord(uperReq);
-        } catch (Exception e) {
-            this.errorLog("更新数据库表中的同步状态失败", examRecordDataId, e);
-        }
-    }
-
-    private void debugLog(String msg, Long examRecordDataId) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("[SYNC-EXAM-DATA-EXECUTOR-" + examRecordDataId + "]:" + msg);
-        }
-    }
-
-    private void errorLog(String msg, Long examRecordDataId, Exception e) {
-        if (LOG.isErrorEnabled()) {
-            LOG.error("[SYNC-EXAM-DATA-EXECUTOR-" + examRecordDataId + "]:" + msg, e);
-        }
-    }
-
-}

+ 0 - 81
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/worker/BaiduFaceLivenessWorker.java

@@ -1,81 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.worker;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.Worker;
-import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.WorkerController;
-import cn.com.qmth.examcloud.commons.util.Util;
-import cn.com.qmth.examcloud.core.oe.student.dao.enums.ExamCaptureQueueStatus;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamCaptureQueueService;
-import cn.com.qmth.examcloud.core.oe.task.service.FaceVerifyService;
-import cn.com.qmth.examcloud.core.oe.task.service.bean.ExamCaptureQueueInfo;
-import cn.com.qmth.examcloud.support.Constants;
-import cn.com.qmth.examcloud.web.support.SpringContextHolder;
-import org.apache.logging.log4j.ThreadContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 百度活体检测工作线程
- *
- * @author lideyin 20190620
- */
-@Deprecated
-public class BaiduFaceLivenessWorker implements Worker<ExamCaptureQueueInfo> {
-
-    private static final Logger log = LoggerFactory.getLogger(BaiduFaceLivenessWorker.class);
-
-    @Override
-    public void process(WorkerController controller, ExamCaptureQueueInfo element) {
-        ThreadContext.put("TRACE_ID", "Q_" + element.getId());
-        ThreadContext.put("CALLER", "BAIDU_WORKER");
-        FaceVerifyCounter.increaseFaceLivenessDetectCount();
-        if (log.isDebugEnabled()) {
-            log.debug("[BAIDU_FACELIVENESS_WORKER.] 图片处理数量+1,count= "
-                    + FaceVerifyCounter.getFaceLivenessDetectCount());
-        }
-
-        FaceVerifyService examCaptureService = SpringContextHolder.getBean(FaceVerifyService.class);
-        ExamCaptureQueueService examCaptureQueueService = SpringContextHolder
-                .getBean(ExamCaptureQueueService.class);
-        try {
-            examCaptureService.disposeBaiDuFaceLiveness(element);
-        } catch (StatusException e) {
-            while (true) {
-                // 异常处理
-                if (examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(), e.getDesc(),
-                        ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED)) {
-                    break;
-                }
-                ;
-                Util.sleep(TimeUnit.MILLISECONDS, 500);
-            }
-            if ((e.getCode().equals(Constants.BAIDU_FACELIVENESS_QPS_LIMIT_EXCEEDED_CODE))) {
-                // 如果超过并发次数,则添加异常次数
-                controller.addConcurrencyWarn();
-                log.debug("[BAIDU_FACELIVENESS_WORKER.] 超过并发次数 ");
-            } else {
-                FaceVerifyCounter.increaseFaceLivenessDetectCount();
-                log.error("[BAIDU_FACELIVENESS_WORKER.] 自定义异常 " + e.getDesc(), e);
-            }
-            Util.sleep(TimeUnit.MICROSECONDS, 50);
-        } catch (Exception e) {
-            FaceVerifyCounter.increaseFaceLivenessDetectCount();
-            while (true) {
-                // 异常处理
-                if (examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(), "系统异常",
-                        ExamCaptureQueueStatus.PROCESS_FACELIVENESS_FAILED)) {
-                    break;
-                }
-                ;
-                Util.sleep(TimeUnit.MILLISECONDS, 500);
-            }
-            log.error("[BAIDU_FACELIVENESS_WORKER.] 系统异常 " + e.getMessage(), e);
-            Util.sleep(TimeUnit.MICROSECONDS, 50);
-        } finally {
-            ThreadContext.clearAll();
-        }
-    }
-
-}

+ 0 - 87
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/worker/FacePPCompareWorker.java

@@ -1,87 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.worker;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.Worker;
-import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.WorkerController;
-import cn.com.qmth.examcloud.commons.util.Util;
-import cn.com.qmth.examcloud.core.oe.student.dao.enums.ExamCaptureQueueStatus;
-import cn.com.qmth.examcloud.core.oe.task.service.ExamCaptureQueueService;
-import cn.com.qmth.examcloud.core.oe.task.service.FaceVerifyService;
-import cn.com.qmth.examcloud.core.oe.task.service.bean.ExamCaptureQueueInfo;
-import cn.com.qmth.examcloud.support.Constants;
-import cn.com.qmth.examcloud.web.support.SpringContextHolder;
-import org.apache.logging.log4j.ThreadContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * face++人脸比对工作线程
- *
- * @author lideyin 20190620
- */
-@Deprecated
-public class FacePPCompareWorker implements Worker<ExamCaptureQueueInfo> {
-
-    private static final Logger log = LoggerFactory.getLogger(FacePPCompareWorker.class);
-
-    @Override
-    public void process(WorkerController controller, ExamCaptureQueueInfo element) {
-
-        ThreadContext.put("TRACE_ID", "Q_" + element.getId());
-        ThreadContext.put("CALLER", "FACEPP_WORKER");
-        // 图片处理数量+1
-        FaceVerifyCounter.increaseFaceCompareCount();
-        if (log.isDebugEnabled()) {
-            log.debug("[FACEPP_COMPARE_WORKER.] 图片处理数量+1,count= "
-                    + FaceVerifyCounter.getFaceCompareCount());
-        }
-        FaceVerifyService examCaptureService = SpringContextHolder.getBean(FaceVerifyService.class);
-
-        ExamCaptureQueueService examCaptureQueueService = SpringContextHolder
-                .getBean(ExamCaptureQueueService.class);
-        try {
-            examCaptureService.disposeFaceCompare(element);
-        } catch (StatusException e) {
-            while (true) {
-                // 异常处理
-                if (examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(), e.getDesc(),
-                        ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED)) {
-                    break;
-                }
-                ;
-                Util.sleep(TimeUnit.MILLISECONDS, 500);
-            }
-
-            if ((e.getCode().equals(Constants.FACE_COMPARE_CONCURRENCY_LIMIT_EXCEEDED))) {
-                // 如果超过并发次数,则添加异常次数
-                controller.addConcurrencyWarn();
-                log.debug("[FACEPP_COMPARE_WORKER.] 超过并发次数 ");
-            } else {
-                FaceVerifyCounter.increaseFaceCompareFailedCount();
-                log.error("[FACEPP_COMPARE_WORKER.] 自定义异常 " +
-                        ",failedCount=" + FaceVerifyCounter.getFaceCompareFailedCount(), e);
-            }
-
-            Util.sleep(TimeUnit.MICROSECONDS, 50);
-        } catch (Exception e) {
-            FaceVerifyCounter.increaseFaceCompareFailedCount();
-            // 异常处理
-            while (true) {
-                // 异常处理
-                if (examCaptureQueueService.saveExamCaptureQueueEntityByFailed(element.getId(), "系统异常",
-                        ExamCaptureQueueStatus.PROCESS_FACE_COMPARE_FAILED)) {
-                    break;
-                }
-                Util.sleep(TimeUnit.MILLISECONDS, 500);
-            }
-            log.error("[FACEPP_COMPARE_WORKER.] 系统异常 " +
-                    ",failedCount=" + FaceVerifyCounter.getFaceCompareFailedCount(), e);
-            Util.sleep(TimeUnit.MICROSECONDS, 50);
-        } finally {
-            ThreadContext.clearAll();
-        }
-    }
-
-}

+ 0 - 158
examcloud-core-oe-task-service/src/main/java/cn/com/qmth/examcloud/core/oe/task/service/worker/FaceVerifyCounter.java

@@ -1,158 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.service.worker;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @Description 考试照片统计控制器
- * @Author lideyin
- * @Date 2019/9/9 17:05
- * @Version 1.0
- */
-@Deprecated
-public class FaceVerifyCounter {
-
-    //人脸比对处理数量
-    private static AtomicInteger faceCompareCount = new AtomicInteger(0);
-
-    //人脸比对处理失败数量
-    private static AtomicInteger faceCompareFailedCount = new AtomicInteger(0);
-
-    private static Object facePPLock = new Object();
-
-    private static Object faceLivenessLock = new Object();
-
-    /**
-     * 人脸比对总数量自增
-     */
-    public static void increaseFaceCompareCount() {
-        synchronized (facePPLock) {
-            faceCompareCount.incrementAndGet();
-        }
-    }
-
-    /**
-     * 人脸比对错误数量自增
-     */
-    public static void increaseFaceCompareFailedCount() {
-        synchronized (facePPLock) {
-            faceCompareFailedCount.incrementAndGet();
-        }
-    }
-
-    /**
-     * 同步重置人脸比对所有数量
-     */
-    public static void resetAllFaceCompareCount() {
-        synchronized (facePPLock) {
-            faceCompareCount.set(0);
-            faceCompareFailedCount.set(0);
-        }
-    }
-
-    /**
-     * 人脸比对总数量
-     *
-     * @return int
-     */
-    public static int getFaceCompareCount() {
-        synchronized (facePPLock) {
-            return faceCompareCount.get();
-        }
-    }
-
-    /**
-     * 人脸比对失败数量
-     *
-     * @return int
-     */
-    public static int getFaceCompareFailedCount() {
-        synchronized (facePPLock) {
-            return faceCompareFailedCount.get();
-        }
-    }
-
-    /**
-     * 人脸比对失败率
-     *
-     * @return int
-     */
-    public static int getFaceCompareFailurePercent() {
-        synchronized (facePPLock) {
-            if (faceCompareCount.get() == 0) {
-                return 0;
-            }
-            return faceCompareFailedCount.get() * 100 / faceCompareCount.get();
-        }
-    }
-
-    //活体检测处理数量
-    private static AtomicInteger faceLivenessDetectCount = new AtomicInteger(0);
-
-    //活体检测处理失败数量
-    private static AtomicInteger faceLivenessDetectFailedCount = new AtomicInteger(0);
-
-    /**
-     * 活体检测总数量自增
-     */
-    public static void increaseFaceLivenessDetectCount() {
-        synchronized (faceLivenessLock) {
-            faceLivenessDetectCount.incrementAndGet();
-        }
-    }
-
-    /**
-     * 活体检测错误数量自增
-     */
-    public static void increaseFaceLivenessDetectFailedCount() {
-        synchronized (faceLivenessLock) {
-            faceLivenessDetectFailedCount.incrementAndGet();
-        }
-    }
-
-    /**
-     * 重置活体检测所有数量
-     */
-    public static void resetAllFaceLivenessDetectCount() {
-        synchronized (faceLivenessLock) {
-            faceLivenessDetectCount.set(0);
-            faceLivenessDetectFailedCount.set(0);
-        }
-    }
-
-    /**
-     * 活体检测总数量
-     *
-     * @return
-     */
-    public static int getFaceLivenessDetectCount() {
-        synchronized (faceLivenessLock) {
-            return faceLivenessDetectCount.get();
-        }
-    }
-
-    /**
-     * 活体检测失败数量
-     *
-     * @return
-     */
-    public static int getFaceLivenessDetectFailedCount() {
-        synchronized (faceLivenessLock) {
-            return faceLivenessDetectFailedCount.get();
-        }
-    }
-
-    /**
-     * 活体检测失败率
-     *
-     * @return int
-     */
-    public static int getFaceLivenessDetectFailurePercent() {
-        synchronized (faceLivenessLock) {
-            if (faceLivenessDetectCount.get() == 0) {
-                return 0;
-            }
-            return faceLivenessDetectFailedCount.get() * 100 / faceLivenessDetectCount.get();
-        }
-    }
-
-}

+ 2 - 1
examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ExamCloudResourceManager.java

@@ -7,6 +7,7 @@ import cn.com.qmth.examcloud.commons.util.RegExpUtil;
 import cn.com.qmth.examcloud.core.basic.api.UserDataRuleCloudService;
 import cn.com.qmth.examcloud.core.basic.api.request.QueryUserDataRuleReq;
 import cn.com.qmth.examcloud.core.basic.api.response.QueryUserDataRuleResp;
+import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.AppCacheBean;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
@@ -101,7 +102,7 @@ public class ExamCloudResourceManager implements ResourceManager {
         Set<String> rolePrivilegeList = Sets.newHashSet();
         Long rootOrgId = user.getRootOrgId();
         for (Role role : roleList) {
-            String key = "$_P_" + rootOrgId + "_" + role.getRoleId();
+            String key = CacheConstants.CACHE_B_ROLE_PRIVILEGE + rootOrgId + "_" + role.getRoleId();
             String rolePrivileges = redisClient.get(key, String.class);
 
             List<String> rpList = RegExpUtil.findAll(rolePrivileges, "\\w+");

+ 0 - 160
examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessBaiduFaceLivenessAlarmTask.java

@@ -1,160 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.starter.config;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.util.Util;
-import cn.com.qmth.examcloud.core.oe.task.service.worker.FaceVerifyCounter;
-import cn.com.qmth.examcloud.exchange.inner.api.SmsCloudService;
-import cn.com.qmth.examcloud.exchange.inner.api.request.SendSmsReq;
-import cn.com.qmth.examcloud.support.cache.CacheHelper;
-import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
-import com.google.common.collect.Maps;
-import com.googlecode.aviator.AviatorEvaluator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @Description 处理抓拍照片预警任务
- * @Author lideyin
- * @Date 2019/9/12 10:52
- * @Version 1.0
- */
-@Deprecated
-@Component
-@Order(203)
-public class ProcessBaiduFaceLivenessAlarmTask implements ApplicationRunner {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ProcessBaiduFaceLivenessAlarmTask.class);
-
-    @Autowired
-    SmsCloudService smsCloudService;
-
-    @Value("${examcloud.face.compare.task.enable}")
-    private Boolean faceCompareTaskEnable;
-
-    @Override
-    public void run(ApplicationArguments args) throws Exception {
-        faceCompareTaskEnable = false;
-
-        LOG.warn("ProcessBaiduFaceLivenessAlarmTask enable is " + faceCompareTaskEnable);
-        if (!faceCompareTaskEnable) {
-            return;
-        }
-
-        Thread thread = new Thread(new Runnable() {
-
-            @Override
-            public void run() {
-                while (true) {
-                    try {
-                        faceLivenessDectectAlarm();
-                    } catch (Exception e) {
-                        LOG.error("[FACE_LIVENESS_ALARM.] 活体检测预警出现异常", e);
-                    }
-
-                    // 每分钟轮循一次
-                    Util.sleep(60);
-                }
-
-            }
-        });
-        thread.setDaemon(true);
-        thread.start();
-    }
-
-    /**
-     * 活体检测,如果有必要则发短信
-     */
-    private void faceLivenessDectectAlarm() {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("[FACE_LIVENESS_ALARM] 进入活体检测" + System.currentTimeMillis()
-                    + "....totalCount="
-                    + FaceVerifyCounter.getFaceLivenessDetectCount()
-                    + " ,failCount="
-                    + FaceVerifyCounter.getFaceLivenessDetectFailedCount());
-        }
-
-        // 默认每分钟失败率超过50%则发短信报警,且总数不少于10次则短信报警
-        if (needSmsAlarm()) {
-            SysPropertyCacheBean faceLivenessSmsAssemblyCodeProperty = CacheHelper
-                    .getSysProperty("capture.faceLiveness.smsAssemblyCode");
-            if (!faceLivenessSmsAssemblyCodeProperty.getHasValue()) {
-                LOG.error("[FACE_LIVENESS_ALARM.] 未配置人脸比对的短信模板代码,totalCount="
-                        + FaceVerifyCounter.getFaceCompareCount()
-                        + ",errorCount="
-                        + FaceVerifyCounter.getFaceCompareFailedCount());
-                throw new StatusException("300003", "未配置人脸活体检测的短信模板代码");
-            }
-            SysPropertyCacheBean smsPhoneProperty = CacheHelper
-                    .getSysProperty("capture.sms.phones");
-            if (!smsPhoneProperty.getHasValue()) {
-                LOG.error("[FACE_LIVENESS_ALARM.] 未配置图片处理失败的通知手机号,totalCount="
-                        + FaceVerifyCounter.getFaceCompareCount()
-                        + ",errorCount="
-                        + FaceVerifyCounter.getFaceCompareFailedCount());
-                throw new StatusException("300004", "未配置图片处理失败的通知手机号");
-            }
-
-            List<String> phoneList = Arrays
-                    .asList(smsPhoneProperty.getValue().toString().split(","));
-            SendSmsReq sendSmsReq = new SendSmsReq();
-            sendSmsReq.setPhoneList(phoneList);
-            sendSmsReq
-                    .setSmsAssemblyCode(faceLivenessSmsAssemblyCodeProperty.getValue().toString());
-
-            HashMap<String, String> params = new HashMap<>();
-            params.put("totalCount", String
-                    .valueOf(FaceVerifyCounter.getFaceLivenessDetectCount()));
-            params.put("errorCount", String.valueOf(
-                    FaceVerifyCounter.getFaceLivenessDetectFailedCount()));
-            sendSmsReq.setParams(params);
-            try {
-                smsCloudService.sendSms(sendSmsReq);
-            } catch (Exception e) {
-                LOG.error("[PROCESS_FACE_LIVENESS.] 发送短信出现异常", e);
-            }
-        }
-        // 每1分钟重置一次总数量与失败数量
-        FaceVerifyCounter.resetAllFaceLivenessDetectCount();
-
-    }
-
-    /**
-     * 是否需要短信报警
-     *
-     * @return boolean
-     */
-    private boolean needSmsAlarm() {
-        if (FaceVerifyCounter.getFaceCompareCount() == 0) {
-            return false;
-        }
-        SysPropertyCacheBean expressionProperty = CacheHelper.getSysProperty("capture.baidu.expression.alarm");
-        if (expressionProperty.getHasValue()) {
-            String expression = expressionProperty.getValue().toString();
-            Map<String, Object> env = Maps.newHashMap();
-            env.put("totalCount", FaceVerifyCounter.getFaceLivenessDetectCount());
-            env.put("failedCount", FaceVerifyCounter.getFaceLivenessDetectFailedCount());
-            try {
-                return (Boolean) AviatorEvaluator.execute(expression, env, true);
-            } catch (Exception e) {
-                throw new StatusException("300004", "failed to execute expression. expression=" + expression);
-            }
-
-        } else {
-            // 默认每分钟失败率超过50%则发短信报警,且失败总数不少于10次则短信报警
-            return FaceVerifyCounter.getFaceLivenessDetectFailedCount() > 10 &&
-                    FaceVerifyCounter.getFaceLivenessDetectFailurePercent() > 50;
-        }
-    }
-
-}

+ 0 - 155
examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessBaiduFacelivenessTask.java

@@ -1,155 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.starter.config;
-
-import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.ConcurrentTask;
-import cn.com.qmth.examcloud.commons.util.Util;
-import cn.com.qmth.examcloud.core.oe.student.dao.ExamCaptureQueueRepo;
-import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamCaptureQueueEntity;
-import cn.com.qmth.examcloud.core.oe.task.service.bean.ExamCaptureQueueInfo;
-import cn.com.qmth.examcloud.core.oe.task.service.worker.BaiduFaceLivenessWorker;
-import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
-import org.apache.logging.log4j.ThreadContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-/**
- * 启动百度活体检测任务
- */
-@Deprecated
-@Component
-@Order(201)
-public class ProcessBaiduFacelivenessTask implements ApplicationRunner {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ProcessBaiduFacelivenessTask.class);
-
-    @Autowired
-    ExamCaptureQueueRepo examCaptureQueueRepo;
-
-    @Value("${examcloud.face.compare.task.enable}")
-    private Boolean faceCompareTaskEnable;
-
-    private int process(ConcurrentTask<ExamCaptureQueueInfo> concurrentTask,
-                        String processBatchNum, Integer limit) {
-
-        // 如果队列没满,则从数据库中查数据并插入
-        List<ExamCaptureQueueEntity> examCaptureQueueList = examCaptureQueueRepo
-                .findNeedFacelivenessDetectExamCaptureQueuesLimit(limit, processBatchNum);
-
-        if (null == examCaptureQueueList || examCaptureQueueList.isEmpty()) {
-            LOG
-                    .debug("[PROCESS_BAIDUFACELIVENESS." + processBatchNum + "] 抓拍队列中没有取到数据,2秒后重试");
-            return 0;
-        }
-
-        LOG.debug("[PROCESS_BAIDUFACELIVENESS." + processBatchNum + "] 抓拍队列中的数据条数为:"
-                + examCaptureQueueList.size());
-
-        for (ExamCaptureQueueEntity offeredQueueEntity : examCaptureQueueList) {
-            while (true) {
-                try {
-                    ThreadContext.put("TRACE_ID", "Q_" + offeredQueueEntity.getId());
-                    ThreadContext.put("CALLER", "BAIDU_TASK");
-
-                    examCaptureQueueRepo.updateProcessBatchNum(offeredQueueEntity.getId(), processBatchNum);
-                    boolean offerSuccess = concurrentTask.offerElement(copyExamCaptureQueueInfoFrom(offeredQueueEntity));
-                    if (offerSuccess) {
-                        LOG.debug("[PROCESS_BAIDUFACELIVENESS." + processBatchNum
-                                + "] 向工作队列中添加数据成功:fileUrl=" + offeredQueueEntity.getFileUrl());
-                        break;
-                    }
-
-                    LOG.debug("[PROCESS_BAIDUFACELIVENESS." + processBatchNum
-                            + "] 向工作队列中添加数据失败,30秒后重试:fileUrl=" + offeredQueueEntity.getFileUrl());
-
-                    Util.sleep(PropertyHolder.getInt("$capture.queue.offer.sleepSeconds.", 30));
-                } finally {
-                    ThreadContext.clearAll();
-                }
-
-            }
-        }
-        return examCaptureQueueList.size();
-    }
-
-    @Override
-    public void run(ApplicationArguments args) {
-        faceCompareTaskEnable = false;
-
-        LOG.warn("ProcessBaiduFacelivenessTask enable is " + faceCompareTaskEnable);
-        if (!faceCompareTaskEnable) {
-            return;
-        }
-
-        ConcurrentTask<ExamCaptureQueueInfo> concurrentTask = new ConcurrentTask<ExamCaptureQueueInfo>("百度活体检测");
-        concurrentTask.setMaxActiveThreadSize(
-                PropertyHolder.getInt("$capture.thread.maxActiveThreadSize", 100));
-        concurrentTask.setMinThreadSize(PropertyHolder.getInt("$capture.thread.minThreadSize", 2));
-        concurrentTask.setWorker(new BaiduFaceLivenessWorker());
-        concurrentTask.setMaxActiveThreadSize(PropertyHolder.getInt("$capture.baidu.thread.maxActiveThreadSize", 30));
-        concurrentTask.start();
-        // 当前获取数据的批次号(默认用时间戳)
-        String processBatchNum = "B_" + System.currentTimeMillis();
-
-        LOG.debug("[PROCESS_BAIDUFACELIVENESS." + processBatchNum + "] 启动百度处理服务...");
-
-        Thread thread = new Thread(new Runnable() {
-            @Override
-            public void run() {
-                while (true) {
-                    try {
-                        Integer limit = PropertyHolder.getInt("$capture.queue.limit", 100);
-                        for (int i = 0; i < 5; i++) {
-                            int realCount = process(concurrentTask, processBatchNum, limit);
-                            if (realCount < limit) {
-                                break;
-                            }
-                        }
-                        Util.sleep(PropertyHolder.getInt("$capture.queue.read.sleepSeconds.", 2));
-                    } catch (Exception e) {
-                        LOG.error("[PROCESS_FACEPP." + processBatchNum + "] 百度活体检测出异常,3秒后重试",
-                                e);
-                        Util.sleep(3);
-                    }
-                }
-
-            }
-        });
-
-        thread.setDaemon(true);
-        thread.start();
-    }
-
-    private ExamCaptureQueueInfo copyExamCaptureQueueInfoFrom(ExamCaptureQueueEntity entity) {
-        ExamCaptureQueueInfo info = new ExamCaptureQueueInfo();
-        info.setFaceCompareResult(entity.getFaceCompareResult());
-        info.setFacelivenessResult(entity.getFacelivenessResult());
-        info.setPass(entity.getIsPass());
-        info.setStranger(entity.getIsStranger());
-        info.setFaceCompareStartTime(entity.getFaceCompareStartTime());
-        info.setStatus(entity.getStatus());
-        info.setBaseFaceToken(entity.getBaseFaceToken());
-        info.setCameraInfos(entity.getCameraInfos());
-        info.setCreationTime(entity.getCreationTime());
-        info.setErrorMsg(entity.getErrorMsg());
-        info.setErrorNum(entity.getErrorNum());
-        info.setExamRecordDataId(entity.getExamRecordDataId());
-        info.setExtMsg(entity.getExtMsg());
-        info.setFileName(entity.getFileName());
-        info.setFileUrl(entity.getFileUrl());
-        info.setHasVirtualCamera(entity.getHasVirtualCamera());
-        info.setId(entity.getId());
-        info.setPriority(entity.getPriority());
-        info.setProcessBatchNum(entity.getProcessBatchNum());
-        info.setStudentId(entity.getStudentId());
-        info.setUpdateTime(entity.getUpdateTime());
-        return info;
-    }
-
-}

+ 0 - 169
examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessFaceCompareAlarmTask.java

@@ -1,169 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.starter.config;
-
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.util.Util;
-import cn.com.qmth.examcloud.core.oe.task.service.worker.FaceVerifyCounter;
-import cn.com.qmth.examcloud.exchange.inner.api.SmsCloudService;
-import cn.com.qmth.examcloud.exchange.inner.api.request.SendSmsReq;
-import cn.com.qmth.examcloud.support.cache.CacheHelper;
-import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
-import com.google.common.collect.Maps;
-import com.googlecode.aviator.AviatorEvaluator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @Description 人脸比对预警任务
- * @Author lideyin
- * @Date 2019/9/12 10:52
- * @Version 1.0
- */
-@Deprecated
-@Component
-@Order(202)
-public class ProcessFaceCompareAlarmTask implements ApplicationRunner {
-
-    @Autowired
-    SmsCloudService smsCloudService;
-
-    @Value("${examcloud.face.compare.task.enable}")
-    private Boolean faceCompareTaskEnable;
-
-    private static final Logger LOG = LoggerFactory.getLogger(ProcessFaceCompareAlarmTask.class);
-
-    @Override
-    public void run(ApplicationArguments args) throws Exception {
-        faceCompareTaskEnable = false;
-
-        LOG.warn("ProcessFaceCompareAlarmTask enable is " + faceCompareTaskEnable);
-        if (!faceCompareTaskEnable) {
-            return;
-        }
-
-        Thread thread = new Thread(new Runnable() {
-
-            @Override
-            public void run() {
-                while (true) {
-                    try {
-                        faceCompareAlarm();
-
-                    } catch (Exception e) {
-                        LOG.error("[FACE_COMPARE_ALARM.] 人脸比对预警出现异常 ", e);
-                    }
-                    // 每分钟轮循一次
-                    Util.sleep(60);
-                }
-            }
-        });
-
-        thread.setDaemon(true);
-        thread.start();
-    }
-
-    /**
-     * 人脸比对,如果有必要则发短信
-     */
-    private void faceCompareAlarm() {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("[FACE_COMPARE_ALARM] 进入人脸" + System.currentTimeMillis()
-                    + "....totalCount="
-                    + FaceVerifyCounter.getFaceCompareCount() + " ,failCount="
-                    + FaceVerifyCounter.getFaceCompareFailedCount());
-        }
-
-        // 默认每分钟失败率超过50%则发短信报警,且总数不少于10次则短信报警
-        if (needSmsAlarm()) {
-            SysPropertyCacheBean faceCompareSmsAssemblyCodeProperty = CacheHelper
-                    .getSysProperty("capture.faceCompare.smsAssemblyCode");
-
-            if (!faceCompareSmsAssemblyCodeProperty.getHasValue()) {
-                LOG.error("[FACE_COMPARE_ALARM.] 未配置人脸比对的短信模板代码,totalCount="
-                        + FaceVerifyCounter.getFaceCompareCount()
-                        + ",errorCount="
-                        + FaceVerifyCounter.getFaceCompareFailedCount());
-                throw new StatusException("300001", "未配置人脸比对的短信模板代码");
-            }
-            SysPropertyCacheBean smsPhoneProperty = CacheHelper
-                    .getSysProperty("capture.sms.phones");
-            if (!smsPhoneProperty.getHasValue()) {
-                if (LOG.isErrorEnabled()) {
-                    LOG.error("[FACE_COMPARE_ALARM.] 未配置图片处理失败的通知手机号,totalCount="
-                            + FaceVerifyCounter.getFaceCompareCount()
-                            + ",errorCount="
-                            + FaceVerifyCounter.getFaceCompareFailedCount());
-                }
-                throw new StatusException("300002", "未配置图片处理失败的通知手机号");
-            }
-
-            List<String> phoneList = Arrays
-                    .asList(smsPhoneProperty.getValue().toString().split(","));
-
-            // List<String> phoneList = Arrays.asList("13717595977");
-            SendSmsReq sendSmsReq = new SendSmsReq();
-            sendSmsReq.setPhoneList(phoneList);
-            sendSmsReq.setSmsAssemblyCode(faceCompareSmsAssemblyCodeProperty.getValue().toString());
-            // sendSmsReq.setSmsAssemblyCode("FACECOMPARE");
-
-            HashMap<String, String> params = new HashMap<>();
-            params.put("totalCount",
-                    String.valueOf(FaceVerifyCounter.getFaceCompareCount()));
-            params.put("errorCount", String
-                    .valueOf(FaceVerifyCounter.getFaceCompareFailedCount()));
-            sendSmsReq.setParams(params);
-            try {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("[FACE_COMPARE_ALARM.] 开始调用发送短信接口,totalCount="
-                            + FaceVerifyCounter.getFaceCompareCount()
-                            + ",errorCount="
-                            + FaceVerifyCounter.getFaceCompareFailedCount());
-                }
-                smsCloudService.sendSms(sendSmsReq);
-            } catch (Exception e) {
-                LOG.error("[FACE_COMPARE_ALARM.] 发送短信出现异常", e);
-            }
-        }
-        // 每1分钟重置一次总数量与失败数量
-        FaceVerifyCounter.resetAllFaceCompareCount();
-    }
-
-    /**
-     * 是否需要短信报警
-     *
-     * @return boolean
-     */
-    private boolean needSmsAlarm() {
-        if (FaceVerifyCounter.getFaceCompareCount() == 0) {
-            return false;
-        }
-        SysPropertyCacheBean expressionProperty = CacheHelper.getSysProperty("capture.faceCompare.expression.alarm");
-        if (expressionProperty.getHasValue()) {
-            String expression = expressionProperty.getValue().toString();
-            Map<String, Object> env = Maps.newHashMap();
-            env.put("totalCount", FaceVerifyCounter.getFaceCompareCount());
-            env.put("failedCount", FaceVerifyCounter.getFaceCompareFailedCount());
-            try {
-                return (Boolean) AviatorEvaluator.execute(expression, env, true);
-            } catch (Exception e) {
-                throw new StatusException("300004", "failed to execute expression. expression=" + expression);
-            }
-
-        } else {
-            // 默认每分钟失败率超过50%则发短信报警,且失败总数不少于10次则短信报警
-            return FaceVerifyCounter.getFaceCompareFailedCount() > 10 &&
-                    FaceVerifyCounter.getFaceLivenessDetectFailurePercent() > 50;
-        }
-    }
-
-}

+ 0 - 157
examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/ProcessFaceCompareQueueTask.java

@@ -1,157 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.starter.config;
-
-import cn.com.qmth.examcloud.commons.helpers.concurrency.simple.ConcurrentTask;
-import cn.com.qmth.examcloud.commons.util.Util;
-import cn.com.qmth.examcloud.core.oe.student.dao.ExamCaptureQueueRepo;
-import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamCaptureQueueEntity;
-import cn.com.qmth.examcloud.core.oe.task.service.bean.ExamCaptureQueueInfo;
-import cn.com.qmth.examcloud.core.oe.task.service.worker.FacePPCompareWorker;
-import cn.com.qmth.examcloud.exchange.inner.api.SmsCloudService;
-import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
-import org.apache.logging.log4j.ThreadContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-/**
- * 启动人脸比对任务
- */
-@Deprecated
-@Component
-@Order(200)
-public class ProcessFaceCompareQueueTask implements ApplicationRunner {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ProcessFaceCompareQueueTask.class);
-
-    @Autowired
-    ExamCaptureQueueRepo examCaptureQueueRepo;
-
-    @Autowired
-    SmsCloudService smsCloudService;
-
-    @Value("${examcloud.face.compare.task.enable}")
-    private Boolean faceCompareTaskEnable;
-
-    private int process(ConcurrentTask<ExamCaptureQueueInfo> concurrentTask,
-                        String processBatchNum, Integer limit) {
-        // 如果队列没满,则从数据库中查数据并插入
-        List<ExamCaptureQueueEntity> examCaptureQueueList = examCaptureQueueRepo
-                .findNeedFaceCompareExamCaptureQueuesLimitByProcessBatchNum(limit, processBatchNum);
-
-        if (null == examCaptureQueueList || examCaptureQueueList.isEmpty()) {
-            LOG.debug("[PROCESS_FACEPP." + processBatchNum + "] 抓拍队列中没有取到数据,2秒后重试");
-            return 0;
-        }
-
-        LOG.debug("[PROCESS_FACEPP." + processBatchNum + "] 抓拍队列中的数据条数为:"
-                + examCaptureQueueList.size());
-
-        for (ExamCaptureQueueEntity offeredQueueEntity : examCaptureQueueList) {
-            while (true) {
-                try {
-                    ThreadContext.put("TRACE_ID", "Q_" + offeredQueueEntity.getId());
-                    ThreadContext.put("CALLER", "FACEPP_TASK");
-
-                    examCaptureQueueRepo.updateProcessBatchNum(offeredQueueEntity.getId(), processBatchNum);
-                    boolean offerSuccess = concurrentTask.offerElement(copyExamCaptureQueueInfoFrom(offeredQueueEntity));
-                    // 如果向队列中添加数据成功,则更新标识
-                    if (offerSuccess) {
-                        LOG.debug("[PROCESS_FACEPP." + processBatchNum
-                                + "] 向工作队列中添加数据成功:fileUrl=" + offeredQueueEntity.getFileUrl());
-                        break;
-                    }
-
-                    LOG.debug("[PROCESS_FACEPP." + processBatchNum
-                            + "] 向工作队列中添加数据失败,30秒后重试:fileUrl=" + offeredQueueEntity.getFileUrl());
-
-                    Util.sleep(PropertyHolder.getInt("$capture.queue.offer.sleepSeconds.", 30));
-                } finally {
-                    ThreadContext.clearAll();
-                }
-
-            }
-        }
-        return examCaptureQueueList.size();
-    }
-
-    @Override
-    public void run(ApplicationArguments args) {
-        faceCompareTaskEnable = false;
-
-        LOG.warn("ProcessFaceCompareQueueTask enable is " + faceCompareTaskEnable);
-        if (!faceCompareTaskEnable) {
-            return;
-        }
-
-        ConcurrentTask<ExamCaptureQueueInfo> concurrentTask = new ConcurrentTask<ExamCaptureQueueInfo>("Face++人脸比对");
-        concurrentTask.setMaxActiveThreadSize(
-                PropertyHolder.getInt("$capture.thread.maxActiveThreadSize", 100));
-        concurrentTask.setWorker(new FacePPCompareWorker());
-        concurrentTask.setMaxActiveThreadSize(PropertyHolder.getInt("$capture.facePP.thread.maxActiveThreadSize", 30));
-        concurrentTask.start();
-        // 当前获取数据的批次号(默认用时间戳)
-        String processBatchNum = "A_" + System.currentTimeMillis();
-
-        LOG.debug("[PROCESS_FACEPP." + processBatchNum + "] 启动face++人脸比对服务...");
-
-        Thread thread = new Thread(new Runnable() {
-            @Override
-            public void run() {
-                while (true) {
-                    try {
-                        Integer limit = PropertyHolder.getInt("$capture.queue.limit", 100);
-                        for (int i = 0; i < 5; i++) {
-                            int realCount = process(concurrentTask, processBatchNum, limit);
-                            if (realCount < limit) {
-                                break;
-                            }
-                        }
-                        Util.sleep(PropertyHolder.getInt("$capture.queue.read.sleepSeconds.", 2));
-                    } catch (Exception e) {
-                        LOG.error("[PROCESS_FACEPP." + processBatchNum + "] 百度活体检测出异常,3秒后重试",
-                                e);
-                        Util.sleep(3);
-                    }
-                }
-
-            }
-        });
-
-        thread.setDaemon(true);
-        thread.start();
-    }
-
-    private ExamCaptureQueueInfo copyExamCaptureQueueInfoFrom(ExamCaptureQueueEntity entity) {
-        ExamCaptureQueueInfo info = new ExamCaptureQueueInfo();
-        info.setFaceCompareResult(entity.getFaceCompareResult());
-        info.setFacelivenessResult(entity.getFacelivenessResult());
-        info.setPass(entity.getIsPass());
-        info.setStranger(entity.getIsStranger());
-        info.setFaceCompareStartTime(entity.getFaceCompareStartTime());
-        info.setStatus(entity.getStatus());
-        info.setBaseFaceToken(entity.getBaseFaceToken());
-        info.setCameraInfos(entity.getCameraInfos());
-        info.setCreationTime(entity.getCreationTime());
-        info.setErrorMsg(entity.getErrorMsg());
-        info.setErrorNum(entity.getErrorNum());
-        info.setExamRecordDataId(entity.getExamRecordDataId());
-        info.setExtMsg(entity.getExtMsg());
-        info.setFileName(entity.getFileName());
-        info.setFileUrl(entity.getFileUrl());
-        info.setHasVirtualCamera(entity.getHasVirtualCamera());
-        info.setId(entity.getId());
-        info.setPriority(entity.getPriority());
-        info.setProcessBatchNum(entity.getProcessBatchNum());
-        info.setStudentId(entity.getStudentId());
-        info.setUpdateTime(entity.getUpdateTime());
-        return info;
-    }
-
-}

+ 0 - 113
examcloud-core-oe-task-starter/src/main/java/cn/com/qmth/examcloud/core/oe/task/starter/config/StreamTaskExecutor.java

@@ -1,113 +0,0 @@
-package cn.com.qmth.examcloud.core.oe.task.starter.config;
-
-import cn.com.qmth.examcloud.commons.helpers.pipeline.Node;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.SimpleNode;
-import cn.com.qmth.examcloud.commons.helpers.pipeline.TaskContext;
-import cn.com.qmth.examcloud.core.oe.task.service.pipeline.*;
-import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Component;
-
-/**
- * @Description 流式任务执行器
- * @Author lideyin
- * @Date 2019/12/24 15:52
- * @Version 1.0
- */
-@Deprecated
-@Component
-@Order(300)
-public class StreamTaskExecutor implements ApplicationRunner {
-
-    private static final Logger LOG = LoggerFactory.getLogger(StreamTaskExecutor.class);
-
-    @Autowired
-    private DataGainExamExecutor dataGainExamExecutor;
-
-    @Autowired
-    private HandInExamExecutor handInExamExecutor;
-
-    @Autowired
-    private AfterHandInExamExecutor afterHandInExamExecutor;
-
-    @Autowired
-    private SyncExamDataExecutor syncExamDataExecutor;
-
-    @Autowired
-    private ClearExamDataCacheExecutor clearExamDataCacheExecutor;
-
-    @Value("${examcloud.record.data.sync.enable}")
-    private Boolean recordDataSyncEnable;
-
-    private static Integer DEFAULT_GAIN_EXAM_DATA_EXECUTOR_SLEEP_SECONDS = 2;
-
-    private static Integer DEFAULT_HAND_IN_EXAM_EXECUTOR_SLEEP_SECONDS = 2;
-
-    private static Integer DEFAULT_AFTER_HAND_IN_EXAM_EXECUTOR_SLEEP_SECONDS = 1;
-
-    private static Integer DEFAULT_SYNC_EXAM_DATA_EXECUTOR_SLEEP_SECONDS = 1;
-
-    private static Integer DEFAULT_CLEAR_EXAM_DATA_CACHE_EXECUTOR_SLEEP_SECONDS = 1;
-
-    @Override
-    public void run(ApplicationArguments args) throws Exception {
-        // boolean recordDataSyncEnable = PropertyHolder.getBoolean("examcloud.record.data.sync.enable", false);
-        LOG.warn("examcloud.record.data.sync.enable = " + recordDataSyncEnable);
-        if (recordDataSyncEnable) {
-            // initExecutor();
-        }
-    }
-
-    private void initExecutor() {
-        TaskContext context = new TaskContext();
-
-        Node<Long, ExamRecordData, Long, ExamRecordData> node1 = new SimpleNode<>(
-                "gainExamData", dataGainExamExecutor, context);
-
-        Node<Long, ExamRecordData, Long, ExamRecordData> node2 = new SimpleNode<>(
-                "handInExam", handInExamExecutor, context);
-
-        Node<Long, ExamRecordData, Long, ExamRecordData> node3 = new SimpleNode<>(
-                "afterHandInExam", afterHandInExamExecutor, context);
-
-        Node<Long, ExamRecordData, Long, ExamRecordData> node4 = new SimpleNode<>(
-                "syncExamData", syncExamDataExecutor, context);
-
-        Node<Long, ExamRecordData, Long, ExamRecordData> node5 = new SimpleNode<>(
-                "clearExamDataCache", clearExamDataCacheExecutor, context);
-
-        node1.setFirst(true);
-        node1.setLowerNode(node2);
-        node1.setSleep(PropertyHolder.getInt("oeTask.executor.gainExamData.sleep",
-                DEFAULT_GAIN_EXAM_DATA_EXECUTOR_SLEEP_SECONDS));//单位秒
-
-        node2.setLowerNode(node3);
-        node2.setSleep(PropertyHolder.getInt("oeTask.executor.handInExam.sleep",
-                DEFAULT_HAND_IN_EXAM_EXECUTOR_SLEEP_SECONDS));//单位秒
-
-        node3.setLowerNode(node4);
-        node3.setSleep(PropertyHolder.getInt("oeTask.executor.afterHandInExam.sleep",
-                DEFAULT_AFTER_HAND_IN_EXAM_EXECUTOR_SLEEP_SECONDS));//单位秒
-
-        node4.setLowerNode(node5);
-        node4.setSleep(PropertyHolder.getInt("oeTask.executor.syncExamData.sleep",
-                DEFAULT_SYNC_EXAM_DATA_EXECUTOR_SLEEP_SECONDS));//单位秒
-
-        node5.setSleep(PropertyHolder.getInt("oeTask.executor.clearExamDataCache.sleep",
-                DEFAULT_CLEAR_EXAM_DATA_CACHE_EXECUTOR_SLEEP_SECONDS));//单位秒
-
-        node1.start();
-        node2.start();
-        node3.start();
-        node4.start();
-        node5.start();
-    }
-
-}

+ 22 - 1
jenkins.sh

@@ -1,8 +1,29 @@
 #!/bin/bash
 
 pwd
+PROJECT_NAME="examcloud-core-oe-task"
+
 mkdir -p ~/packages
+cp $PROJECT_NAME-starter/target/$PROJECT_NAME-distribution.zip ~/packages
+
+if [ "deploy" == "$1" ]; then
+  echo "deploy & restart..."
+  mkdir -p ~/project/examcloud
+  cp ~/packages/$PROJECT_NAME-distribution.zip ~/project/examcloud
+
+  cd ~/project/examcloud
+  rm -rf $PROJECT_NAME/lib
+  rm -rf $PROJECT_NAME/config
+
+  unzip -o -q $PROJECT_NAME-distribution.zip
+
+  cd $PROJECT_NAME
+  bash stop.sh
+  BUILD_ID=DONTKILLME
 
-cp examcloud-core-oe-task-starter/target/examcloud-core-oe-task-distribution.zip ~/packages
+  sleep 10s
+  bash start.sh
+  BUILD_ID=DONTKILLME
+fi
 
 echo "finished..."