Browse Source

agv回调锁优化

master
常熟吴彦祖 3 weeks ago
parent
commit
0833fbc8ea
  1. 32
      src/main/java/com/gaotao/modules/autoWareHourceHaian/api/service/impl/HaiAnWmsMessageServiceImpl.java
  2. 28
      src/main/java/com/gaotao/modules/autoWareHourceHaian/entity/HaiAnTransportTaskDetailLockParam.java
  3. 9
      src/main/java/com/gaotao/modules/autoWareHourceHaian/mapper/HaiAnAgvTaskMapper.java
  4. 21
      src/main/resources/mapper/autoWareHourceHaian/HaiAnAgvTaskMapper.xml

32
src/main/java/com/gaotao/modules/autoWareHourceHaian/api/service/impl/HaiAnWmsMessageServiceImpl.java

@ -24,6 +24,7 @@ import com.gaotao.modules.autoWareHourceHaian.api.entity.HaiAnRobotErrorRequest;
import com.gaotao.modules.autoWareHourceHaian.api.entity.HaiAnWcsInboundCallbackRequest;
import com.gaotao.modules.autoWareHourceHaian.api.service.HaiAnWmsMessageService;
import com.gaotao.modules.autoWareHourceHaian.entity.HaiAnCountResultInsertData;
import com.gaotao.modules.autoWareHourceHaian.entity.HaiAnTransportTaskDetailLockParam;
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnAreaOption;
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnHandlingUnitLabelRow;
import com.gaotao.modules.autoWareHourceHaian.entity.pda.HaiAnPalletDetailRow;
@ -205,11 +206,8 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService {
throw new RuntimeException("RFID复核taskNo或palletId超过运输明细字段长度");
}
// 与原AGV回调使用同一事务级任务锁;只串行化同site+taskNo的写入,不查询或要求运输主表存在。- rqrq
Integer lockResult = haiAnAgvTaskMapper.lockTransportTaskDetailInsert(site, taskNo);
if (lockResult == null || lockResult < 0) {
throw new RuntimeException("RFID复核取得运输明细写入锁失败,taskNo=" + taskNo + ",lockResult=" + lockResult);
}
// 与AGV回调共用事务级任务锁;锁失败中断首次复核写入,不查询或要求运输主表存在。- rqrq
acquireTransportTaskDetailInsertLock(site, taskNo);
// 锁内先读取历史及在线首条;重复请求直接返回首轮响应,禁止用本次扫描覆盖复核事实。- rqrq
HaiAnWmsTransportTaskDetail firstDetail = haiAnAgvTaskMapper.getFirstRfidVerifyDetail(
site, taskNo, HaiAnAgvCallbackTypeStaticData.RFID_CHECK);
@ -333,6 +331,25 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService {
return result;
}
/**
* @Description 通过单次Callable取得同site+taskNo的事务级应用锁;两入口共用锁键并在锁内分配明细序号。- rqrq
* @param site 请求大site,必须已按入口规则校验,不能取登录态。- rqrq
* @param taskNo 搬运任务号,直接对应明细task_no,不要求主任务存在。- rqrq
*/
private void acquireTransportTaskDetailInsertLock(String site, String taskNo) {
if (!StringUtils.hasText(site) || !StringUtils.hasText(taskNo)) {
throw new RuntimeException("运输明细写入锁缺少site或taskNo");
}
HaiAnTransportTaskDetailLockParam lockParam = new HaiAnTransportTaskDetailLockParam(site, taskNo);
// 单次调用SQL Server sp_getapplock并读取返回码;数据库异常或负码须回滚,禁止无锁写入首次复核。- rqrq
haiAnAgvTaskMapper.lockTransportTaskDetailInsert(lockParam);
Integer lockResult = lockParam.getLockResult();
if (lockResult == null || lockResult < 0) {
throw new RuntimeException("取得运输明细写入锁失败,site=" + site + ",taskNo=" + taskNo
+ ",lockResult=" + lockResult);
}
}
/**
* @author rqrq
* @Description 处理海安立库出入库回调:按事务类型分流落库,到达出库口(原取货通知)执行幂等校验,目标区域固定A01并映射仓库/库位;仅认新中文 - rqrq
@ -1512,10 +1529,7 @@ public class HaiAnWmsMessageServiceImpl implements HaiAnWmsMessageService {
// 2. 只写haian_wms_transport_task_detail:task_no用wmsId,状态统一“已录入”,targetArea落to_area,不校验主记录存在 - rqrq
// 与同步RFID复核共用事务级任务锁;失败中断,避免两入口并发分到同一seqNo或产生两条首次复核。- rqrq
Integer lockResult = haiAnAgvTaskMapper.lockTransportTaskDetailInsert(site, wmsId);
if (lockResult == null || lockResult < 0) {
throw new RuntimeException("AGV反馈取得运输明细写入锁失败,taskNo=" + wmsId + ",lockResult=" + lockResult);
}
acquireTransportTaskDetailInsertLock(site, wmsId);
// 旧AGV接口的RFID动作也须遵守首次结果;历史或在线已有复核时直接幂等返回,不在归档后补写第二条。- rqrq
if (HaiAnAgvCallbackTypeStaticData.RFID_CHECK.equals(normalizedType)) {
HaiAnWmsTransportTaskDetail firstRfidDetail = haiAnAgvTaskMapper.getFirstRfidVerifyDetail(

28
src/main/java/com/gaotao/modules/autoWareHourceHaian/entity/HaiAnTransportTaskDetailLockParam.java

@ -0,0 +1,28 @@
package com.gaotao.modules.autoWareHourceHaian.entity;
import lombok.Data;
import java.util.Locale;
/**
* @Description 海安运输明细事务级应用锁参数;将site与搬运任务号归一为同一锁键,并承接SQL Server过程返回码。- rqrq
*/
@Data
public class HaiAnTransportTaskDetailLockParam {
/** 应用锁资源名,由请求大site和搬运taskNo组成;仅传给sp_getapplock,不落库。- rqrq */
private String resource;
/** 过程返回码,由sp_getapplock写回;非负为取得锁,负数须使调用方事务回滚。- rqrq */
private Integer lockResult;
/**
* @Description 按数据库业务键的大小写不敏感口径构造锁键,供同步复核与AGV回调共用。- rqrq
* @param site 请求大site;调用方已校验非空。- rqrq
* @param taskNo 搬运任务号;调用方已校验非空。- rqrq
*/
public HaiAnTransportTaskDetailLockParam(String site, String taskNo) {
this.resource = "HAIAN_TRANSPORT_DETAIL:" + site.toUpperCase(Locale.ROOT)
+ ":" + taskNo.toUpperCase(Locale.ROOT);
}
}

