This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new d6dee7d7c fix(instance): route batch instance deletion through the 
transactional proxy (#3091)
d6dee7d7c is described below

commit d6dee7d7ccfcf4886f02466ec51452a6928b2cc8
Author: cyberslack_lee <[email protected]>
AuthorDate: Mon Sep 7 21:09:05 2026 +0800

    fix(instance): route batch instance deletion through the transactional 
proxy (#3091)
---
 .../org/apache/rocketmq/studio/instance/InstanceService.java | 12 +++++++++++-
 .../apache/rocketmq/studio/instance/InstanceServiceTest.java |  6 ++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java 
b/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
index c5b78c10f..07178719b 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
@@ -39,6 +39,8 @@ import org.apache.rocketmq.studio.settings.SettingsRepository;
 import jakarta.annotation.PreDestroy;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -70,6 +72,14 @@ public class InstanceService {
     private final SettingsRepository settingsRepository;
     private final RegionNames regionNames;
 
+    // @Lazy self-injection: Spring AOP proxies intercept @Transactional calls 
only when they
+    // originate from outside the bean. Calling deleteInstance() directly from 
within this class
+    // bypasses the proxy, so @Transactional is silently ignored. Injecting 
ourselves via @Lazy
+    // ensures the call goes through the proxy and the transaction boundary is 
honored.
+    @Lazy
+    @Autowired
+    private InstanceService self;
+
     static final int COUNT_PARALLELISM = 8;
     static final int COUNT_QUEUE_CAPACITY = 128;
     static final long COUNT_TIMEOUT_SECONDS = 3;
@@ -666,7 +676,7 @@ public class InstanceService {
         List<String> failed = new ArrayList<>();
         for (String instanceId : normalizedIds) {
             try {
-                deleteInstance(resolveInstanceId(instanceId));
+                self.deleteInstance(resolveInstanceId(instanceId));
                 deleted++;
             } catch (BusinessException ex) {
                 failed.add(instanceId + ": " + ex.getMessage());
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
index 54d3d8f37..a41102eab 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
@@ -53,6 +53,8 @@ import java.util.Optional;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+import org.springframework.test.util.ReflectionTestUtils;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
@@ -856,6 +858,7 @@ class InstanceServiceTest {
         when(instanceProvider.countTopics("1")).thenReturn(0);
         when(instanceProvider.countGroups("1")).thenReturn(0);
         when(instanceRepository.deleteById(1L)).thenReturn(true);
+        ReflectionTestUtils.setField(instanceService, "self", instanceService);
 
         BatchDeleteResultVO result = 
instanceService.deleteInstances(List.of("inst-a", "missing"));
 
@@ -878,6 +881,7 @@ class InstanceServiceTest {
         when(instanceProvider.countTopics("2")).thenReturn(0);
         when(instanceProvider.countGroups("2")).thenReturn(0);
         when(instanceRepository.deleteById(2L)).thenReturn(true);
+        ReflectionTestUtils.setField(instanceService, "self", instanceService);
 
         BatchDeleteResultVO result = 
instanceService.deleteInstances(List.of("inst-a", "inst-b"));
 
@@ -899,6 +903,7 @@ class InstanceServiceTest {
         
when(instanceRepository.findById(1L)).thenReturn(Optional.of(existing));
         
when(providerRegistry.forVendor(InstanceVendor.APACHE)).thenReturn(instanceProvider);
         when(instanceProvider.countTopics("1")).thenThrow(new 
IllegalStateException(oversizedMessage));
+        ReflectionTestUtils.setField(instanceService, "self", instanceService);
 
         BatchDeleteResultVO result = 
instanceService.deleteInstances(List.of("inst-a"));
 
@@ -925,6 +930,7 @@ class InstanceServiceTest {
         when(instanceProvider.countTopics("1")).thenReturn(0);
         when(instanceProvider.countGroups("1")).thenReturn(0);
         when(instanceRepository.deleteById(1L)).thenReturn(true);
+        ReflectionTestUtils.setField(instanceService, "self", instanceService);
 
         BatchDeleteResultVO result = 
instanceService.deleteInstances(List.of("inst-a", " inst-a ", "inst-a"));
 

Reply via email to