From 720e0926fa1c94b952c26e111206c5d6e1ed5ba2 Mon Sep 17 00:00:00 2001
From: lsh <lsh@163.com>
Date: 星期二, 21 四月 2026 15:59:49 +0800
Subject: [PATCH] Merge branch 'master' of http://47.97.1.152:5880/r/zy-wcs-master

---
 src/main/java/com/zy/core/utils/station/StationOutboundDecisionSupport.java |  125 +++++++++++++++++++++++++++++++++++------
 1 files changed, 105 insertions(+), 20 deletions(-)

diff --git a/src/main/java/com/zy/core/utils/station/StationOutboundDecisionSupport.java b/src/main/java/com/zy/core/utils/station/StationOutboundDecisionSupport.java
index 02018dd..f6073dc 100644
--- a/src/main/java/com/zy/core/utils/station/StationOutboundDecisionSupport.java
+++ b/src/main/java/com/zy/core/utils/station/StationOutboundDecisionSupport.java
@@ -26,6 +26,7 @@
 import com.zy.core.thread.StationThread;
 import com.zy.core.utils.station.model.CircleTargetCandidate;
 import com.zy.core.utils.station.model.OutOrderDispatchDecision;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -37,8 +38,14 @@
 import java.util.Map;
 import java.util.Objects;
 
+@Slf4j
 @Component
 public class StationOutboundDecisionSupport {
+
+    private static final long PATH_CALC_SLOW_THRESHOLD_MS = 50L;
+    private static final long OUT_ORDER_DECISION_SLOW_THRESHOLD_MS = 100L;
+    private static final long CURRENT_OUT_ORDER_DECISION_SLOW_THRESHOLD_MS = 100L;
+    private static final long CIRCLE_TARGET_EVAL_SLOW_THRESHOLD_MS = 100L;
 
     @Autowired
     private WrkMastService wrkMastService;
@@ -113,6 +120,7 @@
                                                                     WrkMast wrkMast,
                                                                     List<Integer> outOrderStationIds,
                                                                     Double pathLenFactor) {
+        long startMs = System.currentTimeMillis();
         if (wrkMast == null || wrkMast.getStaNo() == null) {
             return null;
         }
@@ -120,6 +128,7 @@
         if (!shouldApplyOutOrder(wrkMast, outOrderStationIds)) {
             return OutOrderDispatchDecision.direct(wrkMast.getStaNo());
         }
+        long resolveDispatchTargetStartMs = System.currentTimeMillis();
         Integer dispatchStationId = resolveDispatchOutOrderTarget(
                 wrkMast,
                 wrkMast.getSourceStaNo(),
@@ -128,18 +137,33 @@
                 pathLenFactor,
                 decisionPathCache
         );
+        long resolveDispatchTargetCostMs = System.currentTimeMillis() - resolveDispatchTargetStartMs;
         if (dispatchStationId == null) {
             return null;
         }
-        if (isCurrentOutOrderDispatchStation(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache)) {
-            return resolveCurrentOutOrderDispatchDecision(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache);
-        }
-        if (!Objects.equals(dispatchStationId, wrkMast.getStaNo())
+        long currentDispatchCheckStartMs = System.currentTimeMillis();
+        boolean currentOutOrderDispatchStation = isCurrentOutOrderDispatchStation(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache);
+        long currentDispatchCheckCostMs = System.currentTimeMillis() - currentDispatchCheckStartMs;
+        OutOrderDispatchDecision decision;
+        if (currentOutOrderDispatchStation) {
+            decision = resolveCurrentOutOrderDispatchDecision(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache);
+        } else if (!Objects.equals(dispatchStationId, wrkMast.getStaNo())
                 && isCurrentOutOrderStation(currentStationId, outOrderStationIds)
                 && isWatchingCircleArrival(wrkMast.getWrkNo(), currentStationId)) {
-            return OutOrderDispatchDecision.circle(dispatchStationId, null, false);
+            decision = OutOrderDispatchDecision.circle(dispatchStationId, null, false);
+        } else {
+            decision = OutOrderDispatchDecision.direct(dispatchStationId);
         }
-        return OutOrderDispatchDecision.direct(dispatchStationId);
+        long totalCostMs = System.currentTimeMillis() - startMs;
+        log.info("resolveOutboundDispatchDecision profile, taskNo={}, currentStationId={}, finalTargetStationId={}, dispatchStationId={}, currentOutOrderDispatchStation={}, decision={}, circle={}, resolveDispatchTargetCostMs={}ms, currentDispatchCheckCostMs={}ms, totalCostMs={}ms",
+                wrkMast.getWrkNo(), currentStationId, wrkMast.getStaNo(), dispatchStationId, currentOutOrderDispatchStation,
+                decision == null ? null : decision.getTargetStationId(), decision != null && decision.isCircle(),
+                resolveDispatchTargetCostMs, currentDispatchCheckCostMs, totalCostMs);
+        if (totalCostMs > OUT_ORDER_DECISION_SLOW_THRESHOLD_MS) {
+            log.warn("resolveOutboundDispatchDecision slow, taskNo={}, currentStationId={}, totalCostMs={}ms, resolveDispatchTargetCostMs={}ms, currentDispatchCheckCostMs={}ms",
+                    wrkMast.getWrkNo(), currentStationId, totalCostMs, resolveDispatchTargetCostMs, currentDispatchCheckCostMs);
+        }
+        return decision;
     }
 
     public void syncOutOrderWatchState(WrkMast wrkMast,
@@ -207,26 +231,39 @@
                                                         Integer targetStationId,
                                                         Double pathLenFactor,
                                                         DecisionPathCache decisionPathCache) {
+        long startMs = System.currentTimeMillis();
         Double normalizedFactor = normalizePathLenFactor(pathLenFactor);
         Integer currentTaskNo = wrkMast == null ? null : wrkMast.getWrkNo();
+        boolean cacheHit = false;
+        List<NavigateNode> path;
         if (decisionPathCache == null) {
-            if (currentTaskNo == null) {
-                return navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, null, normalizedFactor);
+            path = currentTaskNo == null
+                    ? navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, null, normalizedFactor)
+                    : navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, currentTaskNo, normalizedFactor);
+        } else {
+            String cacheKey = buildPathCacheKey(currentTaskNo, sourceStationId, targetStationId, normalizedFactor);
+            List<NavigateNode> cachedPath = decisionPathCache.pathMap.get(cacheKey);
+            if (cachedPath != null) {
+                cacheHit = true;
+                path = cachedPath;
+            } else {
+                path = currentTaskNo == null
+                        ? navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, null, normalizedFactor)
+                        : navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, currentTaskNo, normalizedFactor);
+                if (path == null) {
+                    path = Collections.emptyList();
+                }
+                decisionPathCache.pathMap.put(cacheKey, path);
             }
