From f7d2eda120867b3c5a2d9001d5f5c9d0396c65bd Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 14 四月 2026 12:41:13 +0800
Subject: [PATCH] #命令下发队列优化

---
 src/main/java/com/zy/core/thread/impl/station/StationSegmentExecutor.java |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/src/main/java/com/zy/core/thread/impl/station/StationSegmentExecutor.java b/src/main/java/com/zy/core/thread/impl/station/StationSegmentExecutor.java
index 50ca80f..21496f0 100644
--- a/src/main/java/com/zy/core/thread/impl/station/StationSegmentExecutor.java
+++ b/src/main/java/com/zy/core/thread/impl/station/StationSegmentExecutor.java
@@ -6,6 +6,7 @@
 import com.zy.asrs.domain.vo.StationTaskTraceSegmentVo;
 import com.zy.asrs.entity.DeviceConfig;
 import com.zy.common.utils.RedisUtil;
+import lombok.extern.slf4j.Slf4j;
 import com.zy.core.cache.SlaveConnection;
 import com.zy.core.enums.RedisKeyType;
 import com.zy.core.enums.SlaveType;
@@ -15,6 +16,8 @@
 import com.zy.core.model.protocol.StationProtocol;
 import com.zy.core.move.StationMoveCoordinator;
 import com.zy.core.trace.StationTaskTraceRegistry;
+import com.zy.core.thread.impl.v5.StationV5RuntimeConfigProvider;
+import com.zy.core.thread.support.StationTaskLocationRegistry;
 import com.zy.system.entity.Config;
 import com.zy.system.service.ConfigService;
 
@@ -24,11 +27,13 @@
 import java.util.Map;
 import java.util.function.Function;
 
