diff --git a/youchain-system/src/main/java/com/youchain/appupdate/service/impl/NioF3AppServiceImpl.java b/youchain-system/src/main/java/com/youchain/appupdate/service/impl/NioF3AppServiceImpl.java index 3fce48a..d282ff7 100644 --- a/youchain-system/src/main/java/com/youchain/appupdate/service/impl/NioF3AppServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/appupdate/service/impl/NioF3AppServiceImpl.java @@ -45,6 +45,7 @@ public class NioF3AppServiceImpl implements NioF3AppService { //验证Les任务 List lesList = validateLes(bindSmall.getSrcPositionCode(), bindSmall.getOnlineNo()); + List lesIds = lesList.stream().map(Les::getId).collect(Collectors.toList()); //验证起点是否有Agv任务 validateAgvTask(bindSmall.getSrcPositionCode()); @@ -52,11 +53,15 @@ public class NioF3AppServiceImpl implements NioF3AppService { //获取目标点位 String endPointCode = getEndPointCode(lesList); - //生成Agv任务 - AgvTask agvTask = agvTaskService.createAgvTask(BizStatus.OPEN, null, bindSmall.getSrcPositionCode(), endPointCode, "TUGGER"); - - //绑定任务 - bindLesTask(lesList, agvTask.getId()); + // 4. 仅对关键更新操作加锁 + String lockKey = bindSmall.getSrcPositionCode().intern(); + AgvTask agvTask; + synchronized (lockKey) { + //生成Agv任务 + agvTask = agvTaskService.createAgvTask(BizStatus.OPEN, null, bindSmall.getSrcPositionCode(), endPointCode, "TUGGER"); + //绑定任务 + bindLesAgvTask(agvTask.getId(), lesIds); + } //下发任务 kmReService.sendAgvTask(agvTask, kmReService.sendAgvTaskQYCJson(agvTask, bindSmall.getShooter(), null)); @@ -109,12 +114,8 @@ public class NioF3AppServiceImpl implements NioF3AppService { } @Transactional(rollbackFor = Exception.class) - public void bindLesTask(List lesList, Long agvTaskId) { - //获取Les - for (Les les : lesList) { - les.setAgvTaskId(agvTaskId); - } - lesRepository.saveAll(lesList); + public void bindLesAgvTask(Long agvTaskId, List lesIds) { + lesRepository.batchUpdateAgvTaskId(agvTaskId, lesIds); } @@ -125,12 +126,11 @@ public class NioF3AppServiceImpl implements NioF3AppService { validateParams(bindLarge); //获取所有扫描的料箱号 - List boxNos = bindLarge.getBoxAndDolly().stream() - .map(BoxAndDolly::getBoxNo) - .collect(Collectors.toList()); + List boxNos = bindLarge.getBoxAndDolly().stream().map(BoxAndDolly::getBoxNo).collect(Collectors.toList()); //验证Les任务 List lesList = validateLes(bindLarge.getSrcPositionCode(), boxNos); + List lesIds = lesList.stream().map(Les::getId).collect(Collectors.toList()); //验证料箱号 validateBoxNos(lesList, boxNos); @@ -141,11 +141,16 @@ public class NioF3AppServiceImpl implements NioF3AppService { //获取目标点位 String endPointCode = getEndPointCode(lesList); - //生成Agv任务 - AgvTask agvTask = agvTaskService.createAgvTask(BizStatus.OPEN, null, bindLarge.getSrcPositionCode(), endPointCode, "TUGGER"); + // 4. 仅对关键更新操作加锁 + String lockKey = bindLarge.getSrcPositionCode().intern(); + AgvTask agvTask; + synchronized (lockKey) { + //生成Agv任务 + agvTask = agvTaskService.createAgvTask(BizStatus.OPEN, null, bindLarge.getSrcPositionCode(), endPointCode, "TUGGER"); - //绑定任务 - bindLesTask(lesList, agvTask.getId()); + //绑定任务 + bindLesAgvTask(agvTask.getId(), lesIds); + } //下发任务 kmReService.sendAgvTask(agvTask, kmReService.sendAgvTaskQYCJson(agvTask, boxNos.size(), boxNos)); @@ -232,6 +237,11 @@ public class NioF3AppServiceImpl implements NioF3AppService { //获取Les Les les = lesRepository.findById(lesId).orElseGet(Les::new); + // 防止重复确认 + if (BizStatus.CLOSE.equals(les.getStatus())) { + throw new BadRequestException("该任务已完成,请勿重复操作"); + } + //回传LES lesService.lesCallBack(les, lesService.lesCallBackJson(les.getDstPositionCode(), les.getTaskCode())); } diff --git a/youchain-system/src/main/java/com/youchain/businessdata/repository/AgvTaskRepository.java b/youchain-system/src/main/java/com/youchain/businessdata/repository/AgvTaskRepository.java index 23fc6fc..a375b27 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/repository/AgvTaskRepository.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/repository/AgvTaskRepository.java @@ -18,8 +18,10 @@ package com.youchain.businessdata.repository; import com.youchain.businessdata.domain.AgvTask; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.Query; +import javax.persistence.LockModeType; import java.util.List; import java.util.Map; @@ -33,9 +35,13 @@ public interface AgvTaskRepository extends JpaRepository, JpaSpec @Query(value = "select count(agv.id) from AgvTask agv where agv.stockCode=:stockCode and agv.startSlotCode=:srcPointCode and agv.endSlotCode=:endPointCode and agv.status in ('OPEN','ATCALL','UP_CONTAINER') ") Long isAGVTaskDuplicate(String stockCode, String srcPointCode, String endPointCode); + @Query(value = "select count(agv.id) from AgvTask agv where agv.startSlotCode=:startSlotCode and agv.type=:type and agv.jobType=:jobType and agv.status in ('OPEN','ATCALL','UP_CONTAINER') ") + @Lock(LockModeType.PESSIMISTIC_WRITE) Long findByStartSlotCode(String startSlotCode, String type, String jobType); + @Query(value = "select count(agv.id) from AgvTask agv where agv.endSlotCode=:endSlotCode and agv.type=:type and agv.jobType=:jobType and agv.status in ('OPEN','ATCALL','UP_CONTAINER') ") + @Lock(LockModeType.PESSIMISTIC_WRITE) Long findByEndSlotCode(String endSlotCode, String type, String jobType); } diff --git a/youchain-system/src/main/java/com/youchain/businessdata/repository/LesRepository.java b/youchain-system/src/main/java/com/youchain/businessdata/repository/LesRepository.java index 3169a04..764190a 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/repository/LesRepository.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/repository/LesRepository.java @@ -2,18 +2,17 @@ package com.youchain.businessdata.repository; import com.youchain.businessdata.domain.Les; import com.youchain.appupdate.response.LesTask; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Query; +import org.springframework.data.jpa.repository.*; +import javax.persistence.LockModeType; import java.util.List; public interface LesRepository extends JpaRepository, JpaSpecificationExecutor { - @Query(value = " from Les les where les.taskCode=:taskCode ") + @Query(value = "select les from Les les where les.taskCode=:taskCode ") Les findByTaskCode(String taskCode); - @Query(value = " from Les les where les.agvTaskId is null and les.onlineNo=:onlineNo and les.srcPositionCode=:srcPositionCode ") + @Query(value = " from Les les where les.agvTaskId is null and les.onlineNo=:onlineNo and les.srcPositionCode=:srcPositionCode and les.status='OPEN' ") List findByOnlineNo(String srcPositionCode, String onlineNo); @Query(value = " from Les les where les.agvTaskId=:agvTaskId and les.dstPositionCode=:currentPositionCode and les.status='OPEN' ") @@ -28,6 +27,11 @@ public interface LesRepository extends JpaRepository, JpaSpecificatio "and les.status = 'ARRIVED'") List findByLinePoint(String dstPositionCode); - @Query(value = " from Les les where les.agvTaskId is null and les.srcPositionCode=:srcPositionCode and les.boxNo in (:boxNos) ") + @Query(value = " from Les les where les.agvTaskId is null and les.srcPositionCode=:srcPositionCode and les.boxNo in (:boxNos) and les.status='OPEN' ") List findByBoxNoAndPoint(String srcPositionCode, List boxNos); + + @Modifying + @Query("update Les set agvTaskId = :agvTaskId where id in :ids") + void batchUpdateAgvTaskId(Long agvTaskId,List ids); + } diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/AgvTaskServiceImpl.java b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/AgvTaskServiceImpl.java index b7a29b8..c412921 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/AgvTaskServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/AgvTaskServiceImpl.java @@ -15,7 +15,6 @@ */ package com.youchain.businessdata.service.impl; -import com.youchain.basicdata.domain.Point; import com.youchain.basicdata.domain.Stock; import com.youchain.businessdata.domain.*; import com.youchain.businessdata.service.*; @@ -33,8 +32,6 @@ import org.springframework.data.domain.Pageable; import java.util.*; import java.io.IOException; -import java.util.stream.Collectors; -import javax.persistence.Query; import javax.servlet.http.HttpServletResponse; diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/LesServiceImpl.java b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/LesServiceImpl.java index 8dfd762..909583b 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/LesServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/LesServiceImpl.java @@ -3,12 +3,10 @@ package com.youchain.businessdata.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.youchain.basicdata.service.PointService; -import com.youchain.businessdata.domain.AgvTask; import com.youchain.businessdata.domain.Les; import com.youchain.businessdata.inputJson.LesRequest; import com.youchain.businessdata.inputJson.PositionCodeRequest; import com.youchain.businessdata.repository.LesRepository; -import com.youchain.businessdata.service.KMReService; import com.youchain.businessdata.service.LesService; import com.youchain.businessdata.service.dto.LesDto; import com.youchain.businessdata.service.dto.LesQueryCriteria; @@ -110,14 +108,20 @@ public class LesServiceImpl implements LesService { validateParams(lesRequest); //验证任务是否存在 - validateLes(lesRequest.getTaskCode()); + String taskCode = lesRequest.getTaskCode(); + validateLes(taskCode); String materialCode = lesRequest.getMaterialCode();//物料代码 //有物料走料箱上线场景;无物料走其余场景 if (StringUtils.isNotEmpty(materialCode)) { - createLes(lesRequest); + try { + createLes(lesRequest); + } catch (Exception e) { + throw new BadRequestException(taskCode + "任务号系统已接收,请勿重复操作"); + } + } else { //直接转发给AGV sendLesTask(JSON.toJSONString(lesRequest)); @@ -273,7 +277,7 @@ public class LesServiceImpl implements LesService { private void sendLesTask(String json) { Dict dict = dictRepository.findDictByName("OPEN"); - String resultJson = ""; + String resultJson; if (dict != null) { resultJson = HttpPostUtil.sendPostReq(UrlApi.submitMission(), json); if (StringUtils.isEmpty(resultJson)) {