diff --git a/detection/src/main/java/com/njcn/gather/detection/controller/PreDetectionController.java b/detection/src/main/java/com/njcn/gather/detection/controller/PreDetectionController.java index 3f0acee7..29e38a86 100644 --- a/detection/src/main/java/com/njcn/gather/detection/controller/PreDetectionController.java +++ b/detection/src/main/java/com/njcn/gather/detection/controller/PreDetectionController.java @@ -11,6 +11,7 @@ import com.njcn.gather.detection.lock.DetectionLock; import com.njcn.gather.detection.lock.DetectionLockManager; import com.njcn.gather.detection.lock.DetectionLockManager.AcquireResult; import com.njcn.gather.detection.pojo.enums.DetectionResponseEnum; +import com.njcn.gather.detection.pojo.param.ClosePreTestParam; import com.njcn.gather.detection.pojo.param.ContrastDetectionParam; import com.njcn.gather.detection.pojo.param.FormalProgressParam; import com.njcn.gather.detection.pojo.param.PreDetectionParam; @@ -66,8 +67,7 @@ public class PreDetectionController extends BaseController { boolean keepLock = false; try { // 重置 FormalTestManager 暂停计数残留,避免上次暂停残留计数误触发 R4 - FormalTestManager.stopTime = 0; - FormalTestManager.hasStopFlag = false; + FormalTestManager.clearPauseState(); preDetectionService.sourceCommunicationCheck(param); keepLock = true; return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); @@ -116,8 +116,7 @@ public class PreDetectionController extends BaseController { // 同步阶段抛异常时回滚锁,理由同 startPreTest boolean keepLock = false; try { - FormalTestManager.stopTime = 0; - FormalTestManager.hasStopFlag = false; + FormalTestManager.clearPauseState(); preDetectionService.sendScript(param); keepLock = true; return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); @@ -170,20 +169,30 @@ public class PreDetectionController extends BaseController { /** - * 暂停检测 + * 暂停检测,兼容旧前端:默认等待当前小项完成后暂停。 */ @GetMapping("/closePreTest") @OperateInfo @ApiOperation("暂停检测") - @ApiImplicitParam(name = "param", value = "参数", required = true) public HttpResult temStopTest() { + return closePreTest(new ClosePreTestParam()); + } + + /** + * 暂停检测 + */ + @PostMapping("/closePreTest") + @OperateInfo + @ApiOperation("暂停检测") + public HttpResult closePreTest(@RequestBody(required = false) ClosePreTestParam param) { String methodDescribe = getMethodDescribe("temStopTest"); HttpResult busy = requireHolderSelf(); if (busy != null) { return busy; } // 暂停保持锁(spec §2.3),不释放 - preDetectionService.temStopTest(); + ClosePreTestParam request = param == null ? new ClosePreTestParam() : param; + preDetectionService.temStopTest(RequestUtil.getLoginNameByToken(), request.isWaitCurrentItem()); return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); } @@ -252,8 +261,7 @@ public class PreDetectionController extends BaseController { // 同步阶段抛异常时回滚锁,理由同 startPreTest boolean keepLock = false; try { - FormalTestManager.stopTime = 0; - FormalTestManager.hasStopFlag = false; + FormalTestManager.clearPauseState(); preDetectionService.startContrastTest(param); keepLock = true; return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); diff --git a/detection/src/main/java/com/njcn/gather/detection/handler/SocketDevResponseService.java b/detection/src/main/java/com/njcn/gather/detection/handler/SocketDevResponseService.java index b7a5631d..d6e7e6ce 100644 --- a/detection/src/main/java/com/njcn/gather/detection/handler/SocketDevResponseService.java +++ b/detection/src/main/java/com/njcn/gather/detection/handler/SocketDevResponseService.java @@ -1233,6 +1233,7 @@ public class SocketDevResponseService { } FormalTestManager.currentIssue = firstIssue; FormalTestManager.resumeFormalStartTime = LocalDateTime.now(); + sendFormalCurrentItem(param, firstIssue, type); SocketMsg socketMsg = new SocketMsg<>(); socketMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue()); @@ -1244,6 +1245,23 @@ public class SocketDevResponseService { WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO)); } + private void sendFormalCurrentItem(PreDetectionParam param, SourceIssue issue, String displayType) { + if (issue == null) { + return; + } + FormalTestManager.currentIssue = issue; + String type = StrUtil.isNotBlank(displayType) ? displayType : issue.getType(); + PowerIndexEnum powerIndexEnum = PowerIndexEnum.getByKey(type); + String typeName = powerIndexEnum == null ? type : powerIndexEnum.getDesc(); + FormalCurrentItemVO currentItem = new FormalCurrentItemVO( + type, + typeName, + issue.getIndex(), + StrUtil.blankToDefault(issue.getDesc(), "当前检测小项") + ); + WebServiceManager.sendDetectionMessage(param.getUserPageId(), "formal_current_item", "current", currentItem, null); + } + /** * 添加并且按照slowValueTimeList中的时间去重 * @@ -1292,6 +1310,11 @@ public class SocketDevResponseService { DevData devData = JSON.parseObject(data, DevData.class); //DevData的id值为 设备id_通道号 这种形式 SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode()); SourceIssue sourceIssue = SocketManager.getSourceList().get(0); + if (FormalTestManager.isImmediatePause()) { + successComm.clear(); + FormalTestManager.realDataXiList.clear(); + return; + } switch (Objects.requireNonNull(dictDataEnumByCode)) { case SUCCESS: @@ -1377,9 +1400,10 @@ public class SocketDevResponseService { WebServiceManager.sendDetectionMessage(param.getUserPageId(), socketDataMsg.getRequestId().split(CnSocketUtil.STEP_TAG)[1] + CnSocketUtil.END_TAG, null, resultList, null); } //在这一步判断是否已经触发暂停按钮 - if (FormalTestManager.stopFlag && CollUtil.isNotEmpty(SocketManager.getSourceList())) { - FormalTestManager.stopTime = 0; - FormalTestManager.hasStopFlag = true; + if (FormalTestManager.stopFlag + && FormalTestManager.isWaitCurrentItemPause() + && CollUtil.isNotEmpty(SocketManager.getSourceList())) { + FormalTestManager.markPausedAfterCurrentItem(); successComm.clear(); FormalTestManager.realDataXiList.clear(); sendWebSocket(param.getUserPageId(), "preStopTest", "stop", null); @@ -1406,6 +1430,8 @@ public class SocketDevResponseService { xuMsg.setOperateCode(SourceOperateCodeEnum.OPER_GATHER.getValue()); xuMsg.setData(JSON.toJSONString(sourceIssues)); xuMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + type); + FormalTestManager.currentIssue = sourceIssues; + sendFormalCurrentItem(param, sourceIssues, type); SocketManager.sendMsg(param.getUserPageId() + CnSocketUtil.SOURCE_TAG, JSON.toJSONString(xuMsg)); } else { //TODO 是否最终检测完成需要推送给用户 @@ -1799,9 +1825,7 @@ public class SocketDevResponseService { SocketManager.clockMap.clear(); successComm.clear(); - FormalTestManager.stopFlag = false; - FormalTestManager.hasStopFlag = false; - FormalTestManager.stopTime = 0; + FormalTestManager.clearPauseState(); //初始化相序集合 this.devInfo.clear(); diff --git a/detection/src/main/java/com/njcn/gather/detection/pojo/param/ClosePreTestParam.java b/detection/src/main/java/com/njcn/gather/detection/pojo/param/ClosePreTestParam.java new file mode 100644 index 00000000..137b14e3 --- /dev/null +++ b/detection/src/main/java/com/njcn/gather/detection/pojo/param/ClosePreTestParam.java @@ -0,0 +1,13 @@ +package com.njcn.gather.detection.pojo.param; + +import lombok.Data; + +@Data +public class ClosePreTestParam { + + private Boolean waitCurrentItem; + + public boolean isWaitCurrentItem() { + return !Boolean.FALSE.equals(waitCurrentItem); + } +} diff --git a/detection/src/main/java/com/njcn/gather/detection/pojo/vo/FormalCurrentItemVO.java b/detection/src/main/java/com/njcn/gather/detection/pojo/vo/FormalCurrentItemVO.java new file mode 100644 index 00000000..7129be57 --- /dev/null +++ b/detection/src/main/java/com/njcn/gather/detection/pojo/vo/FormalCurrentItemVO.java @@ -0,0 +1,20 @@ +package com.njcn.gather.detection.pojo.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FormalCurrentItemVO { + + private String type; + + private String typeName; + + private Integer index; + + private String desc; +} diff --git a/detection/src/main/java/com/njcn/gather/detection/service/PreDetectionService.java b/detection/src/main/java/com/njcn/gather/detection/service/PreDetectionService.java index d1780181..f95204a2 100644 --- a/detection/src/main/java/com/njcn/gather/detection/service/PreDetectionService.java +++ b/detection/src/main/java/com/njcn/gather/detection/service/PreDetectionService.java @@ -30,7 +30,7 @@ public interface PreDetectionService { void coefficientCheck(PreDetectionParam param); - boolean temStopTest(); + boolean temStopTest(String userPageId, boolean waitCurrentItem); boolean restartTemTest(PreDetectionParam param); diff --git a/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java b/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java index ee42154e..28c9b184 100644 --- a/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java +++ b/detection/src/main/java/com/njcn/gather/detection/service/impl/PreDetectionServiceImpl.java @@ -277,8 +277,20 @@ public class PreDetectionServiceImpl implements PreDetectionService { } @Override - public boolean temStopTest() { - FormalTestManager.stopFlag = true; + public boolean temStopTest(String userPageId, boolean waitCurrentItem) { + if (waitCurrentItem) { + FormalTestManager.requestWaitPause(); + return true; + } + + FormalTestManager.requestImmediatePause(); + SocketManager.ensureFirst(FormalTestManager.currentIssue); + socketDevResponseService.initRestart(); + PreDetectionParam runtimeParam = WebServiceManager.getPreDetectionParam(userPageId); + String pushUserPageId = runtimeParam != null && StrUtil.isNotBlank(runtimeParam.getUserPageId()) + ? runtimeParam.getUserPageId() + : userPageId; + WebServiceManager.sendDetectionMessage(pushUserPageId, "preStopTest", "stop", null, null); return true; } @@ -291,7 +303,7 @@ public class PreDetectionServiceImpl implements PreDetectionService { } runtimeParam = param; } - FormalTestManager.stopFlag = false; + FormalTestManager.clearPauseState(); socketDevResponseService.initRestart(); List sourceIssueList = SocketManager.getSourceList(); if (StrUtil.isBlank(runtimeParam.getSourceName()) && StrUtil.isNotBlank(runtimeParam.getSourceId())) { diff --git a/detection/src/main/java/com/njcn/gather/detection/util/socket/FormalTestManager.java b/detection/src/main/java/com/njcn/gather/detection/util/socket/FormalTestManager.java index b9e15aa4..08f070f1 100644 --- a/detection/src/main/java/com/njcn/gather/detection/util/socket/FormalTestManager.java +++ b/detection/src/main/java/com/njcn/gather/detection/util/socket/FormalTestManager.java @@ -84,6 +84,14 @@ public class FormalTestManager { */ public static Integer stopTime = 0; + public enum PauseMode { + NONE, + WAIT_CURRENT_ITEM, + IMMEDIATE + } + + public static PauseMode pauseMode = PauseMode.NONE; + /** * 当前正在检测的计划 */ @@ -233,11 +241,45 @@ public class FormalTestManager { public static Integer longFlickerDataCount; + public static void requestWaitPause() { + stopFlag = true; + hasStopFlag = false; + stopTime = 0; + pauseMode = PauseMode.WAIT_CURRENT_ITEM; + } - public static void clearFormalRuntime() { + public static void requestImmediatePause() { + stopFlag = true; + hasStopFlag = true; + stopTime = 0; + pauseMode = PauseMode.IMMEDIATE; + } + + public static void markPausedAfterCurrentItem() { + stopFlag = true; + hasStopFlag = true; + stopTime = 0; + pauseMode = PauseMode.WAIT_CURRENT_ITEM; + } + + public static boolean isWaitCurrentItemPause() { + return pauseMode == PauseMode.WAIT_CURRENT_ITEM; + } + + public static boolean isImmediatePause() { + return pauseMode == PauseMode.IMMEDIATE; + } + + public static void clearPauseState() { stopFlag = false; hasStopFlag = false; stopTime = 0; + pauseMode = PauseMode.NONE; + } + + + public static void clearFormalRuntime() { + clearPauseState(); resumeFormalPending = false; resumeNextSort = null; resumeBaseFormalCheckTime = null; diff --git a/detection/src/main/java/com/njcn/gather/detection/util/socket/SocketManager.java b/detection/src/main/java/com/njcn/gather/detection/util/socket/SocketManager.java index faaeef4c..c45f5a63 100644 --- a/detection/src/main/java/com/njcn/gather/detection/util/socket/SocketManager.java +++ b/detection/src/main/java/com/njcn/gather/detection/util/socket/SocketManager.java @@ -326,6 +326,22 @@ public class SocketManager { sourceIssueList.removeIf(s -> index.equals(s.getIndex())); } + public static void ensureFirst(SourceIssue issue) { + if (issue == null || issue.getIndex() == null) { + return; + } + if (sourceIssueList.isEmpty()) { + sourceIssueList.add(0, issue); + return; + } + SourceIssue first = sourceIssueList.get(0); + if (issue.getIndex().equals(first.getIndex())) { + return; + } + sourceIssueList.removeIf(s -> issue.getIndex().equals(s.getIndex())); + sourceIssueList.add(0, issue); + } + public static void delSourceTarget(String sourceTag) { targetMap.remove(sourceTag); } diff --git a/detection/src/main/java/com/njcn/gather/detection/util/socket/cilent/NettyDevClientHandler.java b/detection/src/main/java/com/njcn/gather/detection/util/socket/cilent/NettyDevClientHandler.java index bc1b35e9..17531f60 100644 --- a/detection/src/main/java/com/njcn/gather/detection/util/socket/cilent/NettyDevClientHandler.java +++ b/detection/src/main/java/com/njcn/gather/detection/util/socket/cilent/NettyDevClientHandler.java @@ -273,8 +273,7 @@ public class NettyDevClientHandler extends SimpleChannelInboundHandler { DetectionLockManager.getInstance().releaseIfHeldBy(cur.getUserId(), "PAUSE_TIMEOUT"); } // 重置 FormalTestManager 状态,避免下次进入误判 - FormalTestManager.stopTime = 0; - FormalTestManager.hasStopFlag = false; + FormalTestManager.clearPauseState(); } } diff --git a/detection/src/test/java/com/njcn/gather/detection/util/socket/FormalTestManagerPauseTest.java b/detection/src/test/java/com/njcn/gather/detection/util/socket/FormalTestManagerPauseTest.java new file mode 100644 index 00000000..49be313a --- /dev/null +++ b/detection/src/test/java/com/njcn/gather/detection/util/socket/FormalTestManagerPauseTest.java @@ -0,0 +1,74 @@ +package com.njcn.gather.detection.util.socket; + +import com.njcn.gather.script.pojo.po.SourceIssue; +import org.junit.After; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +public class FormalTestManagerPauseTest { + + @After + public void tearDown() { + FormalTestManager.clearFormalRuntime(); + SocketManager.clearFormalRuntime(); + } + + @Test + public void requestWaitPause_keepsPauseDeferredUntilCurrentItemFinishes() { + FormalTestManager.requestWaitPause(); + + assertTrue(FormalTestManager.stopFlag); + assertFalse(FormalTestManager.hasStopFlag); + assertTrue(FormalTestManager.isWaitCurrentItemPause()); + assertFalse(FormalTestManager.isImmediatePause()); + } + + @Test + public void requestImmediatePause_entersPausedStateImmediately() { + FormalTestManager.requestImmediatePause(); + + assertTrue(FormalTestManager.stopFlag); + assertTrue(FormalTestManager.hasStopFlag); + assertFalse(FormalTestManager.isWaitCurrentItemPause()); + assertTrue(FormalTestManager.isImmediatePause()); + assertEquals(Integer.valueOf(0), FormalTestManager.stopTime); + } + + @Test + public void ensureFirst_keepsCurrentIssueAtQueueHead() { + SourceIssue first = issue(1, "V"); + SourceIssue second = issue(2, "I"); + SocketManager.addSourceList(new ArrayList<>(Arrays.asList(second))); + + SocketManager.ensureFirst(first); + + assertSame(first, SocketManager.getSourceList().get(0)); + assertSame(second, SocketManager.getSourceList().get(1)); + } + + @Test + public void ensureFirst_doesNotDuplicateExistingHead() { + SourceIssue first = issue(1, "V"); + SocketManager.addSourceList(new ArrayList<>(Arrays.asList(first))); + + SocketManager.ensureFirst(first); + + assertEquals(1, SocketManager.getSourceList().size()); + assertSame(first, SocketManager.getSourceList().get(0)); + } + + private SourceIssue issue(Integer index, String type) { + SourceIssue issue = new SourceIssue(); + issue.setIndex(index); + issue.setType(type); + issue.setDesc(type + " item"); + return issue; + } +}