From a69f9ef3839bbf759480a836f46a20809ccec402 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期一, 27 四月 2026 13:14:17 +0800
Subject: [PATCH] fix: prevent running auto tune jobs on apply failure

---
 src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java |   71 ++++++++++++++++++++++++++++++++++-
 1 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java b/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java
index 9519218..138d1f1 100644
--- a/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java
+++ b/src/test/java/com/zy/ai/service/AutoTuneApplyServiceImplTest.java
@@ -93,11 +93,15 @@
 
         AtomicLong jobId = new AtomicLong(100);
         when(aiAutoTuneJobService.save(any(AiAutoTuneJob.class))).thenAnswer(invocation -> {
+            transactionManager.recordJobSaveCall();
             AiAutoTuneJob job = invocation.getArgument(0);
             job.setId(jobId.incrementAndGet());
             return true;
         });
-        when(aiAutoTuneJobService.updateById(any(AiAutoTuneJob.class))).thenReturn(true);
+        when(aiAutoTuneJobService.updateById(any(AiAutoTuneJob.class))).thenAnswer(invocation -> {
+            transactionManager.recordJobUpdateCall();
+            return true;
+        });
         when(aiAutoTuneChangeService.saveBatch(any(Collection.class))).thenReturn(true);
         when(aiAutoTuneChangeService.list(any(Wrapper.class))).thenReturn(Collections.emptyList());
         when(configService.getConfigValue(eq("aiAutoTuneIntervalMinutes"), any())).thenReturn("10");
@@ -321,6 +325,10 @@
         assertEquals("failed", changes.get(0).getResultStatus());
         assertTrue(changes.get(0).getRejectReason().contains("db write failed"));
         assertEquals(1, transactionManager.getRollbackCount());
+        assertTrue(transactionManager.getJobSaveInsideTransactionCount() > 0);
+        assertTrue(transactionManager.getJobUpdateInsideTransactionCount() > 0);
+        assertEquals(0, transactionManager.getJobSaveOutsideTransactionCount());
+        assertEquals(0, transactionManager.getJobUpdateOutsideTransactionCount());
         verify(redisUtil).compareAndDelete(eq(RedisKeyType.AI_AUTO_TUNE_APPLY_LOCK.key), anyString());
     }
 
@@ -340,6 +348,10 @@
         assertEquals("failed", changes.get(0).getResultStatus());
         assertTrue(changes.get(0).getRejectReason().contains("audit failed"));
         assertEquals(1, transactionManager.getRollbackCount());
+        assertTrue(transactionManager.getJobSaveInsideTransactionCount() > 0);
+        assertTrue(transactionManager.getJobUpdateInsideTransactionCount() > 0);
+        assertEquals(0, transactionManager.getJobSaveOutsideTransactionCount());
+        assertEquals(0, transactionManager.getJobUpdateOutsideTransactionCount());
         verify(configService).saveConfigValue("conveyorStationTaskLimit", "15");
         verify(configService, never()).refreshSystemConfigCache();
         verify(redisUtil).compareAndDelete(eq(RedisKeyType.AI_AUTO_TUNE_APPLY_LOCK.key), anyString());
