From f387c36b171af682c25f877444a01ebbd425e50b Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Thu, 2 Apr 2026 22:55:53 +0800 Subject: [PATCH] refactor(config): prevent registering Configurable after watching started --- .../api/agent/runtime/config/ConfigCenter.kt | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/runtime/config/ConfigCenter.kt b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/runtime/config/ConfigCenter.kt index b5e65da9..0ad0d108 100644 --- a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/runtime/config/ConfigCenter.kt +++ b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/runtime/config/ConfigCenter.kt @@ -8,6 +8,7 @@ import java.io.IOException import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -15,30 +16,38 @@ object ConfigCenter : AutoCloseable { private val log = LoggerFactory.getLogger(ConfigCenter::class.java) val paths = resolvePaths() - private val registrations = mutableMapOf>() + private val registrations = ConcurrentHashMap>() private var watchExecutor: ExecutorService? = null private var watchSupport: DirectoryWatchSupport? = null + @Volatile + private var started = false + @Synchronized fun register(configurable: Configurable) { + + check(!started) { + "ConfigCenter does not allow registration after watching started" + } + val declared = configurable.declare() - val normalized = mutableMapOf>() + val normalized = mutableMapOf>() declared.forEach { (path, registration) -> val normalizedPath = normalizeRelativePath(path) - check(!normalized.containsKey(normalizedPath)) { + check(normalized.putIfAbsent(normalizedPath, registration) != null) { "Duplicated config path declared in the same configurable: $normalizedPath" } - check(!registrations.containsKey(normalizedPath)) { - "Config path already registered: $normalizedPath" - } - - normalized[normalizedPath] = registration } - registrations.putAll(normalized) + normalized.forEach { (path, registration) -> + check(registrations.putIfAbsent(path, registration) != null) { + "Config path already registered: $path" + } + } + } @Synchronized @@ -71,7 +80,9 @@ object ConfigCenter : AutoCloseable { val config = loadConfig(path, registration) registration.init(config) } catch (e: Exception) { - throw AgentLaunchFailedException("Failed to init config", e) + if (registration.configRequired()) { + throw AgentLaunchFailedException("Failed to init config", e) + } } } @@ -173,4 +184,5 @@ interface ConfigRegistration { fun type(): Class fun init(config: T) fun onReload(config: T) {} + fun configRequired(): Boolean }