From de98fe81cca90dd855e0519f065e77fce56333ef Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 26 八月 2026 16:28:30 +0800
Subject: [PATCH] fix(device): address adapter discovery review

---
 ruoyi-device/src/test/java/com/ruoyi/device/registry/DeviceAdapterRegistryTest.java |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/ruoyi-device/src/test/java/com/ruoyi/device/registry/DeviceAdapterRegistryTest.java b/ruoyi-device/src/test/java/com/ruoyi/device/registry/DeviceAdapterRegistryTest.java
index b062175..83c002c 100644
--- a/ruoyi-device/src/test/java/com/ruoyi/device/registry/DeviceAdapterRegistryTest.java
+++ b/ruoyi-device/src/test/java/com/ruoyi/device/registry/DeviceAdapterRegistryTest.java
@@ -7,6 +7,11 @@
 import static org.junit.jupiter.api.Assertions.assertNotSame;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import org.junit.jupiter.api.Test;
 import com.ruoyi.device.api.DeviceAdapter;
@@ -25,10 +30,10 @@
             AdapterInstanceConfig config = config("127.0.0.1", true);
 
             registry.synchronize(config);
-            DeviceAdapter first = registry.require("lab-bts");
+            DeviceAdapter first = registry.execute("lab-bts", adapter -> adapter);
             registry.synchronize(config);
 
-            assertSame(first, registry.require("lab-bts"));
+            assertSame(first, registry.execute("lab-bts", adapter -> adapter));
             assertFalse(factory.adapters.get(0).closed.get());
         }
     }
@@ -45,13 +50,106 @@
             registry.synchronize(config("127.0.0.2", true));
 
             assertTrue(first.closed.get());
-            assertNotSame(first, registry.require("lab-bts"));
+            assertNotSame(first, registry.execute("lab-bts", adapter -> adapter));
 
             registry.synchronize(config("127.0.0.2", false));
 
             assertTrue(factory.adapters.get(1).closed.get());
             assertFalse(registry.contains("lab-bts"));
-            assertThrows(AdapterRegistryException.class, () -> registry.require("lab-bts"));
+            assertThrows(AdapterRegistryException.class,
+                    () -> registry.execute("lab-bts", adapter -> adapter));
+        }
+    }
+
+    @Test
+    void serializesOperationsForTheSameAdapterInstance() throws Exception
+    {
+        RecordingFactory factory = new RecordingFactory();
+        try (DeviceAdapterRegistry registry = new DeviceAdapterRegistry(List.of(factory)))
+        {
+            registry.synchronize(config("127.0.0.1", true));
+            CountDownLatch firstEntered = new CountDownLatch(1);
+            CountDownLatch releaseFirst = new CountDownLatch(1);
+            CountDownLatch secondEntered = new CountDownLatch(1);
+            ExecutorService executor = Executors.newFixedThreadPool(2);
+            try
+            {
+                Future<?> first = executor.submit(() -> registry.execute("lab-bts", adapter -> {
+                    firstEntered.countDown();
+                    await(releaseFirst);
+                    return null;
+                }));
+                assertTrue(firstEntered.await(1, TimeUnit.SECONDS));
+
+                Future<?> second = executor.submit(() -> registry.execute("lab-bts", adapter -> {
+                    secondEntered.countDown();
+                    return null;
+                }));
+
+                assertFalse(secondEntered.await(100, TimeUnit.MILLISECONDS));
+                releaseFirst.countDown();
+                first.get(1, TimeUnit.SECONDS);
+                second.get(1, TimeUnit.SECONDS);
+                assertTrue(secondEntered.await(1, TimeUnit.SECONDS));
+            }
+            finally
+            {
+                executor.shutdownNow();
+            }
+        }
+    }
+
+    @Test
+    void configurationReplacementWaitsForRunningOperationBeforeClosingAdapter() throws Exception
+    {
+        RecordingFactory factory = new RecordingFactory();
+        try (DeviceAdapterRegistry registry = new DeviceAdapterRegistry(List.of(factory)))
+        {
+            registry.synchronize(config("127.0.0.1", true));
+            StubAdapter firstAdapter = factory.adapters.get(0);
+            CountDownLatch operationEntered = new CountDownLatch(1);
+            CountDownLatch releaseOperation = new CountDownLatch(1);
+            CountDownLatch replacementStarted = new CountDownLatch(1);
+            ExecutorService executor = Executors.newFixedThreadPool(2);
+            try
+            {
+                Future<?> operation = executor.submit(() -> registry.execute("lab-bts", adapter -> {
+                    operationEntered.countDown();
+                    await(releaseOperation);
+                    return null;
+                }));
+                assertTrue(operationEntered.await(1, TimeUnit.SECONDS));
+
+                Future<?> replacement = executor.submit(() -> {
+                    replacementStarted.countDown();
+                    registry.synchronize(config("127.0.0.2", true));
+                });
+                assertTrue(replacementStarted.await(1, TimeUnit.SECONDS));
+                assertFalse(replacement.isDone());
+                assertFalse(firstAdapter.closed.get());
+
+                releaseOperation.countDown();
+                operation.get(1, TimeUnit.SECONDS);
+                replacement.get(1, TimeUnit.SECONDS);
+                assertTrue(firstAdapter.closed.get());
+            }
+            finally
+            {
+                executor.shutdownNow();
+            }
+        }
+    }
+
+    private static void await(CountDownLatch latch)
+    {
+        try
+        {
+            if (!latch.await(1, TimeUnit.SECONDS)) throw new AssertionError("等待适配器测试信号超时");
+        }
+        catch (InterruptedException exception)
+        {
+            Thread.currentThread().interrupt();
+            throw new AssertionError("等待适配器测试信号被中断", exception);
         }
     }
 

--
Gitblit v1.7.1