+@Slf4j
 public class StationSegmentExecutor {
 
     private static final String CFG_STATION_COMMAND_SEGMENT_ADVANCE_RATIO = "stationCommandSegmentAdvanceRatio";
     private static final double DEFAULT_STATION_COMMAND_SEGMENT_ADVANCE_RATIO = 0.3d;
     private static final long CURRENT_STATION_TIMEOUT_MS = 1000L * 60L;
+    private static final long TASK_LOCATION_STALE_MS = 2_000L;
 
     private final DeviceConfig deviceConfig;
     private final RedisUtil redisUtil;
@@ -89,6 +94,7 @@
         long lastSeenAt = System.currentTimeMillis();
         int segCursor = 0;
         Integer lastCurrentStationId = null;
+        int lastMatchedPathIndex = -1;
         boolean firstRun = true;
         while (true) {
             try {
@@ -144,12 +150,17 @@
                     break;
                 }
 
-                int currentIndex = effectiveFullPath.indexOf(currentStation.getStationId());
+                int currentIndex = resolveCurrentPathIndex(
+                        effectiveFullPath,
+                        currentStation.getStationId(),
+                        lastMatchedPathIndex
+                );
                 if (currentIndex < 0) {
                     Thread.sleep(500L);
                     firstRun = false;
                     continue;
                 }
+                lastMatchedPathIndex = currentIndex;
 
                 int remaining = effectiveFullPath.size() - currentIndex - 1;
                 if (remaining <= 0) {
@@ -192,10 +203,59 @@
         }
     }
 
+    private int resolveCurrentPathIndex(List<Integer> fullPathStationIds,
+                                        Integer currentStationId,
+                                        int lastMatchedPathIndex) {
+        if (fullPathStationIds == null || fullPathStationIds.isEmpty() || currentStationId == null) {
+            return -1;
+        }
+        if (lastMatchedPathIndex >= 0
+                && lastMatchedPathIndex < fullPathStationIds.size()
+                && equalsInteger(currentStationId, fullPathStationIds.get(lastMatchedPathIndex))) {
+            return lastMatchedPathIndex;
+        }
+
+        int nextIndex = findNextStationIndex(fullPathStationIds, currentStationId, Math.max(lastMatchedPathIndex + 1, 0));
+        if (nextIndex >= 0) {
+            return nextIndex;
+        }
+        return findNextStationIndex(fullPathStationIds, currentStationId, 0);
+    }
+
+    private int findNextStationIndex(List<Integer> path, Integer stationId, int fromIndex) {
+        if (path == null || path.isEmpty() || stationId == null) {
+            return -1;
+        }
+        int startIdx = Math.max(fromIndex, 0);
+        for (int i = startIdx; i < path.size(); i++) {
+            if (equalsInteger(stationId, path.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     private boolean sendSegmentWithRetry(StationCommand command,
                                          StationTaskTraceRegistry traceRegistry,
                                          Integer traceVersion,
                                          Integer currentStationId) {
+        // 鍦ㄤ笅鍙戞柊鍒嗘鍓嶆鏌ヨ矾鐢辩増鏈槸鍚︿粛鐒舵湁鏁堬紝閬垮厤鍦ㄨ矾鐢辩増鏈凡鏇存柊鐨勬儏鍐典笅涓嬪彂鏃х増鏈懡浠�
+        if (!isRouteDispatchable(command == null ? null : command.getTaskNo(), command == null ? null : command.getRouteVersion())) {
+            // 棣栨鏍¢獙澶辫触鍙兘鏄� Redis 鍐欏叆寤惰繜瀵艰嚧鐨勶紝鐭殏绛夊緟鍚庨噸璇曚竴娆°��
+            sleepQuietly(50L);
+            if (!isRouteDispatchable(command == null ? null : command.getTaskNo(), command == null ? null : command.getRouteVersion())) {
+                if (traceRegistry != null && command != null) {
+                    traceRegistry.markCancelled(command.getTaskNo(), traceVersion, currentStationId,
+                            buildDetails("reason", "route_version_replaced_before_segment_send", "routeVersion", command.getRouteVersion()));
+                }
+                markCancelled(command == null ? null : command.getTaskNo(),
+                        command == null ? null : command.getRouteVersion(),
+                        currentStationId,
+                        "route_version_replaced_before_segment_send");
+                return false;
+            }
+        }
+        
         while (true) {
             SegmentSendResult sendResult = executeLockedSegmentSend(command, traceRegistry, traceVersion, currentStationId);
             if (sendResult == SegmentSendResult.CANCELLED) {
@@ -259,6 +319,13 @@
     }
 
     private double loadSegmentAdvanceRatio() {
+        if (isV5ThreadImpl()) {
+            StationV5RuntimeConfigProvider configProvider = SpringUtils.getBean(StationV5RuntimeConfigProvider.class);
+            if (configProvider != null) {
+                return configProvider.getSegmentAdvanceRatio();
+            }
+            return DEFAULT_STATION_COMMAND_SEGMENT_ADVANCE_RATIO;
+        }
         try {
             ConfigService configService = SpringUtils.getBean(ConfigService.class);
             if (configService == null) {
@@ -312,6 +379,9 @@
     }
 
     private StationProtocol findCurrentStationByTask(Integer taskNo) {
+        if (isV5ThreadImpl()) {
+            return findCurrentStationByTaskFromRegistry(taskNo);
+        }
         try {
             com.zy.asrs.service.DeviceConfigService deviceConfigService = SpringUtils.getBean(com.zy.asrs.service.DeviceConfigService.class);
             if (deviceConfigService == null) {
@@ -338,6 +408,27 @@
             return null;
         }
         return null;
+    }
+
+    private StationProtocol findCurrentStationByTaskFromRegistry(Integer taskNo) {
+        StationTaskLocationRegistry registry = SpringUtils.getBean(StationTaskLocationRegistry.class);
+        if (registry == null) {
+            return null;
+        }
+        StationTaskLocationRegistry.TaskLocationSnapshot snapshot = registry.findActive(taskNo, TASK_LOCATION_STALE_MS);
+        if (snapshot == null || !snapshot.isLoading()) {
+            return null;
+        }
+        StationProtocol stationProtocol = new StationProtocol();
+        stationProtocol.setTaskNo(snapshot.getTaskNo());
+        stationProtocol.setStationId(snapshot.getStationId());
+        stationProtocol.setRunBlock(snapshot.isRunBlock());
+        stationProtocol.setLoading(true);
+        return stationProtocol;
+    }
+
+    private boolean isV5ThreadImpl() {
+        return deviceConfig != null && "ZyStationV5Thread".equals(deviceConfig.getThreadImpl());
     }
 
     private List<StationTaskTraceSegmentVo> buildTraceSegments(List<StationCommand> segmentCommands) {
@@ -441,7 +532,15 @@
             return true;
         }
         StationMoveCoordinator moveCoordinator = loadMoveCoordinator();
-        return moveCoordinator == null || moveCoordinator.canDispatchRoute(taskNo, routeVersion);
+        if (moveCoordinator == null) {
+            return true;
+        }
+        boolean dispatchable = moveCoordinator.canDispatchRoute(taskNo, routeVersion);
+        if (!dispatchable) {
+            log.warn("isRouteDispatchable rejected, taskNo={}, routeVersion={}, threadImpl={}",
+                    taskNo, routeVersion, deviceConfig == null ? null : deviceConfig.getThreadImpl());
+        }
+        return dispatchable;
     }
 
     private StationMoveCoordinator loadMoveCoordinator() {

--
Gitblit v1.9.1