mirror of
https://github.com/rustfs/rustfs.git
synced 2026-01-17 01:30:33 +00:00
347 lines
9.4 KiB
Plaintext
347 lines
9.4 KiB
Plaintext
# RustFS 项目 Cursor 规则
|
||
|
||
## 项目概述
|
||
RustFS 是一个用 Rust 编写的高性能分布式对象存储系统,兼容 S3 API。项目采用模块化架构,支持纠删码存储、多租户管理、可观测性等企业级功能。
|
||
|
||
## 核心架构原则
|
||
|
||
### 1. 模块化设计
|
||
- 项目采用 Cargo workspace 结构,包含多个独立的 crate
|
||
- 核心模块:`rustfs`(主服务)、`ecstore`(纠删码存储)、`common`(共享组件)
|
||
- 功能模块:`iam`(身份管理)、`madmin`(管理接口)、`crypto`(加密)等
|
||
- 工具模块:`cli`(命令行工具)、`crates/*`(工具库)
|
||
|
||
### 2. 异步编程模式
|
||
- 全面使用 `tokio` 异步运行时
|
||
- 优先使用 `async/await` 语法
|
||
- 使用 `async-trait` 处理 trait 中的异步方法
|
||
- 避免阻塞操作,必要时使用 `spawn_blocking`
|
||
|
||
### 3. 错误处理策略
|
||
- 使用统一的错误类型 `common::error::Error`
|
||
- 支持错误链和上下文信息
|
||
- 使用 `thiserror` 定义具体错误类型
|
||
- 错误转换使用 `downcast_ref` 进行类型检查
|
||
|
||
## 代码风格规范
|
||
|
||
### 1. 格式化配置
|
||
```toml
|
||
max_width = 130
|
||
fn_call_width = 90
|
||
single_line_let_else_max_width = 100
|
||
```
|
||
|
||
### 2. 命名约定
|
||
- 使用 `snake_case` 命名函数、变量、模块
|
||
- 使用 `PascalCase` 命名类型、trait、枚举
|
||
- 常量使用 `SCREAMING_SNAKE_CASE`
|
||
- 全局变量前缀 `GLOBAL_`,如 `GLOBAL_Endpoints`
|
||
|
||
### 3. 文档注释
|
||
- 公共 API 必须有文档注释
|
||
- 使用 `///` 进行文档注释
|
||
- 复杂函数添加 `# Examples` 和 `# Parameters` 说明
|
||
- 错误情况使用 `# Errors` 说明
|
||
|
||
### 4. 导入规范
|
||
- 标准库导入在最前面
|
||
- 第三方 crate 导入在中间
|
||
- 本项目内部导入在最后
|
||
- 使用 `use` 语句分组,组间空行分隔
|
||
|
||
## 异步编程规范
|
||
|
||
### 1. Trait 定义
|
||
```rust
|
||
#[async_trait::async_trait]
|
||
pub trait StorageAPI: Send + Sync {
|
||
async fn get_object(&self, bucket: &str, object: &str) -> Result<ObjectInfo>;
|
||
}
|
||
```
|
||
|
||
### 2. 错误处理
|
||
```rust
|
||
// 使用 ? 操作符传播错误
|
||
async fn example_function() -> Result<()> {
|
||
let data = read_file("path").await?;
|
||
process_data(data).await?;
|
||
Ok(())
|
||
}
|
||
```
|
||
|
||
### 3. 并发控制
|
||
- 使用 `Arc` 和 `Mutex`/`RwLock` 进行共享状态管理
|
||
- 优先使用 `tokio::sync` 中的异步锁
|
||
- 避免长时间持有锁
|
||
|
||
## 日志和追踪规范
|
||
|
||
### 1. Tracing 使用
|
||
```rust
|
||
#[tracing::instrument(skip(self, data))]
|
||
async fn process_data(&self, data: &[u8]) -> Result<()> {
|
||
info!("Processing {} bytes", data.len());
|
||
// 实现逻辑
|
||
}
|
||
```
|
||
|
||
### 2. 日志级别
|
||
- `error!`: 系统错误,需要立即关注
|
||
- `warn!`: 警告信息,可能影响功能
|
||
- `info!`: 重要的业务信息
|
||
- `debug!`: 调试信息,开发时使用
|
||
- `trace!`: 详细的执行路径
|
||
|
||
### 3. 结构化日志
|
||
```rust
|
||
info!(
|
||
counter.rustfs_api_requests_total = 1_u64,
|
||
key_request_method = %request.method(),
|
||
key_request_uri_path = %request.uri().path(),
|
||
"API request processed"
|
||
);
|
||
```
|
||
|
||
## 错误处理规范
|
||
|
||
### 1. 错误类型定义
|
||
```rust
|
||
#[derive(Debug, thiserror::Error)]
|
||
pub enum MyError {
|
||
#[error("IO error: {0}")]
|
||
Io(#[from] std::io::Error),
|
||
#[error("Custom error: {message}")]
|
||
Custom { message: String },
|
||
}
|
||
```
|
||
|
||
### 2. 错误转换
|
||
```rust
|
||
pub fn to_s3_error(err: Error) -> S3Error {
|
||
if let Some(storage_err) = err.downcast_ref::<StorageError>() {
|
||
match storage_err {
|
||
StorageError::ObjectNotFound(bucket, object) => {
|
||
s3_error!(NoSuchKey, "{}/{}", bucket, object)
|
||
}
|
||
// 其他错误类型...
|
||
}
|
||
}
|
||
// 默认错误处理
|
||
}
|
||
```
|
||
|
||
### 3. 错误上下文
|
||
```rust
|
||
// 添加错误上下文
|
||
.map_err(|e| Error::from_string(format!("Failed to process {}: {}", path, e)))?
|
||
```
|
||
|
||
## 性能优化规范
|
||
|
||
### 1. 内存管理
|
||
- 使用 `Bytes` 而不是 `Vec<u8>` 进行零拷贝操作
|
||
- 避免不必要的克隆,使用引用传递
|
||
- 大对象使用 `Arc` 共享
|
||
|
||
### 2. 并发优化
|
||
```rust
|
||
// 使用 join_all 进行并发操作
|
||
let futures = disks.iter().map(|disk| disk.operation());
|
||
let results = join_all(futures).await;
|
||
```
|
||
|
||
### 3. 缓存策略
|
||
- 使用 `lazy_static` 或 `OnceCell` 进行全局缓存
|
||
- 实现 LRU 缓存避免内存泄漏
|
||
|
||
## 测试规范
|
||
|
||
### 1. 单元测试
|
||
```rust
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
use test_case::test_case;
|
||
|
||
#[tokio::test]
|
||
async fn test_async_function() {
|
||
let result = async_function().await;
|
||
assert!(result.is_ok());
|
||
}
|
||
|
||
#[test_case("input1", "expected1")]
|
||
#[test_case("input2", "expected2")]
|
||
fn test_with_cases(input: &str, expected: &str) {
|
||
assert_eq!(function(input), expected);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 集成测试
|
||
- 使用 `e2e_test` 模块进行端到端测试
|
||
- 模拟真实的存储环境
|
||
|
||
## 安全规范
|
||
|
||
### 1. 内存安全
|
||
- 禁用 `unsafe` 代码(workspace.lints.rust.unsafe_code = "deny")
|
||
- 使用 `rustls` 而不是 `openssl`
|
||
|
||
### 2. 认证授权
|
||
```rust
|
||
// 使用 IAM 系统进行权限检查
|
||
let identity = iam.authenticate(&access_key, &secret_key).await?;
|
||
iam.authorize(&identity, &action, &resource).await?;
|
||
```
|
||
|
||
## 配置管理规范
|
||
|
||
### 1. 环境变量
|
||
- 使用 `RUSTFS_` 前缀
|
||
- 支持配置文件和环境变量两种方式
|
||
- 提供合理的默认值
|
||
|
||
### 2. 配置结构
|
||
```rust
|
||
#[derive(Debug, Deserialize, Clone)]
|
||
pub struct Config {
|
||
pub address: String,
|
||
pub volumes: String,
|
||
#[serde(default)]
|
||
pub console_enable: bool,
|
||
}
|
||
```
|
||
|
||
## 依赖管理规范
|
||
|
||
### 1. Workspace 依赖
|
||
- 在 workspace 级别统一管理版本
|
||
- 使用 `workspace = true` 继承配置
|
||
|
||
### 2. 功能特性
|
||
```rust
|
||
[features]
|
||
default = ["file"]
|
||
gpu = ["dep:nvml-wrapper"]
|
||
kafka = ["dep:rdkafka"]
|
||
```
|
||
|
||
## 部署和运维规范
|
||
|
||
### 1. 容器化
|
||
- 提供 Dockerfile 和 docker-compose 配置
|
||
- 支持多阶段构建优化镜像大小
|
||
|
||
### 2. 可观测性
|
||
- 集成 OpenTelemetry 进行分布式追踪
|
||
- 支持 Prometheus 指标收集
|
||
- 提供 Grafana 仪表板
|
||
|
||
### 3. 健康检查
|
||
```rust
|
||
// 实现健康检查端点
|
||
async fn health_check() -> Result<HealthStatus> {
|
||
// 检查各个组件状态
|
||
}
|
||
```
|
||
|
||
## 代码审查清单
|
||
|
||
### 1. 功能性
|
||
- [ ] 是否正确处理所有错误情况
|
||
- [ ] 是否有适当的日志记录
|
||
- [ ] 是否有必要的测试覆盖
|
||
|
||
### 2. 性能
|
||
- [ ] 是否避免了不必要的内存分配
|
||
- [ ] 是否正确使用了异步操作
|
||
- [ ] 是否有潜在的死锁风险
|
||
|
||
### 3. 安全性
|
||
- [ ] 是否正确验证输入参数
|
||
- [ ] 是否有适当的权限检查
|
||
- [ ] 是否避免了信息泄露
|
||
|
||
### 4. 可维护性
|
||
- [ ] 代码是否清晰易懂
|
||
- [ ] 是否遵循项目的架构模式
|
||
- [ ] 是否有适当的文档
|
||
|
||
### 5. 代码提交
|
||
- [ ] 是否符合[代码提交规范](https://www.conventionalcommits.org/en/v1.0.0/)
|
||
- [ ] 提交的标题要精简,以英文为主,不要使用中文
|
||
|
||
## 常用模式和最佳实践
|
||
|
||
### 1. 资源管理
|
||
```rust
|
||
// 使用 RAII 模式管理资源
|
||
pub struct ResourceGuard {
|
||
resource: Resource,
|
||
}
|
||
|
||
impl Drop for ResourceGuard {
|
||
fn drop(&mut self) {
|
||
// 清理资源
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 配置注入
|
||
```rust
|
||
// 使用依赖注入模式
|
||
pub struct Service {
|
||
config: Arc<Config>,
|
||
storage: Arc<dyn StorageAPI>,
|
||
}
|
||
```
|
||
|
||
### 3. 优雅关闭
|
||
```rust
|
||
// 实现优雅关闭
|
||
async fn shutdown_gracefully(shutdown_rx: &mut Receiver<()>) {
|
||
tokio::select! {
|
||
_ = shutdown_rx.recv() => {
|
||
info!("Received shutdown signal");
|
||
// 执行清理操作
|
||
}
|
||
_ = tokio::time::sleep(SHUTDOWN_TIMEOUT) => {
|
||
warn!("Shutdown timeout reached");
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 特定领域规范
|
||
|
||
### 1. 存储操作
|
||
- 所有存储操作必须支持纠删码
|
||
- 实现读写仲裁机制
|
||
- 支持数据完整性校验
|
||
|
||
### 2. 网络通信
|
||
- 使用 gRPC 进行内部服务通信
|
||
- HTTP/HTTPS 支持 S3 兼容 API
|
||
- 实现连接池和重试机制
|
||
|
||
### 3. 元数据管理
|
||
- 使用 FlatBuffers 进行序列化
|
||
- 支持版本控制和迁移
|
||
- 实现元数据缓存
|
||
|
||
这些规则应该作为开发 RustFS 项目时的指导原则,确保代码质量、性能和可维护性。
|
||
|
||
### 4. 代码操作
|
||
- 每次开始前先查看.cursorrules文件,确保你了解项目规范
|
||
- 每次开始一个变更或者需求的开发,先 git checkout 到 main 分支,然后 git pull 拉取最新代码
|
||
- 每次确定要开发的功能或者做的变更,先创建一个分支,然后 git checkout 到这个分支
|
||
- 每次变更前,请切记仔细阅读现有代码,确保你了解代码的结构和实现,不要破坏已有的逻辑实现,不要引入新的问题
|
||
- 每次的变更确保提供足够的测试用例,确保代码的正确性
|
||
- 测试用例里的数字和常量不要随意修改,请谨慎分析它的含义,确保测试用例的正确性
|
||
- 每次编写或者修改测试的时候,请检查已有的测试用例,检查它是否科学的命名和谨慎的逻辑测试,如果不符合,请修改测试用例,确保测试用例的科学性和严谨性
|
||
- 每次开发完成后,先 git add . 然后 git commit -m "feat: 功能描述" 或者 "fix: 问题描述",确保符合[代码提交规范](https://www.conventionalcommits.org/en/v1.0.0/)
|
||
- 每次开发完成后,先 git push 到远程仓库
|
||
- 每次改动完成,先总结变更内容,不要创建总结文件,提供一个简短的变更描述,确保符合[代码提交规范](https://www.conventionalcommits.org/en/v1.0.0/)
|
||
- 在对话里提供 PR 时需要的变更描述,确保符合[代码提交规范](https://www.conventionalcommits.org/en/v1.0.0/)
|