-            return navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, currentTaskNo, normalizedFactor);
         }
-        String cacheKey = buildPathCacheKey(currentTaskNo, sourceStationId, targetStationId, normalizedFactor);
-        List<NavigateNode> cachedPath = decisionPathCache.pathMap.get(cacheKey);
-        if (cachedPath != null) {
-            return cachedPath;
-        }
-        List<NavigateNode> path = currentTaskNo == null
-                ? navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, null, normalizedFactor)
-                : navigateUtils.calcOptimalPathByStationId(sourceStationId, targetStationId, currentTaskNo, normalizedFactor);
         if (path == null) {
             path = Collections.emptyList();
         }
-        decisionPathCache.pathMap.put(cacheKey, path);
+        long costMs = System.currentTimeMillis() - startMs;
+        if (costMs > PATH_CALC_SLOW_THRESHOLD_MS) {
+            log.warn("calcOutboundNavigatePath slow, taskNo={}, sourceStationId={}, targetStationId={}, pathCacheHit={}, pathNodeCount={}, pathCostMs={}ms",
+                    currentTaskNo, sourceStationId, targetStationId, cacheHit, path.size(), costMs);
+        }
         return path;
     }
 
@@ -301,10 +338,12 @@
                                                                            List<Integer> outOrderStationIds,
                                                                            Double pathLenFactor,
                                                                            DecisionPathCache decisionPathCache) {
+        long startMs = System.currentTimeMillis();
         if (!isCurrentOutOrderDispatchStation(currentStationId, wrkMast, outOrderStationIds, pathLenFactor, decisionPathCache)) {
             return null;
         }
 
+        long batchQueryStartMs = System.currentTimeMillis();
         List<WrkMast> batchWrkList = wrkMastService.list(new QueryWrapper<WrkMast>()
                 .eq("io_type", WrkIoType.OUT.id)
                 .notIn("wrk_sts",
@@ -314,6 +353,7 @@
                 .eq("batch", wrkMast.getBatch())
                 .orderByAsc("batch_seq")
                 .orderByAsc("wrk_no"));
+        long batchQueryCostMs = System.currentTimeMillis() - batchQueryStartMs;
         if (batchWrkList.isEmpty()) {
             return OutOrderDispatchDecision.direct(wrkMast.getStaNo());
         }
@@ -326,26 +366,36 @@
         }
 
         List<NavigateNode> initPath;
+        long initPathStartMs = System.currentTimeMillis();
         try {
             initPath = calcOutboundNavigatePath(wrkMast, wrkMast.getSourceStaNo(), wrkMast.getStaNo(), pathLenFactor, decisionPathCache);
         } catch (Exception e) {
             News.taskInfo(wrkMast.getWrkNo(), "鎵规:{} 璁$畻鎺掑簭璺緞澶辫触锛屽綋鍓嶇珯鐐�={}", wrkMast.getBatch(), currentStationId);
             return null;
         }
+        long initPathCostMs = System.currentTimeMillis() - initPathStartMs;
 
+        long batchSeqScanStartMs = System.currentTimeMillis();
         Integer seq = getOutStationBatchSeq(initPath, currentStationId, wrkMast.getBatch());
+        long batchSeqScanCostMs = System.currentTimeMillis() - batchSeqScanStartMs;
         boolean toTarget = seq == null
                 ? currentBatchSeq.equals(wrkMast.getBatchSeq())
                 : Integer.valueOf(seq + 1).equals(wrkMast.getBatchSeq());
         if (toTarget) {
-            if (hasReachableOutReleaseSlot(wrkMast, currentStationId, wrkMast.getStaNo(), pathLenFactor, decisionPathCache)) {
+            long releaseSlotCheckStartMs = System.currentTimeMillis();
+            boolean hasReachableReleaseSlot = hasReachableOutReleaseSlot(wrkMast, currentStationId, wrkMast.getStaNo(), pathLenFactor, decisionPathCache);
+            long releaseSlotCheckCostMs = System.currentTimeMillis() - releaseSlotCheckStartMs;
+            if (hasReachableReleaseSlot) {
                 return OutOrderDispatchDecision.direct(wrkMast.getStaNo());
             }
+            long loopEvalStartMs = System.currentTimeMillis();
             StationTaskLoopService.LoopEvaluation loopEvaluation = evaluateOutOrderLoop(
                     wrkMast.getWrkNo(),
                     currentStationId,
                     outOrderStationIds
             );
+            long loopEvalCostMs = System.currentTimeMillis() - loopEvalStartMs;
+            long circleTargetEvalStartMs = System.currentTimeMillis();
             Integer circleTarget = resolveNextCircleOrderTarget(
                     wrkMast,
                     currentStationId,
@@ -354,6 +404,15 @@
                     pathLenFactor,
                     decisionPathCache
             );
+            long circleTargetEvalCostMs = System.currentTimeMillis() - circleTargetEvalStartMs;
+            long totalCostMs = System.currentTimeMillis() - startMs;
+            log.info("resolveCurrentOutOrderDispatchDecision profile, taskNo={}, currentStationId={}, batch={}, currentBatchSeq={}, taskBatchSeq={}, toTarget={}, batchQueryCostMs={}ms, initPathCostMs={}ms, batchSeqScanCostMs={}ms, releaseSlotCheckCostMs={}ms, loopEvalCostMs={}ms, circleTargetEvalCostMs={}ms, totalCostMs={}ms, circleTarget={}",
+                    wrkMast.getWrkNo(), currentStationId, wrkMast.getBatch(), currentBatchSeq, wrkMast.getBatchSeq(), toTarget,
+                    batchQueryCostMs, initPathCostMs, batchSeqScanCostMs, releaseSlotCheckCostMs, loopEvalCostMs, circleTargetEvalCostMs, totalCostMs, circleTarget);
+            if (totalCostMs > CURRENT_OUT_ORDER_DECISION_SLOW_THRESHOLD_MS) {
+                log.warn("resolveCurrentOutOrderDispatchDecision slow, taskNo={}, currentStationId={}, totalCostMs={}ms, batchQueryCostMs={}ms, initPathCostMs={}ms, batchSeqScanCostMs={}ms, releaseSlotCheckCostMs={}ms, circleTargetEvalCostMs={}ms",
+                        wrkMast.getWrkNo(), currentStationId, totalCostMs, batchQueryCostMs, initPathCostMs, batchSeqScanCostMs, releaseSlotCheckCostMs, circleTargetEvalCostMs);
+            }
             if (circleTarget == null) {
                 News.taskInfo(wrkMast.getWrkNo(), "鐩爣绔欏綋鍓嶄笉鍙繘锛屼笖鏈壘鍒板彲鎵ц鐨勪笅涓�鎺掑簭妫�娴嬬偣锛屽綋鍓嶇珯鐐�={}", currentStationId);
                 return null;
@@ -361,11 +420,14 @@
             return OutOrderDispatchDecision.circle(circleTarget, loopEvaluation, true);
         }
 
+        long loopEvalStartMs = System.currentTimeMillis();
         StationTaskLoopService.LoopEvaluation loopEvaluation = evaluateOutOrderLoop(
                 wrkMast.getWrkNo(),
                 currentStationId,
                 outOrderStationIds
         );
+        long loopEvalCostMs = System.currentTimeMillis() - loopEvalStartMs;
+        long circleTargetEvalStartMs = System.currentTimeMillis();
         Integer circleTarget = resolveNextCircleOrderTarget(
                 wrkMast,
                 currentStationId,
@@ -374,6 +436,15 @@
                 pathLenFactor,
                 decisionPathCache
         );
+        long circleTargetEvalCostMs = System.currentTimeMillis() - circleTargetEvalStartMs;
+        long totalCostMs = System.currentTimeMillis() - startMs;
+        log.info("resolveCurrentOutOrderDispatchDecision profile, taskNo={}, currentStationId={}, batch={}, currentBatchSeq={}, taskBatchSeq={}, toTarget={}, batchQueryCostMs={}ms, initPathCostMs={}ms, batchSeqScanCostMs={}ms, loopEvalCostMs={}ms, circleTargetEvalCostMs={}ms, totalCostMs={}ms, circleTarget={}",
+                wrkMast.getWrkNo(), currentStationId, wrkMast.getBatch(), currentBatchSeq, wrkMast.getBatchSeq(), toTarget,
+                batchQueryCostMs, initPathCostMs, batchSeqScanCostMs, loopEvalCostMs, circleTargetEvalCostMs, totalCostMs, circleTarget);
+        if (totalCostMs > CURRENT_OUT_ORDER_DECISION_SLOW_THRESHOLD_MS) {
+            log.warn("resolveCurrentOutOrderDispatchDecision slow, taskNo={}, currentStationId={}, totalCostMs={}ms, batchQueryCostMs={}ms, initPathCostMs={}ms, batchSeqScanCostMs={}ms, circleTargetEvalCostMs={}ms",
+                    wrkMast.getWrkNo(), currentStationId, totalCostMs, batchQueryCostMs, initPathCostMs, batchSeqScanCostMs, circleTargetEvalCostMs);
+        }
         if (circleTarget == null) {
             News.taskInfo(wrkMast.getWrkNo(), "鏈壘鍒板彲鎵ц鐨勪笅涓�鎺掑簭妫�娴嬬偣锛屽綋鍓嶇珯鐐�={}", currentStationId);
             return null;
@@ -496,6 +567,7 @@
                                                  Integer expectedLoopIssueCount,
                                                  Double pathLenFactor,
                                                  DecisionPathCache decisionPathCache) {
+        long startMs = System.currentTimeMillis();
         if (currentStationId == null || orderedOutStationList == null || orderedOutStationList.size() <= 1) {
             return null;
         }
@@ -503,6 +575,8 @@
         int startIndex = orderedOutStationList.indexOf(currentStationId);
         int total = orderedOutStationList.size();
         List<CircleTargetCandidate> candidateList = new ArrayList<>();
+        int minPathLen = Integer.MAX_VALUE;
+        int maxPathLen = 0;
         for (int offset = 1; offset < total; offset++) {
             int candidateIndex = (startIndex + offset + total) % total;
             Integer candidateStationId = orderedOutStationList.get(candidateIndex);
@@ -513,6 +587,8 @@
                 List<NavigateNode> path = calcOutboundNavigatePath(wrkMast, currentStationId, candidateStationId, pathLenFactor, decisionPathCache);
                 if (path != null && !path.isEmpty()) {
                     candidateList.add(new CircleTargetCandidate(candidateStationId, path.size(), offset));
+                    minPathLen = Math.min(minPathLen, path.size());
+                    maxPathLen = Math.max(maxPathLen, path.size());
                 }
             } catch (Exception ignore) {
             }
@@ -539,7 +615,16 @@
                 return Integer.compare(left.getOffset(), right.getOffset());
             }
         });
-        return resolveGradualCircleTargetByPathLength(expectedLoopIssueCount, candidateList, pathLenFactor);
+        Integer circleTarget = resolveGradualCircleTargetByPathLength(expectedLoopIssueCount, candidateList, pathLenFactor);
+        long totalCostMs = System.currentTimeMillis() - startMs;
+        log.info("resolveNextCircleOrderTarget profile, taskNo={}, currentStationId={}, candidateCount={}, successfulCandidateCount={}, selectedTargetStationId={}, minPathLen={}, maxPathLen={}, totalCostMs={}ms",
+                wrkMast == null ? null : wrkMast.getWrkNo(), currentStationId, Math.max(total - 1, 0), candidateList.size(), circleTarget,
+                minPathLen == Integer.MAX_VALUE ? 0 : minPathLen, maxPathLen, totalCostMs);
+        if (totalCostMs > CIRCLE_TARGET_EVAL_SLOW_THRESHOLD_MS) {
+            log.warn("resolveNextCircleOrderTarget slow, taskNo={}, currentStationId={}, successfulCandidateCount={}, selectedTargetStationId={}, totalCostMs={}ms",
+                    wrkMast == null ? null : wrkMast.getWrkNo(), currentStationId, candidateList.size(), circleTarget, totalCostMs);
+        }
+        return circleTarget;
     }
 
     private Integer resolveGradualCircleTargetByPathLength(Integer expectedLoopIssueCount,

--
Gitblit v1.9.1