diff --git a/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java b/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java index 6c6586fb..9b9fa02f 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java +++ b/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/LocalRunnerClient.java @@ -176,6 +176,7 @@ public class LocalRunnerClient extends RunnerClient { if (!closed.compareAndSet(false, true)) { return; } + mcpConfigWatcher.unregisterPolicyListener(); closeQuietly(mcpConfigWatcher); closeQuietly(dynamicActionMcpManager); closeQuietly(mcpDescWatcher); diff --git a/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/policy/ExecutionPolicy.kt b/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/policy/ExecutionPolicy.kt index 90434ed8..7dbf0082 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/policy/ExecutionPolicy.kt +++ b/Partner-Core/src/main/java/work/slhaf/partner/core/action/runner/policy/ExecutionPolicy.kt @@ -150,4 +150,8 @@ interface RunnerExecutionPolicyListener { fun registerPolicyListener() { ExecutionPolicyRegistry.addListener(this) } + + fun unregisterPolicyListener() { + ExecutionPolicyRegistry.removeListener(this) + } } diff --git a/Partner-Core/src/test/java/work/slhaf/partner/core/action/runner/LocalRunnerClientCloseTest.java b/Partner-Core/src/test/java/work/slhaf/partner/core/action/runner/LocalRunnerClientCloseTest.java new file mode 100644 index 00000000..2c848894 --- /dev/null +++ b/Partner-Core/src/test/java/work/slhaf/partner/core/action/runner/LocalRunnerClientCloseTest.java @@ -0,0 +1,54 @@ +package work.slhaf.partner.core.action.runner; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import work.slhaf.partner.core.action.entity.MetaActionInfo; +import work.slhaf.partner.core.action.runner.policy.ExecutionPolicyRegistry; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +class LocalRunnerClientCloseTest { + + private static String originalUserHome; + + @BeforeAll + static void prepareTestHome() throws IOException { + originalUserHome = System.getProperty("user.home"); + Path tempHome = Files.createTempDirectory("partner-test-home"); + System.setProperty("user.home", tempHome.toString()); + } + + @AfterAll + static void restoreUserHome() { + if (originalUserHome != null) { + System.setProperty("user.home", originalUserHome); + } + } + + @Test + void testLocalRunnerClientCloseUnregistersPolicyListener(@TempDir Path tempDir) throws Exception { + Field listenersField = ExecutionPolicyRegistry.class.getDeclaredField("listeners"); + listenersField.setAccessible(true); + @SuppressWarnings("unchecked") + CopyOnWriteArraySet listeners = (CopyOnWriteArraySet) listenersField.get(ExecutionPolicyRegistry.INSTANCE); + int before = listeners.size(); + + ConcurrentHashMap existedMetaActions = new ConcurrentHashMap<>(); + try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { + LocalRunnerClient client = new LocalRunnerClient(existedMetaActions, executor, tempDir.toString()); + Assertions.assertEquals(before + 1, listeners.size()); + client.close(); + Assertions.assertEquals(before, listeners.size()); + } + } +}