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"));