fix(mq-starter): 修复启动 fail-fast 校验 review 发现的缺陷(relaxed binding / 逃生开关 / redis 假地址)

workflow 多智能体 review 后修复:

- rocketmq 探测改用 Binder 读 rocketmq.name-server,与 driver(RocketMQProperties)同源、
  享受 relaxed binding,修复 camelCase(rocketmq.nameServer) 被误判为「未配置」而错误 fail-fast
- MqStartupChecks 逃生开关只认严格 false(忽略大小写/空白),缺省或非法值一律继续校验,
  不再因非法布尔值(如 enabled=disabled)抛类型转换异常炸掉启动
- redis 探测 target() 对 cluster/sentinel 回退到指向真实配置项的文案,
  不再假报使用者从未配过的 localhost:6379
- 补齐回归测试:camelCase 键 / 非法开关值继续校验 / host:port 提示分支 / cluster 回退
  (core 5、redis-stream 5、rocketmq 5,全绿)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 14:06:05 +08:00
parent 0c6d37842e
commit 886c02ff96
6 changed files with 91 additions and 5 deletions

View File

@@ -3,6 +3,7 @@ package com.njcn.mq.driver.rocketmq;
import com.njcn.mq.autoconfig.MqStartupChecks;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
@@ -31,7 +32,10 @@ public class RocketMqStartupProbeAutoConfiguration implements InitializingBean {
if (!MqStartupChecks.enabled(env)) {
return;
}
String nameServer = env.getProperty("rocketmq.name-server");
// 与 driver 同源取值driver 走 RocketMQProperties(@ConfigurationProperties)的 getNameServer()
// 享受 Spring relaxed binding这里也用 Binder避免 env.getProperty 精确键查找漏掉
// camelCase(rocketmq.nameServer)等 relaxed 变体,从而把「其实配好了」误判成「未配置」而错误 fail-fast。
String nameServer = Binder.get(env).bind("rocketmq.name-server", String.class).orElse(null);
if (!StringUtils.hasText(nameServer)) {
throw new IllegalStateException(
"MQ 启动失败mq.type=rocketmq但未配置 rocketmq.name-server。"

View File

@@ -25,6 +25,19 @@ class RocketMqStartupProbeAutoConfigurationTest {
}
}
@Test
void reachableNameServer_camelCaseKey_startsUp() throws Exception {
// driver 通过 RocketMQProperties 走 relaxed bindingcamelCase 的 rocketmq.nameServer 也能生效;
// 探测取值必须与之同源,否则会把配好的 NameServer 误判为未配置而错误 fail-fast。
try (ServerSocket server = new ServerSocket(0)) {
int port = server.getLocalPort();
runner.withPropertyValues(
"mq.type=rocketmq",
"rocketmq.nameServer=127.0.0.1:" + port)
.run(ctx -> assertThat(ctx).hasNotFailed());
}
}
@Test
void unreachableNameServer_startupFails() {
runner.withPropertyValues(