| 文件 | 重构前 | 重构后 | 减少 |
|---|---|---|---|
directory_permissions.rs |
~900 行 | ~220 行 | -75% |
| 公开方法数量 | 8 个 | 2 个 | -75% |
// ❌ 臃肿的 API
pub fn new(work_dir: PathBuf) -> Self
pub fn basic_permission_fix(&self) -> Result<()>
pub fn progressive_permission_management(&self) -> Result<()>
pub fn fix_mysql_permissions_on_failure(&self) -> Result<()>
pub async fn post_container_start_maintenance(&self) -> Result<()>
pub fn check_and_fix_mysql_config_permissions(&self) -> Result<()>
pub async fn post_mysql_start_permission_check(&self) -> Result<()>
// ... 还有很多私有方法// ✅ 简洁的 API
pub fn new(work_dir: PathBuf) -> Self
pub fn ensure_directories_and_config(&self) -> Result<()> // 启动前调用
pub fn fix_mysql_permissions_on_failure(&self) -> Result<()> // 失败时调用原因:
- 调用处全部被注释掉
- 功能重复,与
ensure_directories_and_config()重叠 - 过度设计,实际不需要"渐进式"管理
原因:
- 调用处全部被注释掉
- 容器启动后不需要额外的权限维护
- Docker init 容器已经处理了所有权问题
原因:
- 功能合并到
ensure_directories_and_config()中 - 不需要单独的公开方法
原因:
- 从未被调用
- 启动后检查权限没有意义(应该在启动前确保正确)
原因:
- 功能与
ensure_directories_and_config()重复 - "回退方案"的设计过度复杂
// ❌ 删除的辅助方法
fn set_basic_permissions()
fn handle_mysql_config_permissions()
fn set_docker_base_permissions()
fn prepare_mysql_directory()
fn is_safe_to_clean_mysql_dir()
fn is_likely_user_data()
fn is_mysql_init_file()
fn safe_cleanup_mysql_init_files()
fn is_safe_init_directory()
fn fix_existing_mysql_permissions()
fn ensure_mysql_directories()
fn set_wsl2_permission() // 从未被调用
fn is_wsl2_windows_mount() // 从未被使用
// ... 还有更多原因:
- 过度设计,试图处理所有可能的边缘情况
- 实际上 Docker init 容器已经处理了大部分问题
- 增加了维护成本,但没有实际价值
- 职责不清:Rust 代码试图处理所有权限问题
- 过度设计:大量"以防万一"的代码
- 重复逻辑:多个方法做类似的事情
- 未使用代码:大量被注释掉的调用
-
职责分离:
- Rust:创建目录 + 设置配置文件权限(644)
- Docker init 容器:修改数据目录所有权(chown 999:999)
-
最小化:只保留真正需要的功能
-
简单明确:
- 启动前:
ensure_directories_and_config() - 失败时:
fix_mysql_permissions_on_failure()
- 启动前:
// ❌ 复杂的调用链
if let Err(e) = self
.directory_permission_manager
.progressive_permission_management()
{
warn!("渐进式权限管理失败,回退到基础权限: {}", e);
if let Err(fallback_err) = self.directory_permission_manager.basic_permission_fix() {
error!("权限设置完全失败: {}", fallback_err);
return Err(fallback_err);
}
}
// ... 启动容器 ...
if let Err(e) = self
.directory_permission_manager
.post_container_start_maintenance()
.await
{
warn!("容器启动后权限维护失败: {}", e);
}// ✅ 简单直接
self.directory_permission_manager
.ensure_directories_and_config()?;
// ... 启动容器 ...
// 失败时才调用修复
if mysql_failed {
self.directory_permission_manager
.fix_mysql_permissions_on_failure()?;
}职责:
- 创建所有必要目录
- 设置 MySQL 配置文件为 644 权限
调用时机:启动容器前
职责:
- 确保目录存在
- 设置最宽松权限(777)
- 确保配置文件权限正确(644)
调用时机:MySQL 启动失败时
mysql-permission-fix:
command: |
chown -R 999:999 /var/lib/mysql /var/log/mysql
chmod -R 755 /var/lib/mysql /var/log/mysql这是最可靠的方式,因为:
- 以 root 身份运行,保证成功
- 在容器内执行,跨平台兼容
- 集成在 docker-compose 中,自动化
MySQL 配置文件:
- 容器只需读取,不需要写入
- 保持当前用户所有权即可
- 只需确保权限是 644(不是 group-writable)
在 WSL2/网络文件系统上:
chmod可能失败,但只记录警告- Docker 有自己的权限映射机制
- 只要
chown成功(由 init 容器保证),容器就能运行
# 应该成功
cargo run -- docker-service start# 模拟权限问题
chmod 000 data/mysql/
# 应该触发修复逻辑
cargo run -- docker-service start# 设置错误权限
chmod 777 config/mysql.cnf
# 应该自动修复为 644
cargo run -- docker-service start
# 验证
ls -la config/mysql.cnf # 应该是 -rw-r--r--| 指标 | 重构前 | 重构后 | 改进 |
|---|---|---|---|
| 代码行数 | ~900 | ~220 | -75% |
| 公开方法 | 8 | 2 | -75% |
| 私有方法 | ~20 | ~4 | -80% |
| 复杂度 | 高 | 低 | 显著降低 |
| 可维护性 | 差 | 好 | 显著提升 |
| 测试覆盖 | 困难 | 容易 | 显著改善 |
核心理念:
- 不要试图在 Rust 代码中解决所有权限问题
- 依赖 Docker init 容器处理 chown(最可靠)
- Rust 只做必要的事:创建目录 + 设置配置文件权限
- 失败时提供简单的修复逻辑
这样的设计:
- ✅ 更简单
- ✅ 更可靠
- ✅ 更易维护
- ✅ 更易测试