| | |
| | | import com.zy.ai.domain.autotune.AutoTuneApplyRequest; |
| | | import com.zy.ai.domain.autotune.AutoTuneApplyResult; |
| | | import com.zy.ai.domain.autotune.AutoTuneChangeCommand; |
| | | import com.zy.ai.domain.autotune.AutoTuneControlModeSnapshot; |
| | | import com.zy.ai.domain.autotune.AutoTuneJobStatus; |
| | | import com.zy.ai.domain.autotune.AutoTuneRuleDefinition; |
| | | import com.zy.ai.domain.autotune.AutoTuneTargetType; |
| | |
| | | import com.zy.ai.service.AiAutoTuneChangeService; |
| | | import com.zy.ai.service.AiAutoTuneJobService; |
| | | import com.zy.ai.service.AutoTuneApplyService; |
| | | import com.zy.ai.service.AutoTuneControlModeService; |
| | | import com.zy.asrs.entity.BasCrnp; |
| | | 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 Logger LOGGER = LoggerFactory.getLogger(AutoTuneApplyServiceImpl.class); |
| | | private static final String PROMPT_SCENE_CODE = "auto_tune_apply"; |
| | | 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 String ANALYSIS_ONLY_REJECT_REASON = "仅分析模式禁止实际应用/回滚,未修改运行参数"; |
| | | 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; |
| | |
| | | @Autowired |
| | | private ConfigService configService; |
| | | @Autowired |
| | | private AutoTuneControlModeService autoTuneControlModeService; |
| | | @Autowired |
| | | private BasStationService basStationService; |
| | | @Autowired |
| | | private BasCrnpService basCrnpService; |
| | | @Autowired |
| | | private BasDualCrnpService basDualCrnpService; |
| | | @Autowired |
| | | private StationFlowCapacityService stationFlowCapacityService; |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | | private PlatformTransactionManager transactionManager; |
| | | @Autowired |
| | |
| | | @Override |
| | | public AutoTuneApplyResult apply(AutoTuneApplyRequest request) { |
| | | AutoTuneApplyRequest safeRequest = request == null ? new AutoTuneApplyRequest() : request; |
| | | AutoTuneControlModeSnapshot controlMode = currentControlModeSnapshot(); |
| | | boolean dryRun = Boolean.TRUE.equals(safeRequest.getDryRun()); |
| | | Date now = new Date(); |
| | | AiAutoTuneJob job = createJob(safeRequest, dryRun, now); |
| | | |
| | | if (dryRun) { |
| | | return applyDryRun(safeRequest, job, now); |
| | | return applyDryRun(safeRequest, job, now, controlMode); |
| | | } |
| | | return applyRealWithLock(safeRequest, job, now); |
| | | if (isAnalysisOnly(controlMode)) { |
| | | return rejectRealApplyForAnalysisOnly(safeRequest, job, now, controlMode); |
| | | } |
| | | return applyRealWithLock(safeRequest, job, now, controlMode); |
| | | } |
| | | |
| | | private AutoTuneApplyResult applyDryRun(AutoTuneApplyRequest request, AiAutoTuneJob job, Date now) { |
| | | private AutoTuneApplyResult applyDryRun(AutoTuneApplyRequest request, |
| | | AiAutoTuneJob job, |
| | | Date now, |
| | | AutoTuneControlModeSnapshot controlMode) { |
| | | List<ValidatedChange> validatedChanges = validateChanges(request, true, now); |
| | | ApplyPersistenceResult persistenceResult = persistApplyResultInTransaction( |
| | | job, |
| | |
| | | now, |
| | | false |
| | | ); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), true); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), true, controlMode); |
| | | } |
| | | |
| | | private AutoTuneApplyResult applyRealWithLock(AutoTuneApplyRequest request, AiAutoTuneJob job, Date now) { |
| | | private AutoTuneApplyResult applyRealWithLock(AutoTuneApplyRequest request, |
| | | AiAutoTuneJob job, |
| | | Date now, |
| | | AutoTuneControlModeSnapshot controlMode) { |
| | | if (request.getChanges() == null || request.getChanges().isEmpty()) { |
| | | ApplyPersistenceResult persistenceResult = persistApplyResultInTransaction( |
| | | job, |
| | |
| | | now, |
| | | false |
| | | ); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false, controlMode); |
| | | } |
| | | |
| | | String lockKey = RedisKeyType.AI_AUTO_TUNE_APPLY_LOCK.key; |
| | | String lockToken = UUID.randomUUID().toString(); |
| | | if (!redisUtil.trySetStringIfAbsent(lockKey, lockToken, APPLY_LOCK_SECONDS)) { |
| | | return rejectRealApplyForUnavailableLock(request, job, now, lockKey); |
| | | return rejectRealApplyForUnavailableLock(request, job, now, lockKey, controlMode); |
| | | } |
| | | |
| | | try { |
| | |
| | | now, |
| | | false |
| | | ); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false, controlMode); |
| | | } |
| | | |
| | | try { |
| | |
| | | true |
| | | ); |
| | | refreshSystemConfigCacheSafely(persistenceResult); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false, controlMode); |
| | | } catch (RuntimeException exception) { |
| | | markWriteFailure(validatedChanges, exception); |
| | | Date failureNow = new Date(); |
| | |
| | | failureNow, |
| | | false |
| | | ); |
| | | return buildResult(failureJob, persistenceResult.getAuditChanges(), false); |
| | | return buildResult(failureJob, persistenceResult.getAuditChanges(), false, controlMode); |
| | | } |
| | | } finally { |
| | | redisUtil.compareAndDelete(lockKey, lockToken); |
| | |
| | | private AutoTuneApplyResult rejectRealApplyForUnavailableLock(AutoTuneApplyRequest request, |
| | | AiAutoTuneJob job, |
| | | Date now, |
| | | String lockKey) { |
| | | String lockKey, |
| | | AutoTuneControlModeSnapshot controlMode) { |
| | | boolean lockKeyExists = redisUtil.hasKey(lockKey); |
| | | LOGGER.warn("申请AI自动调参 apply 锁失败,lockKey={}, lockKeyExists={}", lockKey, lockKeyExists); |
| | | List<ValidatedChange> validatedChanges = buildLockBusyChanges(request); |
| | |
| | | now, |
| | | false |
| | | ); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false); |
| | | return buildResult(job, persistenceResult.getAuditChanges(), false, controlMode); |
| | | } |
| | | |
| | | private AutoTuneApplyResult rejectRealApplyForAnalysisOnly(AutoTuneApplyRequest request, |
| | | AiAutoTuneJob job, |
| | | Date now, |
| | | AutoTuneControlModeSnapshot controlMode) { |
| | | ApplyPersistenceResult persistenceResult = persistAnalysisOnlyApplyRejectionInTransaction(job, request, now); |
| | | AutoTuneApplyResult result = buildResult(job, persistenceResult.getAuditChanges(), false, controlMode); |
| | | result.setAnalysisOnly(true); |
| | | result.setNoApply(true); |
| | | return result; |
| | | } |
| | | |
| | | private List<ValidatedChange> buildLockBusyChanges(AutoTuneApplyRequest request) { |
| | |
| | | |
| | | @Override |
| | | public AutoTuneApplyResult rollbackLastSuccessfulJob(String reason) { |
| | | AutoTuneControlModeSnapshot controlMode = currentControlModeSnapshot(); |
| | | Date now = new Date(); |
| | | AiAutoTuneJob rollbackJob = createRollbackJob(reason, now); |
| | | if (isAnalysisOnly(controlMode)) { |
| | | return rejectRollbackForAnalysisOnly(rollbackJob, now, controlMode); |
| | | } |
| | | |
| | | String lockKey = RedisKeyType.AI_AUTO_TUNE_APPLY_LOCK.key; |
| | | String lockToken = UUID.randomUUID().toString(); |
| | | if (!redisUtil.trySetStringIfAbsent(lockKey, lockToken, APPLY_LOCK_SECONDS)) { |
| | | return rejectRollbackForUnavailableLock(reason, now, lockKey); |
| | | return rejectRollbackForUnavailableLock(reason, now, lockKey, controlMode); |
| | | } |
| | | |
| | | try { |
| | | List<AiAutoTuneChange> sourceChanges = findLatestSuccessfulChanges(); |
| | | if (sourceChanges.isEmpty()) { |
| | | persistNoRollbackSourceJobInTransaction(rollbackJob, now); |
| | | return buildResult(rollbackJob, new ArrayList<>(), false); |
| | | return buildResult(rollbackJob, new ArrayList<>(), false, controlMode); |
| | | } |
| | | try { |
| | | RollbackPersistenceResult persistenceResult = persistRollbackResultInTransaction( |
| | |
| | | now |
| | | ); |
| | | refreshRollbackConfigCacheSafely(persistenceResult); |
| | | return buildResult(rollbackJob, persistenceResult.getRollbackChanges(), false); |
| | | return buildResult(rollbackJob, persistenceResult.getRollbackChanges(), false, controlMode); |
| | | } catch (RuntimeException exception) { |
| | | Date failureNow = new Date(); |
| | | AiAutoTuneJob failureJob = createRollbackJob(reason, failureNow); |
| | |
| | | exception, |
| | | failureNow |
| | | ); |
| | | return buildResult(failureJob, persistenceResult.getRollbackChanges(), false); |
| | | return buildResult(failureJob, persistenceResult.getRollbackChanges(), false, controlMode); |
| | | } |
| | | } finally { |
| | | redisUtil.compareAndDelete(lockKey, lockToken); |
| | |
| | | |
| | | private AutoTuneApplyResult rejectRollbackForUnavailableLock(String reason, |
| | | Date now, |
| | | String lockKey) { |
| | | String lockKey, |
| | | AutoTuneControlModeSnapshot controlMode) { |
| | | boolean lockKeyExists = redisUtil.hasKey(lockKey); |
| | | LOGGER.warn("申请AI自动调参 rollback 锁失败,lockKey={}, lockKeyExists={}", lockKey, lockKeyExists); |
| | | AiAutoTuneJob rollbackJob = createRollbackJob(reason, now); |
| | |
| | | rollbackJob, |
| | | now |
| | | ); |
| | | return buildResult(rollbackJob, persistenceResult.getRollbackChanges(), false); |
| | | return buildResult(rollbackJob, persistenceResult.getRollbackChanges(), false, controlMode); |
| | | } |
| | | |
| | | private AutoTuneApplyResult rejectRollbackForAnalysisOnly(AiAutoTuneJob rollbackJob, |
| | | Date now, |
| | | AutoTuneControlModeSnapshot controlMode) { |
| | | RollbackPersistenceResult persistenceResult = persistAnalysisOnlyRollbackRejectionInTransaction( |
| | | rollbackJob, |
| | | now |
| | | ); |
| | | AutoTuneApplyResult result = buildResult(rollbackJob, persistenceResult.getRollbackChanges(), false, controlMode); |
| | | result.setAnalysisOnly(true); |
| | | result.setNoApply(true); |
| | | return result; |
| | | } |
| | | |
| | | private List<ValidatedChange> validateChanges(AutoTuneApplyRequest request, boolean dryRun, Date now) { |
| | |
| | | Integer maxValue = resolveMaxValue(validatedChange, rule, requestedValue); |
| | | if (maxValue == null) { |
| | | return validatedChange.reject("站点 " + validatedChange.getTargetId() |
| | | + " 缺少 OUT 方向 bufferCapacity,无法证明 outTaskLimit 上限"); |
| | | + " 缺少 outBufferCapacity,无法证明 outTaskLimit 上限"); |
| | | } |
| | | if (requestedValue < rule.getMinValue() || requestedValue > maxValue) { |
| | | return validatedChange.reject(validatedChange.getTargetKey() + " 必须在 " |
| | |
| | | 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) { |
| | | 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()) { |
| | | if (nullOrNegativeAsZero) { |
| | | return CurrentValue.accepted(null, 0); |
| | | } |
| | | 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 + " 当前值不是整数,无法计算步长"); |
| | |
| | | return rule.getMaxValue(); |
| | | } |
| | | Integer targetId = parseTargetId(validatedChange.getTargetId(), rule.getTargetType()); |
| | | StationFlowCapacity capacity = stationFlowCapacityService.getOne( |
| | | new QueryWrapper<StationFlowCapacity>() |
| | | .eq("station_id", targetId) |
| | | .eq("direction_code", DIRECTION_OUT) |
| | | .last("limit 1") |
| | | ); |
| | | if (capacity == null || capacity.getBufferCapacity() == null) { |
| | | BasStation station = basStationService.getById(targetId); |
| | | if (station == null || station.getOutBufferCapacity() == null) { |
| | | return requestedValue == 0 ? 0 : null; |
| | | } |
| | | return Math.max(0, capacity.getBufferCapacity()); |
| | | return Math.max(0, station.getOutBufferCapacity()); |
| | | } |
| | | |
| | | private Date findCooldownExpireTime(ValidatedChange validatedChange, Date now) { |
| | |
| | | }); |
| | | } |
| | | |
| | | private ApplyPersistenceResult persistAnalysisOnlyApplyRejectionInTransaction(AiAutoTuneJob job, |
| | | AutoTuneApplyRequest request, |
| | | Date now) { |
| | | TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); |
| | | return transactionTemplate.execute(status -> { |
| | | saveJob(job); |
| | | List<AiAutoTuneChange> auditChanges = buildAnalysisOnlyApplyChanges(job.getId(), request, now); |
| | | saveAuditChanges(auditChanges); |
| | | finishAnalysisOnlyRejectedJob(job, auditChanges, now); |
| | | updateJob(job); |
| | | return new ApplyPersistenceResult(auditChanges, false); |
| | | }); |
| | | } |
| | | |
| | | private RollbackPersistenceResult persistAnalysisOnlyRollbackRejectionInTransaction(AiAutoTuneJob rollbackJob, |
| | | Date now) { |
| | | TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); |
| | | return transactionTemplate.execute(status -> { |
| | | saveJob(rollbackJob); |
| | | List<AiAutoTuneChange> rollbackChanges = buildAnalysisOnlyRollbackChanges(rollbackJob.getId(), now); |
| | | saveAuditChanges(rollbackChanges); |
| | | finishAnalysisOnlyRejectedJob(rollbackJob, rollbackChanges, now); |
| | | updateJob(rollbackJob); |
| | | return new RollbackPersistenceResult(rollbackChanges, false); |
| | | }); |
| | | } |
| | | |
| | | private RollbackPersistenceResult rollbackChanges(Long rollbackJobId, List<AiAutoTuneChange> sourceChanges, Date now) { |
| | | List<AiAutoTuneChange> rollbackChanges = new ArrayList<>(); |
| | | boolean refreshConfigCache = false; |
| | |
| | | rollbackChange.setRejectReason(APPLY_LOCK_BUSY_REASON); |
| | | rollbackChange.setCreateTime(now); |
| | | return List.of(rollbackChange); |
| | | } |
| | | |
| | | private List<AiAutoTuneChange> buildAnalysisOnlyApplyChanges(Long jobId, |
| | | AutoTuneApplyRequest request, |
| | | Date now) { |
| | | List<AiAutoTuneChange> changes = new ArrayList<>(); |
| | | List<AutoTuneChangeCommand> commands = request == null ? null : request.getChanges(); |
| | | if (commands == null || commands.isEmpty()) { |
| | | changes.add(buildAnalysisOnlyChange(jobId, "analysis_only", "", "apply", null, now)); |
| | | return changes; |
| | | } |
| | | for (AutoTuneChangeCommand command : commands) { |
| | | changes.add(buildAnalysisOnlyChange( |
| | | jobId, |
| | | normalizeText(command == null ? null : command.getTargetType()), |
| | | normalizeText(command == null ? null : command.getTargetId()), |
| | | normalizeText(command == null ? null : command.getTargetKey()), |
| | | command == null ? null : command.getNewValue(), |
| | | now |
| | | )); |
| | | } |
| | | return changes; |
| | | } |
| | | |
| | | private List<AiAutoTuneChange> buildAnalysisOnlyRollbackChanges(Long jobId, Date now) { |
| | | AiAutoTuneChange rollbackChange = buildAnalysisOnlyChange( |
| | | jobId, |
| | | "analysis_only", |
| | | "", |
| | | "rollback", |
| | | null, |
| | | now |
| | | ); |
| | | return List.of(rollbackChange); |
| | | } |
| | | |
| | | private AiAutoTuneChange buildAnalysisOnlyChange(Long jobId, |
| | | String targetType, |
| | | String targetId, |
| | | String targetKey, |
| | | String requestedValue, |
| | | Date now) { |
| | | AiAutoTuneChange change = new AiAutoTuneChange(); |
| | | change.setJobId(jobId); |
| | | change.setTargetType(targetType); |
| | | change.setTargetId(targetId); |
| | | change.setTargetKey(targetKey); |
| | | change.setRequestedValue(requestedValue); |
| | | change.setResultStatus(ChangeStatus.REJECTED.getCode()); |
| | | change.setRejectReason(ANALYSIS_ONLY_REJECT_REASON); |
| | | change.setCreateTime(now); |
| | | return change; |
| | | } |
| | | |
| | | private void refreshRollbackConfigCacheSafely(RollbackPersistenceResult persistenceResult) { |
| | |
| | | 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()); |
| | |
| | | job.setTotalTokens(0); |
| | | job.setCreateTime(now); |
| | | 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, |
| | |
| | | if (rejectCount > 0) { |
| | | job.setErrorMessage(firstRejectReason(auditChanges)); |
| | | } |
| | | } |
| | | |
| | | private void finishAnalysisOnlyRejectedJob(AiAutoTuneJob job, List<AiAutoTuneChange> changes, Date now) { |
| | | int rejectCount = Math.max(1, countRejected(changes)); |
| | | job.setFinishTime(now); |
| | | job.setSuccessCount(0); |
| | | job.setRejectCount(rejectCount); |
| | | job.setIntervalAfter(readIntervalMinutes()); |
| | | job.setStatus(AutoTuneJobStatus.REJECTED.getCode()); |
| | | job.setSummary(ANALYSIS_ONLY_REJECT_REASON); |
| | | job.setErrorMessage(ANALYSIS_ONLY_REJECT_REASON); |
| | | } |
| | | |
| | | private void finishRollbackJob(AiAutoTuneJob job, List<AiAutoTuneChange> changes, Date now) { |
| | |
| | | return !AutoTuneTriggerType.ROLLBACK.getCode().equals(job.getTriggerType()); |
| | | } |
| | | |
| | | private AutoTuneApplyResult buildResult(AiAutoTuneJob job, List<AiAutoTuneChange> changes, boolean dryRun) { |
| | | private AutoTuneApplyResult buildResult(AiAutoTuneJob job, |
| | | List<AiAutoTuneChange> changes, |
| | | boolean dryRun, |
| | | AutoTuneControlModeSnapshot controlMode) { |
| | | AutoTuneApplyResult result = new AutoTuneApplyResult(); |
| | | result.setDryRun(dryRun); |
| | | result.setSuccess(AutoTuneJobStatus.SUCCESS.getCode().equals(job.getStatus()) |
| | | || AutoTuneJobStatus.NO_CHANGE.getCode().equals(job.getStatus())); |
| | | result.setAnalysisOnly(isAnalysisOnly(controlMode)); |
| | | result.setNoApply(false); |
| | | result.setJobId(job.getId()); |
| | | result.setSummary(job.getSummary()); |
| | | result.setSuccessCount(job.getSuccessCount()); |
| | |
| | | } |
| | | } |
| | | |
| | | private AutoTuneControlModeSnapshot currentControlModeSnapshot() { |
| | | return autoTuneControlModeService.currentMode(); |
| | | } |
| | | |
| | | private boolean isAnalysisOnly(AutoTuneControlModeSnapshot controlMode) { |
| | | return controlMode == null || Boolean.TRUE.equals(controlMode.getAnalysisOnly()); |
| | | } |
| | | |
| | | private String toText(Integer value) { |
| | | return value == null ? null : String.valueOf(value); |
| | | } |