diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java b/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java
index ae71f52..1a341a4 100644
--- a/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java
+++ b/src/main/java/com/gaotao/modules/automatedWarehouse/mapper/WcsIntegrationMapper.java
@@ -764,6 +764,21 @@ public interface WcsIntegrationMapper {
@Param("toLocation") String toLocation,
@Param("oldWmsStatus") String oldWmsStatus, @Param("newWmsStatus") String newWmsStatus);
+ /**
+ * @Description 使用乐观锁更新AGV站点状态(检查期望状态,防止并发覆盖)- rqrq
+ * @param stationCode 站点编码
+ * @param expectedStatusDb 期望的当前状态(乐观锁)
+ * @param newStatusDb 新状态代码
+ * @param newStatus 新状态描述
+ * @return 影响的行数(0=更新失败,1=更新成功)
+ * @author rqrq
+ * @date 2025/11/04
+ */
+ int updateAgvStationStatusWithLock(@Param("stationCode") String stationCode,
+ @Param("expectedStatusDb") Integer expectedStatusDb,
+ @Param("newStatusDb") Integer newStatusDb,
+ @Param("newStatus") String newStatus);
+
/**
* @Description 根据栈板ID和sourceType查询最新的OrderTask(按创建时间倒序)- rqrq
* @param site 工厂编码
diff --git a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/AutoTaskServiceImpl.java b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/AutoTaskServiceImpl.java
index 01a583a..0196a0c 100644
--- a/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/AutoTaskServiceImpl.java
+++ b/src/main/java/com/gaotao/modules/automatedWarehouse/service/impl/AutoTaskServiceImpl.java
@@ -417,8 +417,22 @@ public class AutoTaskServiceImpl implements AutoTaskService {
}
if(targetStationStatus == 0){
- System.out.println("目标站点空闲 - rqrq");
- return inData.getToLocation();
+ System.out.println("目标站点空闲,尝试使用乐观锁预占 - rqrq");
+ // 使用乐观锁尝试预占站点(从空闲0改为待放货2)- rqrq
+ int lockResult = wcsIntegrationMapper.updateAgvStationStatusWithLock(
+ inData.getToLocation(),
+ 0, // expectedStatusDb - 期望当前是空闲
+ 2, // newStatusDb - 更新为待放货
+ "待放货"
+ );
+
+ if(lockResult == 1){
+ System.out.println("乐观锁预占站点成功 - rqrq");
+ return inData.getToLocation();
+ } else {
+ System.out.println("乐观锁预占站点失败,站点已被占用 - rqrq");
+ return null; // 站点已被其他线程占用,创建预约任务 - rqrq
+ }
} else {
System.out.println("目标站点不空闲,需要创建预约任务 - rqrq,状态码:" + targetStationStatus);
return null;
@@ -432,8 +446,22 @@ public class AutoTaskServiceImpl implements AutoTaskService {
String idleLocation = wcsIntegrationMapper.findFirstFreeStationByAreaId(inData.getToArea());
if(StringUtils.hasText(idleLocation)){
- System.out.println("找到空闲站点 - rqrq:" + idleLocation);
- return idleLocation;
+ System.out.println("找到空闲站点,尝试使用乐观锁预占 - rqrq:" + idleLocation);
+ // 使用乐观锁尝试预占站点(从空闲0改为待放货2)- rqrq
+ int lockResult = wcsIntegrationMapper.updateAgvStationStatusWithLock(
+ idleLocation,
+ 0, // expectedStatusDb - 期望当前是空闲
+ 2, // newStatusDb - 更新为待放货
+ "待放货"
+ );
+
+ if(lockResult == 1){
+ System.out.println("乐观锁预占站点成功 - rqrq");
+ return idleLocation;
+ } else {
+ System.out.println("乐观锁预占站点失败,站点已被占用,尝试查找其他站点 - rqrq");
+ return null; // 站点已被其他线程占用,创建预约任务 - rqrq
+ }
} else {
System.out.println("区域内无空闲站点,需要创建预约任务 - rqrq");
return null;
@@ -487,11 +515,32 @@ public class AutoTaskServiceImpl implements AutoTaskService {
// 更新起始站点状态为"待取货" - rqrq
wcsIntegrationMapper.updateAgvStationStatus(inData.getFromLocation(), 3, "待取货");
+ // 如果指定了目标站点,需要使用乐观锁更新目标站点状态为"待放货",防止其他托盘预约同一站点 - rqrq
+ if(StringUtils.hasText(inData.getToLocation())){
+ System.out.println("预约任务指定了目标站点,尝试使用乐观锁更新为待放货 - rqrq,toLocation=" + inData.getToLocation());
+
+ // 使用乐观锁尝试预占站点(从空闲0改为待放货2)- rqrq
+ int lockResult = wcsIntegrationMapper.updateAgvStationStatusWithLock(
+ inData.getToLocation(),
+ 0, // expectedStatusDb - 期望当前是空闲
+ 2, // newStatusDb - 更新为待放货
+ "待放货"
+ );
+
+ if(lockResult == 0){
+ // 乐观锁更新失败,说明站点已被其他线程占用 - rqrq
+ System.out.println("警告:乐观锁更新目标站点状态失败,站点可能已被占用 - rqrq");
+ // 注意:这里不抛出异常,允许创建预约任务,但目标站点可能不是空闲状态 - rqrq
+ } else {
+ System.out.println("成功更新目标站点状态为待放货 - rqrq");
+ }
+ }
+
// 更新栈板calling_flag为'Y' - rqrq
wcsIntegrationMapper.updatePalletCallingFlag(inData.getSite(), inData.getPalletId(), "Y",
inData.getUsername() != null ? inData.getUsername() : "sys_wms");
- // 预约任务不创建明细记录,不更改目标站点状态 - rqrq
+ // 预约任务不创建明细记录 - rqrq
System.out.println("预约运输任务创建完成 - rqrq,taskNo=" + task.getTaskNo());
}
@@ -542,8 +591,7 @@ public class AutoTaskServiceImpl implements AutoTaskService {
// 更新起始站点状态为"待取货" - rqrq
wcsIntegrationMapper.updateAgvStationStatus(inData.getFromLocation(), 3, "待取货");
- // 更新目标站点状态为"待放货" - rqrq
- wcsIntegrationMapper.updateAgvStationStatus(targetLocation, 2, "待放货");
+ // 注意:目标站点状态已在determineTargetLocation方法中使用乐观锁预占,这里不需要再更新 - rqrq
// 更新栈板calling_flag为'Y' - rqrq
wcsIntegrationMapper.updatePalletCallingFlag(inData.getSite(), inData.getPalletId(), "Y",
@@ -783,9 +831,9 @@ public class AutoTaskServiceImpl implements AutoTaskService {
private String determineTargetStationForTransport(WmsTransportTask wmsTransportTask) {
System.out.println("开始确定目标站点 - rqrq");
- // 如果toLocation不为空,检查该站点状态 - rqrq
+ // 如果toLocation不为空,说明是指定站点预约,检查该站点状态必须为待放货(2) - rqrq
if(StringUtils.hasText(wmsTransportTask.getToLocation())){
- System.out.println("检查指定目标站点 - rqrq,toLocation=" + wmsTransportTask.getToLocation());
+ System.out.println("处理指定站点预约任务 - rqrq,toLocation=" + wmsTransportTask.getToLocation());
Integer stationStatus = wcsIntegrationMapper.getAgvStationStatus(wmsTransportTask.getToLocation());
if(stationStatus == null){
@@ -793,24 +841,40 @@ public class AutoTaskServiceImpl implements AutoTaskService {
throw new RuntimeException("目标站点不存在:" + wmsTransportTask.getToLocation());
}
- if(stationStatus == 0){
- System.out.println("目标站点空闲 - rqrq");
+ // 指定站点预约:创建时已锁定为待放货(2),这里检查必须是2才能使用 - rqrq
+ if(stationStatus == 2){
+ System.out.println("目标站点状态为待放货,可以使用(预留给此任务)- rqrq");
return wmsTransportTask.getToLocation();
} else {
- System.out.println("目标站点不空闲 - rqrq,状态码:" + stationStatus);
+ System.out.println("目标站点状态异常 - rqrq,期望状态=2(待放货),实际状态=" + stationStatus);
return null;
}
}
- // 如果toLocation为空,根据toArea查找空闲站点 - rqrq
+ // 如果toLocation为空,说明是指定区域预约,需要查找空闲站点并锁定 - rqrq
else if(StringUtils.hasText(wmsTransportTask.getToArea())){
- System.out.println("根据目标区域查找空闲站点 - rqrq,toArea=" + wmsTransportTask.getToArea());
+ System.out.println("处理指定区域预约任务 - rqrq,toArea=" + wmsTransportTask.getToArea());
- // 查询agv_station表中status_db=0且area_type=toArea的第一个站点 - rqrq
+ // 查询该区域下的空闲站点(status_db=0)- rqrq
String idleStation = wcsIntegrationMapper.findFirstFreeStationByAreaId(wmsTransportTask.getToArea());
if(StringUtils.hasText(idleStation)){
- System.out.println("找到空闲站点 - rqrq:" + idleStation);
- return idleStation;
+ System.out.println("找到空闲站点,尝试使用乐观锁占用 - rqrq:" + idleStation);
+
+ // 使用乐观锁尝试占用站点(从空闲0改为待放货2)- rqrq
+ int lockResult = wcsIntegrationMapper.updateAgvStationStatusWithLock(
+ idleStation,
+ 0, // expectedStatusDb - 期望当前是空闲
+ 2, // newStatusDb - 更新为待放货
+ "待放货"
+ );
+
+ if(lockResult == 1){
+ System.out.println("乐观锁占用站点成功 - rqrq");
+ return idleStation;
+ } else {
+ System.out.println("乐观锁占用站点失败,站点已被占用,继续等待 - rqrq");
+ return null;
+ }
} else {
System.out.println("区域内无空闲站点 - rqrq");
return null;
@@ -849,8 +913,10 @@ public class AutoTaskServiceImpl implements AutoTaskService {
throw new RuntimeException("更新任务状态失败");
}
- // 更新目标站点状态为"待放货" - rqrq
- wcsIntegrationMapper.updateAgvStationStatus(targetStation, 2, "待放货");
+ // 注意:如果是指定站点预约,站点状态已在createScheduledTask时锁定为待放货(2) - rqrq
+ // 如果是区域预约,站点状态已在determineTargetStationForTransport时锁定为待放货(2) - rqrq
+ // 这里不需要再次更新站点状态 - rqrq
+ System.out.println("目标站点状态已在之前锁定,无需重复更新 - rqrq");
// 生成任务明细 - rqrq
WmsTransportTaskDetail detail = new WmsTransportTaskDetail();
diff --git a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml
index d8a1b4f..f9b693b 100644
--- a/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml
+++ b/src/main/resources/mapper/automatedWarehouse/WcsIntegrationMapper.xml
@@ -1045,6 +1045,15 @@
status = #{status}
WHERE station_code = #{stationCode}
+
+
+
+ UPDATE agv_station
+ SET status_db = #{newStatusDb},
+ status = #{newStatus}
+ WHERE station_code = #{stationCode}
+ AND status_db = #{expectedStatusDb}
+
update wms_transport_task set to_location=#{toLocation} where site=#{site} and task_no=#{taskNo}