M-REDIS-04 真实 Redis Cluster 负向发布门禁 Delta¶
日期:2026-08-23 状态:已实现并经真实 Docker Cluster 验证
变更摘要¶
新增一条不依赖常规集成环境的发布负向门禁:启动三个 cluster-enabled Redis 节点,使用
官方镜像内的 redis-cli --cluster create 建立无副本 Cluster,确认其完整覆盖 16384 slots,
再从宿主机 loopback 暴露的真实节点调用生产
qim_common::redis_runtime::assert_redis_runtime_safe。即使进程环境设置
QIM_REDIS_ALLOW_UNSAFE_DEV=1,结果也必须是 ClusterNotStandalone。
影响文件与职责¶
| 文件 | 职责 |
|---|---|
compose.redis-cluster-negative.yml |
只定义三个 Cluster 节点、独立网络、三个项目专属卷,以及 Docker 自动分配的 loopback 端口。 |
scripts/integration/redis-cluster-negative.sh |
验证依赖,生成唯一项目,建集群、验收拓扑、运行 ignored Rust 测试并精确清理本项目。 |
crates/qim-common/tests/redis_cluster_rejection.rs |
经真实 TCP 连接调用生产安全断言,并证明开发放宽开关不覆盖 Cluster 拒绝。 |
接口与集成点¶
没有生产 API、Redis store 或常规集成脚本的接口变化。脚本仅向单次 Cargo 进程传递:
QIM_TEST_REDIS_CLUSTER_ADDR=127.0.0.1:<Docker 自动分配端口>
QIM_REDIS_ALLOW_UNSAFE_DEV=1
测试本身要求两个变量存在且值正确;手工运行却漏变量时失败,不会跳过。
隔离与清理契约¶
项目名必须是唯一的 qim-redis-cluster-negative-*;启动前若同名项目的 container、network
或 volume 已存在则拒绝复用。主节点的宿主端口默认 0 由 Docker 分配,避免与 16379
及并行门禁冲突。清理只执行:
docker compose --project-name "$QIM_REDIS_CLUSTER_NEGATIVE_PROJECT" \
--file compose.redis-cluster-negative.yml down --volumes --remove-orphans
它不会调用系统范围 prune、不会按宽泛 label 删除,也不会触及常规集成 Compose 项目。
验证计划¶
| Must Have | 证据 |
|---|---|
| 三个真实 Cluster 节点 | 脚本等待每个节点 PONG,然后执行 redis-cli --cluster create。 |
| 集群已成形 | 轮询 cluster_state:ok、cluster_slots_assigned:16384 和三个 connected master。 |
| 开发开关仍拒绝 | Rust ignored 测试读取 QIM_REDIS_ALLOW_UNSAFE_DEV=1,再用 true 调用生产函数,并精确断言 ClusterNotStandalone。 |
| 依赖/收敛失败不可假绿 | 任何缺失或超时都经 fail 非零退出;测试没有 Option/early return skip。 |
| 清理只限本项目 | 同名残留拒绝复用;trap 仅对本 Compose project 执行 down --volumes。 |
本次应执行:
bash -n scripts/integration/redis-cluster-negative.sh
cargo test --locked -p qim-common --test redis_cluster_rejection --no-run
cargo clippy --locked -p qim-common --test redis_cluster_rejection -- -D warnings
scripts/integration/redis-cluster-negative.sh
验证结果(2026-08-23):四条命令均通过;最后一项创建了三个真实 Redis 7.4.1
master,redis-cli 确认 16384 slots 全覆盖,ignored 测试结果为 1 passed; 0 failed。
Docker 自动分配的测试端口为 127.0.0.1:1026;trap 随后销毁该唯一项目的资源。
风险与边界¶
本门禁只验证“当前发布运行时拒绝 Cluster”,不测试 Redis Cluster 的键槽行为,也不把 Cluster 作为受支持的 store 后端。Cluster 形成失败时不应尝试单节点替代;这正是该负向 测试需要捕获的环境失效。