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 24e8eeb5 [ISSUE #1519] Cancel interrupted Aliyun OpenAPI futures
(#1520)
24e8eeb5 is described below
commit 24e8eeb539d8bf142904c9b55d98ce2bead54d68
Author: youngkermit8-coder <[email protected]>
AuthorDate: Tue Aug 11 20:21:10 2026 +0800
[ISSUE #1519] Cancel interrupted Aliyun OpenAPI futures (#1520)
Signed-off-by: youngkermit8-coder <[email protected]>
---
.../provider/alibaba/AliyunClientFactory.java | 1 +
.../provider/alibaba/AliyunClientFactoryTest.java | 37 ++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactory.java
b/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactory.java
index 3e56b467..bb068daf 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactory.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactory.java
@@ -96,6 +96,7 @@ public class AliyunClientFactory {
throw new BusinessException(504,
"Aliyun OpenAPI request timed out after " +
callTimeoutSeconds + " seconds");
} catch (InterruptedException ex) {
+ future.cancel(true);
Thread.currentThread().interrupt();
throw new BusinessException(502, "Aliyun OpenAPI request was
interrupted");
} catch (ExecutionException ex) {
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactoryTest.java
b/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactoryTest.java
index 0eaed03d..3f6c6312 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactoryTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunClientFactoryTest.java
@@ -34,7 +34,11 @@ import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -127,6 +131,39 @@ class AliyunClientFactoryTest {
assertThat(future).isCancelled();
}
+ @Test
+ void callShouldCancelFutureAndPreserveInterruptTest() throws Exception {
+ AliyunClientFactory spy = Mockito.spy(factory);
+ doReturn(asyncClient).when(spy).client(anyString(), anyString());
+ CompletableFuture<Object> future = new CompletableFuture<>();
+ CountDownLatch waiting = new CountDownLatch(1);
+ AtomicReference<Throwable> failure = new AtomicReference<>();
+ AtomicBoolean interrupted = new AtomicBoolean();
+ Thread caller = Thread.ofPlatform().start(() -> {
+ try {
+ spy.call(CREDENTIAL_ID, REGION, client -> {
+ waiting.countDown();
+ return future;
+ });
+ } catch (Throwable throwable) {
+ failure.set(throwable);
+ interrupted.set(Thread.currentThread().isInterrupted());
+ }
+ });
+
+ assertThat(waiting.await(5, TimeUnit.SECONDS)).isTrue();
+ caller.interrupt();
+ caller.join(TimeUnit.SECONDS.toMillis(5));
+
+ assertThat(caller.isAlive()).isFalse();
+ assertThat(future).isCancelled();
+ assertThat(interrupted).isTrue();
+ assertThat(failure.get())
+ .isInstanceOf(BusinessException.class)
+ .extracting("code")
+ .isEqualTo(502);
+ }
+
@Test
void callShouldMapServer404ToBusinessExceptionTest() {
AliyunClientFactory spy = Mockito.spy(factory);