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<Integer, ReentrantLock> 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();
|
}
|
}
|
}
|