9
src/main/java/com/gaotao/modules/autoWareHourceHaian/mapper/HaiAnAgvTaskMapper.java

@ -3,6 +3,7 @@ package com.gaotao.modules.autoWareHourceHaian.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gaotao.modules.autoWareHourceHaian.entity.HaiAnWmsTransportTaskData;
import com.gaotao.modules.autoWareHourceHaian.entity.HaiAnTransportTaskDetailLockParam;
import com.gaotao.modules.autoWareHourceHaian.entity.vo.HaiAnWmsTransportTask;
import com.gaotao.modules.autoWareHourceHaian.entity.vo.HaiAnWmsTransportTaskDetail;
import org.apache.ibatis.annotations.Mapper;
@ -48,12 +49,10 @@ public interface HaiAnAgvTaskMapper {
Integer getNextSeqNoForTaskDetail(@Param("site") String site, @Param("taskNo") String taskNo);
/**
* @Description 对同site、同任务号的回调插入取得事务级应用锁;负数表示超时或失败,调用方必须中断,避免首次RFID复核和序号并发错写。- rqrq
* @param site 请求大site,参与锁键,不能使用登录态。- rqrq
* @param taskNo 搬运任务号,参与锁键;不要求运输主表存在。- rqrq
* @return SQL Server sp_getapplock结果,非负表示取得锁。- rqrq
* @Description 通过单次Callable调用对同site、同任务号的插入取得事务级应用锁;不放宽Druid多语句限制。- rqrq
* @param param 由请求site和搬运taskNo组成的锁键;过程返回码写入lockResult,负数须回滚。- rqrq
*/
Integer lockTransportTaskDetailInsert(@Param("site") String site, @Param("taskNo") String taskNo);
void lockTransportTaskDetailInsert(HaiAnTransportTaskDetailLockParam param);
/**
* @Description 按site、taskNo和RFID动作读取最早落库的复核明细;历史优先于在线表,供重复请求返回首次响应。- rqrq

21
src/main/resources/mapper/autoWareHourceHaian/HaiAnAgvTaskMapper.xml

@ -135,17 +135,16 @@
AND item_no = 1
</select>
<!-- 按大site+taskNo串行化明细写入和首次RFID判定;锁随调用方事务提交释放,负数由Service抛错。- rqrq -->
<select id="lockTransportTaskDetailInsert" resultType="java.lang.Integer">
SET NOCOUNT ON;
DECLARE @lockResult INT;
DECLARE @resource NVARCHAR(255) = CONCAT(N'HAIAN_TRANSPORT_DETAIL:', UPPER(#{site}), N':', UPPER(#{taskNo}));
EXEC @lockResult = sys.sp_getapplock
@Resource = @resource,
@LockMode = 'Exclusive',
@LockOwner = 'Transaction',
@LockTimeout = 10000;
SELECT @lockResult;
<!-- 单次Callable取得同site+taskNo事务级应用锁;输出返回码由Service检查,避免Druid拦截多语句。- rqrq -->
<select id="lockTransportTaskDetailInsert"
parameterType="com.gaotao.modules.autoWareHourceHaian.entity.HaiAnTransportTaskDetailLockParam"
statementType="CALLABLE">
{#{lockResult, mode=OUT, jdbcType=INTEGER} = call sys.sp_getapplock(
#{resource, mode=IN, jdbcType=NVARCHAR},
'Exclusive',
'Transaction',
10000
)}
</select>
<!-- 重复复核优先取历史首条,再取在线首条;即使旧回调在归档后误补写在线记录,也只认最初业务结果。- rqrq -->

Loading…
Cancel
Save