package com.zy.core.network.fake; import com.zy.core.News; import com.zy.core.network.entity.ZyStationStatusEntity; import java.util.Arrays; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; /** * 仿真站点移动引擎 * 负责站点间的移动执行:初始化、移动到下一站、清除站点 * 使用 ReentrantLock 做站点级并发控制 */ public class FakeStationMoveEngine { private final Map stationLocks = new ConcurrentHashMap<>(); private final FakeStationStateManager stateManager; public FakeStationMoveEngine(FakeStationStateManager stateManager) { this.stateManager = stateManager; } public boolean initStationMove(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer taskNo, Integer targetStationId, Boolean isLoading, String barcode) { lockStations(currentStationId); try { ZyStationStatusEntity currentStatus = stateManager.findStationStatus(currentStationDeviceNo, currentStationId); if (currentStatus == null) { return false; } if (currentStatus.getTaskNo() != null && currentStatus.getTaskNo() > 0 && !currentStatus.getTaskNo().equals(taskNo) && currentStatus.isLoading()) { return false; } boolean updated = stateManager.updateStationDataWithHeldLock(currentStationId, currentStationDeviceNo, taskNo, targetStationId, isLoading, barcode, false); if (updated) { stateManager.publishTaskLocation(taskNo, currentStationDeviceNo, currentStationId, Boolean.TRUE.equals(isLoading), false); } return updated; } finally { unlockStations(currentStationId); } } public boolean stationMoveToNext(Integer lockTaskNo, Integer currentStationId, Integer currentStationDeviceNo, Integer nextStationId, Integer nextStationDeviceNo, Integer taskNo, Integer targetStaNo) { News.info("[WCS Debug] fake stationMoveToNext开始,taskNo={},currentStationId={},currentDeviceNo={},nextStationId={},nextDeviceNo={},targetStaNo={}", taskNo, currentStationId, currentStationDeviceNo, nextStationId, nextStationDeviceNo, targetStaNo); lockStations(currentStationId, nextStationId); try { ZyStationStatusEntity currentStatus = stateManager.findStationStatus(currentStationDeviceNo, currentStationId); ZyStationStatusEntity nextStatus = stateManager.findStationStatus(nextStationDeviceNo, nextStationId); if (currentStatus == null || nextStatus == null) { News.info("仿真站点移动失败,原因=station_status_missing,taskNo={},currentStationId={},currentDeviceNo={},nextStationId={},nextDeviceNo={},targetStaNo={},currentStatusNull={},nextStatusNull={}", taskNo, currentStationId, currentStationDeviceNo, nextStationId, nextStationDeviceNo, targetStaNo, currentStatus == null, nextStatus == null); return false; } if ((nextStatus.getTaskNo() != null && nextStatus.getTaskNo() > 0) || nextStatus.isLoading()) { News.info("仿真站点移动失败,原因=next_station_busy,taskNo={},currentStationId={},nextStationId={},targetStaNo={},currentTaskNo={},currentLoading={},currentRunBlock={},nextTaskNo={},nextLoading={},nextRunBlock={},nextTargetStaNo={}", taskNo, currentStationId, nextStationId, targetStaNo, currentStatus.getTaskNo(), currentStatus.isLoading(), currentStatus.isRunBlock(), nextStatus.getTaskNo(), nextStatus.isLoading(), nextStatus.isRunBlock(), nextStatus.getTargetStaNo()); return false; } if (currentStatus.getTaskNo() == null || !taskNo.equals(currentStatus.getTaskNo()) || !currentStatus.isLoading()) { News.info("仿真站点移动失败,原因=current_station_task_mismatch,taskNo={},currentStationId={},nextStationId={},currentTaskNo={},currentLoading={},currentTargetStaNo={}", taskNo, currentStationId, nextStationId, currentStatus.getTaskNo(), currentStatus.isLoading(), currentStatus.getTargetStaNo()); return false; } String barcode = currentStatus.getBarcode(); News.info("[WCS Debug] fake handoff准备提交,taskNo={},sourceStationId={},sourceTaskNo={},sourceLoading={},sourceTargetStaNo={},sourceBarcode={},sourceRunBlock={},targetStationId={},targetTaskNo={},targetLoading={},targetTargetStaNo={},targetBarcode={},targetRunBlock={}", taskNo, currentStationId, currentStatus.getTaskNo(), currentStatus.isLoading(), currentStatus.getTargetStaNo(), currentStatus.getBarcode(), currentStatus.isRunBlock(), nextStationId, nextStatus.getTaskNo(), nextStatus.isLoading(), nextStatus.getTargetStaNo(), nextStatus.getBarcode(), nextStatus.isRunBlock()); boolean prepared = stateManager.updateStationDataWithHeldLock(nextStationId, nextStationDeviceNo, taskNo, targetStaNo, false, barcode, false); if (!prepared) { News.info("仿真站点移动失败,原因=next_station_prepare_failed,taskNo={},currentStationId={},nextStationId={},targetStaNo={}", taskNo, currentStationId, nextStationId, targetStaNo); return false; } boolean loaded = stateManager.updateStationDataWithHeldLock(nextStationId, nextStationDeviceNo, null, null, true, null, false); if (!loaded) { News.info("仿真站点移动失败,原因=next_station_loading_commit_failed,taskNo={},currentStationId={},nextStationId={},targetStaNo={}", taskNo, currentStationId, nextStationId, targetStaNo); stateManager.updateStationDataWithHeldLock(nextStationId, nextStationDeviceNo, 0, 0, false, "", false); return false; } boolean cleared = stateManager.updateStationDataWithHeldLock(currentStationId, currentStationDeviceNo, 0, 0, false, "", false); if (!cleared) { News.info("仿真站点移动失败,原因=current_station_clear_failed,taskNo={},currentStationId={},nextStationId={},targetStaNo={},currentTaskNo={},currentLoading={},currentRunBlock={},nextTaskNo={},nextLoading={},nextRunBlock={}", taskNo, currentStationId, nextStationId, targetStaNo, currentStatus.getTaskNo(), currentStatus.isLoading(), currentStatus.isRunBlock(), taskNo, true, false); stateManager.updateStationDataWithHeldLock(nextStationId, nextStationDeviceNo, 0, 0, false, "", false); return false; } News.info("[WCS Debug] fake handoff提交成功,taskNo={},sourceStationId={},targetStationId={},targetStaNo={},sourceCleared=true,targetLoading=true", taskNo, currentStationId, nextStationId, targetStaNo); stateManager.clearTaskLocationIfMatches(taskNo, currentStationDeviceNo, currentStationId); stateManager.publishTaskLocation(taskNo, nextStationDeviceNo, nextStationId, true, false); return true; } finally { unlockStations(currentStationId, nextStationId); } } public boolean clearStation(Integer deviceNo, Integer lockTaskNo, Integer currentStationId) { lockStations(currentStationId); try { ZyStationStatusEntity currentStatus = stateManager.findStationStatus(deviceNo, currentStationId); if (currentStatus == null) { return false; } Integer taskNo = currentStatus.getTaskNo(); boolean cleared = stateManager.updateStationDataWithHeldLock(currentStationId, deviceNo, 0, 0, false, "", false); if (cleared) { stateManager.clearTaskLocationIfMatches(taskNo, deviceNo, currentStationId); } return cleared; } finally { unlockStations(currentStationId); } } private ReentrantLock getStationLock(Integer stationId) { return stationLocks.computeIfAbsent(stationId, key -> new ReentrantLock()); } public void lockStations(Integer... stationIds) { Integer[] sorted = Arrays.copyOf(stationIds, stationIds.length); Arrays.sort(sorted); for (Integer stationId : sorted) { getStationLock(stationId).lock(); } } public void unlockStations(Integer... stationIds) { Integer[] sorted = Arrays.copyOf(stationIds, stationIds.length); Arrays.sort(sorted); for (int i = sorted.length - 1; i >= 0; i--) { getStationLock(sorted[i]).unlock(); } } }