@@ -348,7 +360,10 @@
     @Test
     void jobUpdateFailureRollsBackTargetWriteTransaction() {
         when(configService.getOne(any(Wrapper.class))).thenReturn(config("conveyorStationTaskLimit", "10"));
-        when(aiAutoTuneJobService.updateById(any(AiAutoTuneJob.class))).thenReturn(false);
+        when(aiAutoTuneJobService.updateById(any(AiAutoTuneJob.class))).thenAnswer(invocation -> {
+            transactionManager.recordJobUpdateCall();
+            return false;
+        });
 
         IllegalStateException exception = assertThrows(IllegalStateException.class,
                 () -> service.apply(request(false, command("sys_config", null, "conveyorStationTaskLimit", "15"))));
@@ -356,6 +371,10 @@
         assertTrue(exception.getMessage().contains("鏇存柊璋冨弬浠诲姟鐘舵�佸け璐�"));
         assertEquals(2, transactionManager.getRollbackCount());
         assertEquals(0, transactionManager.getCommitCount());
+        assertTrue(transactionManager.getJobSaveInsideTransactionCount() > 0);
+        assertTrue(transactionManager.getJobUpdateInsideTransactionCount() > 0);
+        assertEquals(0, transactionManager.getJobSaveOutsideTransactionCount());
+        assertEquals(0, transactionManager.getJobUpdateOutsideTransactionCount());
         verify(configService).saveConfigValue("conveyorStationTaskLimit", "15");
         verify(configService, never()).refreshSystemConfigCache();
         verify(redisUtil).compareAndDelete(eq(RedisKeyType.AI_AUTO_TUNE_APPLY_LOCK.key), anyString());
@@ -372,9 +391,15 @@
         assertFalse(result.getSuccess());
         assertEquals("failed", updatedJob.getStatus());
         assertEquals("failed", changes.get(0).getResultStatus());
-        assertTrue(changes.get(0).getRejectReason().contains("姝e湪鎵ц"));
+        assertTrue(changes.get(0).getRejectReason().contains("閿佷笉鍙敤"));
+        assertTrue(changes.get(0).getRejectReason().contains("Redis"));
+        assertTrue(transactionManager.getJobSaveInsideTransactionCount() > 0);
+        assertTrue(transactionManager.getJobUpdateInsideTransactionCount() > 0);
+        assertEquals(0, transactionManager.getJobSaveOutsideTransactionCount());
+        assertEquals(0, transactionManager.getJobUpdateOutsideTransactionCount());
         verify(configService, never()).getOne(any(Wrapper.class));
         verify(configService, never()).saveConfigValue(any(), any());
+        verify(redisUtil).hasKey(RedisKeyType.AI_AUTO_TUNE_APPLY_LOCK.key);
         verify(redisUtil, never()).compareAndDelete(anyString(), anyString());
     }
 
@@ -526,21 +551,45 @@
         private int beginCount;
         private int commitCount;
         private int rollbackCount;
+        private boolean transactionActive;
+        private int jobSaveInsideTransactionCount;
+        private int jobSaveOutsideTransactionCount;
+        private int jobUpdateInsideTransactionCount;
+        private int jobUpdateOutsideTransactionCount;
 
         @Override
         public TransactionStatus getTransaction(TransactionDefinition definition) {
             beginCount++;
+            transactionActive = true;
             return new SimpleTransactionStatus();
         }
 
         @Override
         public void commit(TransactionStatus status) {
             commitCount++;
+            transactionActive = false;
         }
 
         @Override
         public void rollback(TransactionStatus status) {
             rollbackCount++;
+            transactionActive = false;
+        }
+
+        public void recordJobSaveCall() {
+            if (transactionActive) {
+                jobSaveInsideTransactionCount++;
+            } else {
+                jobSaveOutsideTransactionCount++;
+            }
+        }
+
+        public void recordJobUpdateCall() {
+            if (transactionActive) {
+                jobUpdateInsideTransactionCount++;
+            } else {
+                jobUpdateOutsideTransactionCount++;
+            }
         }
 
         public int getCommitCount() {
@@ -550,5 +599,21 @@
         public int getRollbackCount() {
             return rollbackCount;
         }
+
+        public int getJobSaveInsideTransactionCount() {
+            return jobSaveInsideTransactionCount;
+        }
+
+        public int getJobSaveOutsideTransactionCount() {
+            return jobSaveOutsideTransactionCount;
+        }
+
+        public int getJobUpdateInsideTransactionCount() {
+            return jobUpdateInsideTransactionCount;
+        }
+
+        public int getJobUpdateOutsideTransactionCount() {
+            return jobUpdateOutsideTransactionCount;
+        }
     }
 }

--
Gitblit v1.9.1