From 04dc01cd25ea66f845ebec183b2399f056a61118 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期一, 27 四月 2026 13:26:27 +0800
Subject: [PATCH] fix: lock auto tune rollback before source lookup

---
 src/main/java/com/zy/ai/service/impl/AutoTuneApplyServiceImpl.java |   42 +++++++++++++++++++++++++++++++-----------
 1 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/src/main/java/com/zy/ai/service/impl/AutoTuneApplyServiceImpl.java b/src/main/java/com/zy/ai/service/impl/AutoTuneApplyServiceImpl.java
index 3c42210..12b5e4c 100644
--- a/src/main/java/com/zy/ai/service/impl/AutoTuneApplyServiceImpl.java
+++ b/src/main/java/com/zy/ai/service/impl/AutoTuneApplyServiceImpl.java
@@ -198,19 +198,18 @@
         Date now = new Date();
         AiAutoTuneJob rollbackJob = createRollbackJob(reason, now);
 
-        List<AiAutoTuneChange> sourceChanges = findLatestSuccessfulChanges();
-        if (sourceChanges.isEmpty()) {
-            persistNoRollbackSourceJobInTransaction(rollbackJob, now);
-            return buildResult(rollbackJob, new ArrayList<>(), false);
-        }
-
         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, sourceChanges, now, lockKey);
+            return rejectRollbackForUnavailableLock(reason, now, lockKey);
         }
 
         try {
+            List<AiAutoTuneChange> sourceChanges = findLatestSuccessfulChanges();
+            if (sourceChanges.isEmpty()) {
+                persistNoRollbackSourceJobInTransaction(rollbackJob, now);
+                return buildResult(rollbackJob, new ArrayList<>(), false);
+            }
             try {
                 RollbackPersistenceResult persistenceResult = persistRollbackResultInTransaction(
                         rollbackJob,
@@ -236,16 +235,13 @@
     }
 
     private AutoTuneApplyResult rejectRollbackForUnavailableLock(String reason,
-                                                                 List<AiAutoTuneChange> sourceChanges,
                                                                  Date now,
                                                                  String lockKey) {
         boolean lockKeyExists = redisUtil.hasKey(lockKey);
         LOGGER.warn("鐢宠AI鑷姩璋冨弬 rollback 閿佸け璐ワ紝lockKey={}, lockKeyExists={}", lockKey, lockKeyExists);
         AiAutoTuneJob rollbackJob = createRollbackJob(reason, now);
-        RollbackPersistenceResult persistenceResult = persistFailedRollbackResultInTransaction(
+        RollbackPersistenceResult persistenceResult = persistRollbackLockFailureInTransaction(
                 rollbackJob,
-                sourceChanges,
-                new IllegalStateException(APPLY_LOCK_BUSY_REASON),
                 now
         );
         return buildResult(rollbackJob, persistenceResult.getRollbackChanges(), false);
@@ -542,6 +538,18 @@
         });
     }
 
+    private RollbackPersistenceResult persistRollbackLockFailureInTransaction(AiAutoTuneJob rollbackJob, Date now) {
+        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
+        return transactionTemplate.execute(status -> {
+            saveJob(rollbackJob);
+            List<AiAutoTuneChange> rollbackChanges = buildRollbackLockFailureChanges(rollbackJob.getId(), now);
+            saveAuditChanges(rollbackChanges);
+            finishRollbackJob(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;
@@ -564,6 +572,18 @@
         return new RollbackPersistenceResult(rollbackChanges, refreshConfigCache);
     }
 
+    private List<AiAutoTuneChange> buildRollbackLockFailureChanges(Long rollbackJobId, Date now) {
+        AiAutoTuneChange rollbackChange = new AiAutoTuneChange();
+        rollbackChange.setJobId(rollbackJobId);
+        rollbackChange.setTargetType(AutoTuneTriggerType.ROLLBACK.getCode());
+        rollbackChange.setTargetId("");
+        rollbackChange.setTargetKey("latest_successful_job");
+        rollbackChange.setResultStatus(ChangeStatus.FAILED.getCode());
+        rollbackChange.setRejectReason(APPLY_LOCK_BUSY_REASON);
+        rollbackChange.setCreateTime(now);
+        return List.of(rollbackChange);
+    }
+
     private void refreshRollbackConfigCacheIfNeeded(RollbackPersistenceResult persistenceResult) {
         if (persistenceResult != null && persistenceResult.isRefreshConfigCache()) {
             configService.refreshSystemConfigCache();

--
Gitblit v1.9.1