From 7046d9d368a640e1ee44b097ae828027939ea402 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Mon, 8 Jun 2026 19:05:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8E=92=E5=8D=95=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redis/constants/RedisKeyConstants.java | 5 ++ .../executor/enums/ErrorCodeConstants.java | 1 + .../admin/plan/OptimizePlanController.java | 4 +- .../controller/admin/plan/PlanController.java | 15 ++++- .../admin/plan/vo/OrderPlanLockReqVO.java | 23 ++++++++ .../optimizeplan/OptimizePlanService.java | 2 +- .../optimizeplan/OptimizePlanServiceImpl.java | 8 ++- .../executor/service/plan/PlanService.java | 14 +++++ .../service/plan/PlanServiceImpl.java | 59 ++++++++++++++++++- 9 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPlanLockReqVO.java diff --git a/cf-framework/cf-spring-boot-starter-redis/src/main/java/com/cf/imes/framework/redis/constants/RedisKeyConstants.java b/cf-framework/cf-spring-boot-starter-redis/src/main/java/com/cf/imes/framework/redis/constants/RedisKeyConstants.java index d0ba1caa9..55862b570 100644 --- a/cf-framework/cf-spring-boot-starter-redis/src/main/java/com/cf/imes/framework/redis/constants/RedisKeyConstants.java +++ b/cf-framework/cf-spring-boot-starter-redis/src/main/java/com/cf/imes/framework/redis/constants/RedisKeyConstants.java @@ -27,4 +27,9 @@ public class RedisKeyConstants { * 字典数据i18n缓存刷新 */ public static final String DICT_DATA_I18N_CACHE_REFRESH = "DICT_DATA_I18N_CACHE_REFRESH"; + + /** + * 排单优化锁 + */ + public static final String ORDER_PLAN_OPTIMIZE_KEY = "order_plan_optimize:%s"; } diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java index 6d5bdf371..442b6e22c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java @@ -24,6 +24,7 @@ public class ErrorCodeConstants { public static final ErrorCode ORDER_PLATE_UPDATE_CONCURRENCY_ERROR = new ErrorCode(1_003_107_012, "order.plate.update.concurrency.error"); public static final ErrorCode GOODS_PLATE_UPDATE_CONCURRENCY_ERROR = new ErrorCode(1_003_107_013, "goods.plate.update.concurrency.error"); public static final ErrorCode BODY_PLATE_UPDATE_CONCURRENCY_ERROR = new ErrorCode(1_003_107_014, "body.plate.update.concurrency.error"); + public static final ErrorCode ORDER_PLAN_LOCKED = new ErrorCode(1_003_107_015, "当前排单已锁定,请稍后再试"); // ========== 订单商品 1_003_108_000 ========== diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java index d09efbeca..ea754fe38 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/OptimizePlanController.java @@ -72,9 +72,9 @@ public class OptimizePlanController { @PreAuthorize("@ss.hasAnyPermissions('placeorder:optimize','production:manager-list:calculate','manage:order-plan:process-scheme','producePlan:order-plan:process-scheme','producePlan:optimize')") public CommonResult getOrderSource(@Schema(description = "订单id") @RequestParam(required = false) Long orderId, @Schema(description = "排单id") @RequestParam(required = false) Long planId, - @Schema(description = "机台Id") @RequestParam(required = false) Long machineId + @Schema(description = "排单值") @RequestParam(required = false) String val ) { - return CommonResult.success(optimizePlanService.getOrderSource(orderId, planId, machineId)); + return CommonResult.success(optimizePlanService.getOrderSource(orderId, planId, val)); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java index 27164b96f..97bd1ca19 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/PlanController.java @@ -193,6 +193,19 @@ public class PlanController { } + @PostMapping("/lock") + @Operation(summary = "获取排单锁") + @PreAuthorize("@ss.hasAnyPermissions('placeorder:optimize','production:manager-list:calculate','manage:order-plan:process-scheme','producePlan:order-plan:process-scheme','producePlan:optimize')") + public CommonResult getPlanLock(@RequestBody OrderPlanLockReqVO orderPlanLockReqVO) { + planService.getPlanLock(orderPlanLockReqVO); + return success(true); + } - + @PostMapping("/release/lock") + @Operation(summary = "释放排单锁") + @PreAuthorize("@ss.hasAnyPermissions('placeorder:optimize','production:manager-list:calculate','manage:order-plan:process-scheme','producePlan:order-plan:process-scheme','producePlan:optimize')") + public CommonResult releasePlanLock(@RequestBody OrderPlanLockReqVO orderPlanLockReqVO) { + planService.releasePlanLock(orderPlanLockReqVO); + return success(true); + } } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPlanLockReqVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPlanLockReqVO.java new file mode 100644 index 000000000..76cb51f64 --- /dev/null +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderPlanLockReqVO.java @@ -0,0 +1,23 @@ +package com.cf.imes.module.executor.controller.admin.plan.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * + * + * @author Gqr + * @since 2026/6/8 16:43 + */ +@Data +@Schema(description = "排单锁定请求参数") +public class OrderPlanLockReqVO { + @Schema(description = "排单ID") + @NotNull(message = "排单ID不能为空") + private Long planId; + + @Schema(description = "排单优化本地值") + @NotNull(message = "排单优化本地值不能为空") + private String val; +} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java index 3a6ffae83..45c6f67c3 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java @@ -27,7 +27,7 @@ public interface OptimizePlanService { Map getLabelDataSourceValue(GetSourceDataReq req); - OrderSource getOrderSource(Long orderId, Long planId, Long machineId); + OrderSource getOrderSource(Long orderId, Long planId, String val); OrderSource getOrderSourceByOrderId(Long orderId); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java index 66f06b429..49542bf93 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java @@ -71,6 +71,7 @@ import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper; import com.cf.imes.module.executor.dal.mysql.remainplaten.RemainPlateMapper; import com.cf.imes.module.executor.enums.ErrorCodeConstants; import com.cf.imes.module.executor.enums.plan.FlowProcessStatus; +import com.cf.imes.module.executor.service.plan.PlanService; import com.cf.imes.module.executor.util.elasticsearch.EsUtils; import com.cf.imes.module.system.api.dataSource.DataSourceApi; import com.cf.imes.module.system.api.machine.MachineApi; @@ -160,6 +161,9 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { @Resource private PlateGoodMapper plateGoodMapper; + @Resource + private PlanService planService; + @Value("${chenfeng.plan.create.plate-threshold:20000}") private int planCreatePlateThreshold; @@ -282,7 +286,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } @Override - public OrderSource getOrderSource(Long orderId, Long planId, Long machineId) { + public OrderSource getOrderSource(Long orderId, Long planId, String val) { if (!Objects.isNull(orderId) && !Objects.isNull(planId)) { throw new ServiceException(ORDER_PLAN_ID_IS_ONE); } @@ -292,6 +296,8 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { return orderSource; } if (ObjectUtil.isNotNull(planId)) { + // 获取排单锁 + planService.getPlanLock(new OrderPlanLockReqVO().setPlanId(planId).setVal(val)); orderSource = getOrderSourceByPlanId(planId); return orderSource; } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java index 58710ffda..c5746d0ae 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java @@ -2,6 +2,7 @@ package com.cf.imes.module.executor.service.plan; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; +import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPlanLockReqVO; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList; import com.cf.imes.module.executor.controller.admin.plan.vo.*; @@ -93,4 +94,17 @@ public interface PlanService { List getPlanPlateList(Long planId); + /** + * 获取排单锁 + * + * @param orderPlanLockReqVO + */ + void getPlanLock(OrderPlanLockReqVO orderPlanLockReqVO); + + /** + * 释放排单锁 + * + * @param orderPlanLockReqVO + */ + void releasePlanLock(OrderPlanLockReqVO orderPlanLockReqVO); } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java index 0b4a89ba7..ebfb1431d 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._types.FieldValue; import co.elastic.clients.elasticsearch.core.UpdateByQueryRequest; @@ -27,6 +28,7 @@ import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.controller.admin.goods.vo.GoodsRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderPlanPlateNumAndAreaRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderRespVO; +import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPlanLockReqVO; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderRoomBodyList; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.RemainBoardInfo; import com.cf.imes.module.executor.controller.admin.plan.vo.*; @@ -59,11 +61,11 @@ import com.cf.imes.module.executor.dal.mysql.remainplaten.RemainPlateMapper; import com.cf.imes.module.executor.enums.ErrorCodeConstants; import com.cf.imes.module.executor.enums.OrderPlanQueryTypeEnum; import com.cf.imes.module.executor.enums.OrderStatusEnum; -import com.cf.imes.module.executor.service.order.OrderService; import com.cf.imes.module.executor.util.elasticsearch.EsUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.aop.framework.AopContext; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; @@ -71,13 +73,16 @@ import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import java.math.BigDecimal; +import java.time.Duration; import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.DATA_DATA_ERROR; +import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.framework.common.util.json.JsonUtils.parseArray; +import static com.cf.imes.framework.redis.constants.RedisKeyConstants.ORDER_PLAN_OPTIMIZE_KEY; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.*; import static com.cf.imes.module.executor.enums.EsIndexEnum.*; @@ -135,7 +140,7 @@ public class PlanServiceImpl implements PlanService { private OrderComponentMapper orderComponentMapper; @Resource - private OrderService orderService; + private StringRedisTemplate stringRedisTemplate; // 重复使用的常量 private static final String FIELD_ORDER_ID = "o.id"; @@ -2087,4 +2092,54 @@ public class PlanServiceImpl implements PlanService { return resultList; } + @Override + public void getPlanLock(OrderPlanLockReqVO orderPlanLockReqVO) { + Long planId = orderPlanLockReqVO.getPlanId(); + String lockValInput = orderPlanLockReqVO.getVal(); + + PlanDO planDO = planMapper.selectById(planId); + + AssertUtils.notEmpty(planDO, PLAN_NOT_EXISTS); + + String planLockKey = String.format(ORDER_PLAN_OPTIMIZE_KEY, planId); + + // 获取优化锁 + String lockVal = stringRedisTemplate.opsForValue().get(planLockKey); + + // 没有锁,尝试获取 + if (StrUtil.isBlank(lockVal)) { + + Boolean success = stringRedisTemplate.opsForValue().setIfAbsent( + planLockKey, + lockValInput, + Duration.ofMinutes(30) + ); + + if (Boolean.TRUE.equals(success)) { + return; + } + + // 极端并发场景 + lockVal = stringRedisTemplate.opsForValue().get(planLockKey); + } + + // 用不同的lockKey去请求优化提示已锁单 + if (!StrUtil.equals(lockVal, lockValInput)) { + throw exception(ORDER_PLAN_LOCKED); + } + } + + @Override + public void releasePlanLock(OrderPlanLockReqVO orderPlanLockReqVO) { + Long planId = orderPlanLockReqVO.getPlanId(); + String lockValInput = orderPlanLockReqVO.getVal(); + + String lockKey = String.format(ORDER_PLAN_OPTIMIZE_KEY, planId); + + String lockVal = stringRedisTemplate.opsForValue().get(lockKey); + + if (Objects.equals(lockVal, lockValInput)) { + stringRedisTemplate.delete(lockKey); + } + } } \ No newline at end of file