From 1837b8df655d40acc832651e21757023eaacf40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B8=B8=E7=86=9F=E5=90=B4=E5=BD=A6=E7=A5=96?= Date: Tue, 4 Nov 2025 12:43:25 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=84=E7=BA=A6=E4=BB=BB=E5=8A=A1bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/WcsIntegrationMapper.java | 15 +++ .../service/impl/AutoTaskServiceImpl.java | 104 ++++++++++++++---- .../WcsIntegrationMapper.xml | 9 ++ 3 files changed, 109 insertions(+), 19 deletions(-) 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}