| | |
| | | import com.zy.core.model.StationObjModel; |
| | | import com.zy.core.model.command.StationCommand; |
| | | import com.zy.core.model.protocol.StationProtocol; |
| | | import com.zy.core.model.protocol.StationTaskBufferItem; |
| | | import com.zy.core.move.StationMoveCoordinator; |
| | | import com.zy.core.thread.StationThread; |
| | | import com.zy.core.utils.station.model.DispatchLimitConfig; |
| | |
| | | |
| | | @Component |
| | | public class StationRegularDispatchProcessor { |
| | | |
| | | private static final long STATION_IN_SLOW_LOG_THRESHOLD_MS = 500L; |
| | | |
| | | @Autowired |
| | | private BasDevpService basDevpService; |
| | |
| | | ) { |
| | | return; |
| | | } |
| | | |
| | | WrkMast wrkMast = wrkMastService.getOne(new QueryWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode())); |
| | | if (wrkMast == null || !Objects.equals(wrkMast.getWrkSts(), WrkStsType.NEW_INBOUND.sts)) { |
| | | return; |
| | | } |
| | | |
| | | Integer crnNo = wrkMast.getCrnNo(); |
| | | BasCrnp basCrnp = basCrnpService.getOne(new QueryWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if (basCrnp == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,未找到堆垛机数据", wrkMast.getWrkNo()); |
| | | return; |
| | | } |
| | | |
| | | int maxInTask = 3; |
| | | if (basCrnp.getMaxInTask() != null) { |
| | | maxInTask = basCrnp.getMaxInTask(); |
| | | } |
| | | |
| | | long count = wrkMastService.count(new QueryWrapper<WrkMast>().eq("crn_no", crnNo).eq("wrk_sts", WrkStsType.INBOUND_STATION_RUN.sts)); |
| | | if(count >= maxInTask) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,堆垛机到达任务上限,稍后执行", wrkMast.getWrkNo()); |
| | | stationProtocol.setSystemWarning(wrkMast.getWrkNo() + "工作,堆垛机到达任务上限,稍后执行"); |
| | | return; |
| | | } |
| | | |
| | | String locNo = wrkMast.getLocNo(); |
| | | FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo); |
| | | if (findCrnNoResult == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,未匹配到堆垛机", wrkMast.getWrkNo()); |
| | | return; |
| | | } |
| | | |
| | | Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationId); |
| | | if (targetStationId == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}站点,搜索入库站点失败", stationId); |
| | | return; |
| | | } |
| | | |
| | | DispatchLimitConfig limitConfig = stationDispatchLoadSupport.getDispatchLimitConfig(stationProtocol.getStationId(), targetStationId); |
| | | int currentStationTaskCount = stationDispatchLoadSupport.countCurrentStationTask(); |
| | | LoadGuardState loadGuardState = stationDispatchLoadSupport.buildLoadGuardState(limitConfig); |
| | | LoopHitResult loopHitResult = stationDispatchLoadSupport.findPathLoopHit( |
| | | limitConfig, |
| | | stationProtocol.getStationId(), |
| | | targetStationId, |
| | | loadGuardState |
| | | ); |
| | | if (stationDispatchLoadSupport.isDispatchBlocked(limitConfig, currentStationTaskCount, loadGuardState, loopHitResult.isThroughLoop())) { |
| | | return; |
| | | } |
| | | |
| | | StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationId, targetStationId, 0); |
| | | if (command == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,获取输送线命令失败", wrkMast.getWrkNo()); |
| | | return; |
| | | } |
| | | |
| | | Date now = new Date(); |
| | | wrkMast.setWrkSts(WrkStsType.INBOUND_STATION_RUN.sts); |
| | | wrkMast.setSourceStaNo(stationProtocol.getStationId()); |
| | | wrkMast.setStaNo(targetStationId); |
| | | wrkMast.setSystemMsg(""); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setModiTime(now); |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | wrkAnalysisService.markInboundStationStart(wrkMast, now); |
| | | boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "stationInExecute"); |
| | | if (offered && stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.recordDispatch( |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | | "stationInExecute", |
| | | command, |
| | | false |
| | | ); |
| | | long totalStartNs = System.nanoTime(); |
| | | Map<String, Long> stepCostMap = new java.util.LinkedHashMap<>(); |
| | | WrkMast wrkMast = null; |
| | | Integer targetStationId = null; |
| | | String targetSource = "unknown"; |
| | | String locNo = null; |
| | | try { |
| | | long stepStartNs = System.nanoTime(); |
| | | wrkMast = wrkMastService.getOne(new QueryWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode())); |
| | | stepCostMap.put("loadWrkByBarcode", elapsedMillis(stepStartNs)); |
| | | if (wrkMast == null || !Objects.equals(wrkMast.getWrkSts(), WrkStsType.NEW_INBOUND.sts)) { |
| | | return; |
| | | } |
| | | News.info("输送站点入库命令下发成功,站点号={},工作号={},命令数据={}", stationId, wrkMast.getWrkNo(), JSON.toJSONString(command)); |
| | | redisUtil.set(RedisKeyType.STATION_IN_EXECUTE_LIMIT.key + stationId, "lock", 5); |
| | | loadGuardState.reserveLoopTask(loopHitResult.getLoopNo()); |
| | | stationDispatchLoadSupport.saveLoopLoadReserve(wrkMast.getWrkNo(), loopHitResult); |
| | | |
| | | Integer crnNo = wrkMast.getCrnNo(); |
| | | BasCrnp basCrnp = basCrnpService.getOne(new QueryWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if (basCrnp == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,未找到堆垛机数据", wrkMast.getWrkNo()); |
| | | return; |
| | | } |
| | | |
| | | int maxInTask = 3; |
| | | if (basCrnp.getMaxInTask() != null) { |
| | | maxInTask = basCrnp.getMaxInTask(); |
| | | } |
| | | |
| | | stepStartNs = System.nanoTime(); |
| | | long count = wrkMastService.count(new QueryWrapper<WrkMast>().eq("crn_no", crnNo).eq("wrk_sts", WrkStsType.INBOUND_STATION_RUN.sts)); |
| | | stepCostMap.put("countCrnInboundRunTask", elapsedMillis(stepStartNs)); |
| | | if(count >= maxInTask) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,堆垛机到达任务上限,稍后执行", wrkMast.getWrkNo()); |
| | | stationProtocol.setSystemWarning(wrkMast.getWrkNo() + "工作," + crnNo + "号堆垛机到达任务上限,稍后执行"); |
| | | return; |
| | | } |
| | | |
| | | locNo = wrkMast.getLocNo(); |
| | | stepStartNs = System.nanoTime(); |
| | | FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo); |
| | | stepCostMap.put("resolveCrnByLocNo", elapsedMillis(stepStartNs)); |
| | | if (findCrnNoResult == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,未匹配到堆垛机", wrkMast.getWrkNo()); |
| | | return; |
| | | } |
| | | |
| | | stepStartNs = System.nanoTime(); |
| | | CommonService.InStationResolveResult resolveResult = commonService.resolveInStationId(findCrnNoResult, stationId); |
| | | stepCostMap.put("resolveInboundTargetStation", elapsedMillis(stepStartNs)); |
| | | targetStationId = resolveResult == null ? null : resolveResult.getTargetStationId(); |
| | | targetSource = resolveResult == null ? "unknown" : (resolveResult.isCacheHit() ? "cache" : "search"); |
| | | if (targetStationId == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}站点,搜索入库站点失败", stationId); |
| | | return; |
| | | } |
| | | |
| | | stepStartNs = System.nanoTime(); |
| | | DispatchLimitConfig limitConfig = stationDispatchLoadSupport.getDispatchLimitConfig(stationProtocol.getStationId(), targetStationId); |
| | | int currentStationTaskCount = stationDispatchLoadSupport.countCurrentStationTask(); |
| | | LoadGuardState loadGuardState = stationDispatchLoadSupport.buildLoadGuardState(limitConfig); |
| | | stepCostMap.put("buildLoopGuardState", elapsedMillis(stepStartNs)); |
| | | |
| | | stepStartNs = System.nanoTime(); |
| | | StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationId, targetStationId, 0); |
| | | stepCostMap.put("buildMoveCommand", elapsedMillis(stepStartNs)); |
| | | if (command == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "{}工作,获取输送线命令失败", wrkMast.getWrkNo()); |
| | | return; |
| | | } |
| | | |
| | | stepStartNs = System.nanoTime(); |
| | | LoopHitResult loopHitResult = stationDispatchLoadSupport.findPathLoopHitByNavigatePath(command.getNavigatePath(), loadGuardState); |
| | | stepCostMap.put("evaluateLoopPath", elapsedMillis(stepStartNs)); |
| | | if (stationDispatchLoadSupport.isDispatchBlocked(limitConfig, currentStationTaskCount, loadGuardState, loopHitResult.isThroughLoop())) { |
| | | return; |
| | | } |
| | | |
| | | stepStartNs = System.nanoTime(); |
| | | Date now = new Date(); |
| | | wrkMast.setWrkSts(WrkStsType.INBOUND_STATION_RUN.sts); |
| | | wrkMast.setSourceStaNo(stationProtocol.getStationId()); |
| | | wrkMast.setStaNo(targetStationId); |
| | | wrkMast.setSystemMsg(""); |
| | | wrkMast.setIoTime(now); |
| | | wrkMast.setModiTime(now); |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | wrkAnalysisService.markInboundStationStart(wrkMast, now); |
| | | // 先记录 session 再入队命令,避免消费线程在 session 写入 Redis 前取到命令导致路由校验失败。 |
| | | if (stationMoveCoordinator != null) { |
| | | stationMoveCoordinator.recordDispatch( |
| | | wrkMast.getWrkNo(), |
| | | stationProtocol.getStationId(), |
| | | "stationInExecute", |
| | | command, |
| | | false |
| | | ); |
| | | } |
| | | boolean offered = offerDevpCommandWithDedup(basDevp.getDevpNo(), command, "stationInExecute"); |
| | | if (offered) { |
| | | News.info("输送站点入库命令下发成功,站点号={},工作号={},命令数据={}", stationId, wrkMast.getWrkNo(), JSON.toJSONString(command)); |
| | | } else { |
| | | News.warn("输送站点入库命令入队被拒绝(可能重复),站点号={},工作号={}", stationId, wrkMast.getWrkNo()); |
| | | } |
| | | redisUtil.set(RedisKeyType.STATION_IN_EXECUTE_LIMIT.key + stationId, "lock", 5); |
| | | loadGuardState.reserveLoopTask(loopHitResult.getLoopNo()); |
| | | stationDispatchLoadSupport.saveLoopLoadReserve(wrkMast.getWrkNo(), loopHitResult); |
| | | } |
| | | stepCostMap.put("updateWrkAndDispatch", elapsedMillis(stepStartNs)); |
| | | } finally { |
| | | long totalCostMs = elapsedMillis(totalStartNs); |
| | | if (totalCostMs >= STATION_IN_SLOW_LOG_THRESHOLD_MS) { |
| | | News.warn("stationInExecute耗时较长,stationId={},barcode={},wrkNo={},locNo={},targetStaNo={},targetSource={},stepCosts={},totalCost={}ms", |
| | | stationId, |
| | | stationProtocol.getBarcode(), |
| | | wrkMast == null ? null : wrkMast.getWrkNo(), |
| | | locNo, |
| | | targetStationId, |
| | | targetSource, |
| | | JSON.toJSONString(stepCostMap), |
| | | totalCostMs); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private long elapsedMillis(long startNs) { |
| | | long elapsedNs = System.nanoTime() - startNs; |
| | | return elapsedNs <= 0L ? 0L : elapsedNs / 1_000_000L; |
| | | } |
| | | } |