| | |
| | | import com.zy.asrs.entity.BasDualCrnp; |
| | | import com.zy.asrs.entity.BasStation; |
| | | import com.zy.asrs.entity.StationFlowCapacity; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.BasCrnpService; |
| | | import com.zy.asrs.service.BasDualCrnpService; |
| | | import com.zy.asrs.service.BasStationService; |
| | | import com.zy.asrs.service.StationFlowCapacityService; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import com.zy.core.enums.RedisKeyType; |
| | | import com.zy.core.enums.WrkStsType; |
| | | import com.zy.system.entity.Config; |
| | | import com.zy.system.service.ConfigService; |
| | | import org.slf4j.Logger; |
| | |
| | | import org.springframework.transaction.support.TransactionTemplate; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Date; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | |
| | | private static final String DIRECTION_OUT = "OUT"; |
| | | private static final long APPLY_LOCK_SECONDS = 120L; |
| | | private static final String APPLY_LOCK_BUSY_REASON = "申请调参锁失败,锁不可用,可能已有任务或 Redis 异常"; |
| | | private static final List<Long> FINAL_WRK_STS_LIST = Arrays.asList( |
| | | WrkStsType.COMPLETE_INBOUND.sts, |
| | | WrkStsType.SETTLE_INBOUND.sts, |
| | | WrkStsType.COMPLETE_OUTBOUND.sts, |
| | | WrkStsType.SETTLE_OUTBOUND.sts, |
| | | WrkStsType.COMPLETE_LOC_MOVE.sts, |
| | | WrkStsType.COMPLETE_CRN_MOVE.sts |
| | | ); |
| | | |
| | | @Autowired |
| | | private AiAutoTuneJobService aiAutoTuneJobService; |
| | |
| | | private BasDualCrnpService basDualCrnpService; |
| | | @Autowired |
| | | private StationFlowCapacityService stationFlowCapacityService; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | | private PlatformTransactionManager transactionManager; |
| | | @Autowired |
| | |
| | | if (config == null) { |
| | | return CurrentValue.rejected("运行参数不存在: " + validatedChange.getTargetKey()); |
| | | } |
| | | return numericCurrentValue(config.getValue(), false, validatedChange.getTargetKey()); |
| | | return numericCurrentValue(config.getValue(), validatedChange.getTargetKey()); |
| | | } |
| | | if (AutoTuneTargetType.STATION.equals(targetType)) { |
| | | BasStation station = basStationService.getById(targetId); |
| | | if (station == null) { |
| | | return CurrentValue.rejected("站点不存在: " + validatedChange.getTargetId()); |
| | | } |
| | | return numericCurrentValue(toText(station.getOutTaskLimit()), true, validatedChange.getTargetKey()); |
| | | return stationOutTaskLimitCurrentValue(station.getOutTaskLimit(), validatedChange.getTargetKey()); |
| | | } |
| | | if (AutoTuneTargetType.CRN.equals(targetType)) { |
| | | BasCrnp crnp = basCrnpService.getById(targetId); |
| | |
| | | return CurrentValue.rejected("堆垛机不存在: " + validatedChange.getTargetId()); |
| | | } |
| | | Integer value = "maxOutTask".equals(validatedChange.getTargetKey()) ? crnp.getMaxOutTask() : crnp.getMaxInTask(); |
| | | return numericCurrentValue(toText(value), false, validatedChange.getTargetKey()); |
| | | return numericCurrentValue(toText(value), validatedChange.getTargetKey()); |
| | | } |
| | | BasDualCrnp dualCrnp = basDualCrnpService.getById(targetId); |
| | | if (dualCrnp == null) { |
| | | return CurrentValue.rejected("双工位堆垛机不存在: " + validatedChange.getTargetId()); |
| | | } |
| | | Integer value = "maxOutTask".equals(validatedChange.getTargetKey()) ? dualCrnp.getMaxOutTask() : dualCrnp.getMaxInTask(); |
| | | return numericCurrentValue(toText(value), false, validatedChange.getTargetKey()); |
| | | return numericCurrentValue(toText(value), validatedChange.getTargetKey()); |
| | | } |
| | | |
| | | private CurrentValue numericCurrentValue(String oldValue, boolean nullOrNegativeAsZero, String targetKey) { |
| | | if (oldValue == null || oldValue.trim().isEmpty()) { |
| | | if (nullOrNegativeAsZero) { |
| | | return CurrentValue.accepted(null, 0); |
| | | private CurrentValue stationOutTaskLimitCurrentValue(Integer outTaskLimit, String targetKey) { |
| | | if (outTaskLimit == null || outTaskLimit < 0) { |
| | | return CurrentValue.rejected(targetKey + " 当前为不限制,需要人工先初始化为有限值后才能自动调参"); |
| | | } |
| | | return numericCurrentValue(toText(outTaskLimit), targetKey); |
| | | } |
| | | |
| | | private CurrentValue numericCurrentValue(String oldValue, String targetKey) { |
| | | if (oldValue == null || oldValue.trim().isEmpty()) { |
| | | return CurrentValue.rejected(targetKey + " 当前值为空,无法计算步长"); |
| | | } |
| | | try { |
| | | Integer parsedValue = Integer.valueOf(oldValue.trim()); |
| | | if (nullOrNegativeAsZero && parsedValue < 0) { |
| | | return CurrentValue.accepted(oldValue, 0); |
| | | } |
| | | return CurrentValue.accepted(oldValue, parsedValue); |
| | | } catch (Exception exception) { |
| | | return CurrentValue.rejected(targetKey + " 当前值不是整数,无法计算步长"); |
| | |
| | | job.setTriggerType(AutoTuneTriggerType.normalize(request.getTriggerType())); |
| | | job.setStatus(AutoTuneJobStatus.RUNNING.getCode()); |
| | | job.setStartTime(now); |
| | | job.setHasActiveTasks(0); |
| | | job.setHasActiveTasks(resolveHasActiveTasksForAudit()); |
| | | job.setPromptSceneCode(PROMPT_SCENE_CODE); |
| | | job.setSummary(dryRun ? "AI自动调参 dry-run: " + safeReason(request.getReason()) : safeReason(request.getReason())); |
| | | job.setIntervalBefore(readIntervalMinutes()); |
| | |
| | | job.setTriggerType(AutoTuneTriggerType.ROLLBACK.getCode()); |
| | | job.setStatus(AutoTuneJobStatus.RUNNING.getCode()); |
| | | job.setStartTime(now); |
| | | job.setHasActiveTasks(0); |
| | | job.setHasActiveTasks(resolveHasActiveTasksForAudit()); |
| | | job.setPromptSceneCode(PROMPT_SCENE_CODE); |
| | | job.setSummary(safeReason(reason)); |
| | | job.setIntervalBefore(readIntervalMinutes()); |
| | |
| | | return job; |
| | | } |
| | | |
| | | private int resolveHasActiveTasksForAudit() { |
| | | if (wrkMastService == null) { |
| | | LOGGER.warn("AI自动调参审计无法获取 WrkMastService,hasActiveTasks 按 0 记录"); |
| | | return 0; |
| | | } |
| | | try { |
| | | QueryWrapper<WrkMast> queryWrapper = new QueryWrapper<>(); |
| | | queryWrapper.and(wrapper -> wrapper.notIn("wrk_sts", FINAL_WRK_STS_LIST).or().isNull("wrk_sts")); |
| | | return wrkMastService.count(queryWrapper) > 0 ? 1 : 0; |
| | | } catch (RuntimeException exception) { |
| | | LOGGER.warn("AI自动调参审计查询未完成任务失败,hasActiveTasks 按 0 记录", exception); |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | private void finishJob(AiAutoTuneJob job, |
| | | AutoTuneApplyRequest request, |
| | | List<AiAutoTuneChange> auditChanges, |