@@ -177,6 +177,227 @@ private validateUserData(userData: CreateUserDto | UpdateUserDto): void {
}
```
## 🚨 异常处理完整性检查(关键规范)
### 问题定义
**异常吞没( Exception Swallowing) ** 是指在 catch 块中捕获异常后,只记录日志但不重新抛出,导致:
- 调用方无法感知错误
- 方法返回 undefined 而非声明的类型
- 数据不一致或静默失败
- 难以调试和定位问题
### 检查规则
#### 规则1: catch 块必须有明确的异常处理策略
``` typescript
// ❌ 严重错误: catch 块吞没异常
async create ( createDto : CreateDto ) : Promise < ResponseDto > {
try {
const result = await this . repository . create ( createDto ) ;
return this . toResponseDto ( result ) ;
} catch ( error ) {
this . logger . error ( '创建失败' , error ) ;
// 错误:没有 throw, 方法返回 undefined
// 但声明返回 Promise<ResponseDto>
}
}
// ❌ 错误:只记录日志不处理
async findById ( id : string ) : Promise < Entity > {
try {
return await this . repository . findById ( id ) ;
} catch ( error ) {
monitor . error ( error ) ;
// 错误:异常被吞没,调用方无法感知
}
}
// ✅ 正确:重新抛出异常
async create ( createDto : CreateDto ) : Promise < ResponseDto > {
try {
const result = await this . repository . create ( createDto ) ;
return this . toResponseDto ( result ) ;
} catch ( error ) {
this . logger . error ( '创建失败' , error ) ;
throw error ; // 必须重新抛出
}
}
// ✅ 正确:转换为特定异常类型
async create ( createDto : CreateDto ) : Promise < ResponseDto > {
try {
const result = await this . repository . create ( createDto ) ;
return this . toResponseDto ( result ) ;
} catch ( error ) {
this . logger . error ( '创建失败' , error ) ;
if ( error . message . includes ( 'duplicate' ) ) {
throw new ConflictException ( '记录已存在' ) ;
}
throw error ; // 其他错误继续抛出
}
}
// ✅ 正确: 返回错误响应( 仅限顶层API)
async create ( createDto : CreateDto ) : Promise < ApiResponse < ResponseDto > > {
try {
const result = await this . repository . create ( createDto ) ;
return { success : true , data : this.toResponseDto ( result ) } ;
} catch ( error ) {
this . logger . error ( '创建失败' , error ) ;
return {
success : false ,
error : error.message ,
errorCode : 'CREATE_FAILED'
} ; // 顶层API可以返回错误响应
}
}
```
#### 规则2: Service 层方法必须传播异常
``` typescript
// ❌ 错误: Service 层吞没异常
@Injectable ( )
export class UserService {
async update ( id : string , dto : UpdateDto ) : Promise < ResponseDto > {
try {
const result = await this . repository . update ( id , dto ) ;
return this . toResponseDto ( result ) ;
} catch ( error ) {
this . logger . error ( '更新失败' , { id , error } ) ;
// 错误: Service 层不应吞没异常
}
}
}
// ✅ 正确: Service 层传播异常
@Injectable ( )
export class UserService {
async update ( id : string , dto : UpdateDto ) : Promise < ResponseDto > {
try {
const result = await this . repository . update ( id , dto ) ;
return this . toResponseDto ( result ) ;
} catch ( error ) {
this . logger . error ( '更新失败' , { id , error } ) ;
throw error ; // 传播给调用方处理
}
}
}
```
#### 规则3: Repository 层必须传播数据库异常
``` typescript
// ❌ 错误: Repository 层吞没数据库异常
@Injectable ( )
export class UserRepository {
async findById ( id : bigint ) : Promise < User | null > {
try {
return await this . repository . findOne ( { where : { id } } ) ;
} catch ( error ) {
this . logger . error ( '查询失败' , { id , error } ) ;
// 错误:数据库异常被吞没,调用方以为查询成功但返回 null
}
}
}
// ✅ 正确: Repository 层传播异常
@Injectable ( )
export class UserRepository {
async findById ( id : bigint ) : Promise < User | null > {
try {
return await this . repository . findOne ( { where : { id } } ) ;
} catch ( error ) {
this . logger . error ( '查询失败' , { id , error } ) ;
throw error ; // 数据库异常必须传播
}
}
}
```
### 异常处理层级规范
| 层级 | 异常处理策略 | 说明 |
|------|-------------|------|
| **Repository 层 ** | 必须 throw | 数据访问异常必须传播 |
| **Service 层 ** | 必须 throw | 业务异常必须传播给调用方 |
| **Business 层 ** | 必须 throw | 业务逻辑异常必须传播 |
| **Gateway/Controller 层 ** | 可以转换为 HTTP 响应 | 顶层可以将异常转换为错误响应 |
### 检查清单
- [ ] **所有 catch 块是否有 throw 语句? **
- [ ] **方法返回类型与实际返回是否一致? ** (避免返回 undefined)
- [ ] **Service/Repository 层是否传播异常? **
- [ ] **只有顶层 API 才能将异常转换为错误响应? **
- [ ] **异常日志是否包含足够的上下文信息? **
### 快速检查命令
``` bash
# 搜索可能吞没异常的 catch 块(没有 throw 的 catch)
# 在代码审查时重点关注这些位置
grep -rn "catch.*error" --include= "*.ts" | grep -v "throw"
```
### 常见错误模式
#### 模式1: 性能监控后忘记抛出
``` typescript
// ❌ 常见错误
} catch ( error ) {
monitor . error ( error ) ; // 只记录监控
// 忘记 throw error;
}
// ✅ 正确
} catch ( error ) {
monitor . error ( error ) ;
throw error ; // 必须抛出
}
```
#### 模式2: 条件分支遗漏 throw
``` typescript
// ❌ 常见错误
} catch ( error ) {
if ( error . code === 'DUPLICATE' ) {
throw new ConflictException ( '已存在' ) ;
}
// else 分支忘记 throw
this . logger . error ( error ) ;
}
// ✅ 正确
} catch ( error ) {
if ( error . code === 'DUPLICATE' ) {
throw new ConflictException ( '已存在' ) ;
}
this . logger . error ( error ) ;
throw error ; // else 分支也要抛出
}
```
#### 模式3: 返回类型不匹配
``` typescript
// ❌ 错误:声明返回 Promise<Entity> 但可能返回 undefined
async findById ( id : string ) : Promise < Entity > {
try {
return await this . repo . findById ( id ) ;
} catch ( error ) {
this . logger . error ( error ) ;
// 没有 throw, TypeScript 不会报错但运行时返回 undefined
}
}
// ✅ 正确
async findById ( id : string ) : Promise < Entity > {
try {
return await this . repo . findById ( id ) ;
} catch ( error ) {
this . logger . error ( error ) ;
throw error ;
}
}
```
## 🚫 TODO项处理( 强制要求)
### 处理原则
@@ -323,12 +544,19 @@ describe('AdminService Properties', () => {
- 抽象为可复用的工具方法
- 消除代码重复
6. **处理所有TODO项 **
6. * * 🚨 检查异常处理完整性(关键步骤) **
- 扫描所有 catch 块
- 检查是否有 throw 语句
- 验证 Service/Repository 层是否传播异常
- 确认方法返回类型与实际返回一致
- 识别异常吞没模式并修复
7. **处理所有TODO项 **
- 搜索所有TODO注释
- 要求真正实现功能或删除代码
- 确保最终文件无TODO项
7 . **游戏服务器特殊检查 **
8 . **游戏服务器特殊检查 **
- WebSocket连接管理完整性
- 双模式服务行为一致性
- 属性测试实现质量