HaniBlindBox/.kiro/specs/api-infrastructure/design.md
2026-01-02 15:46:56 +08:00

241 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design Document
## Overview
本设计文档描述 HoneyBox 抽奖系统 .NET 8 Web API 项目基础架构的技术实现方案。采用四层架构设计,使用 Autofac 进行依赖注入Mapster 进行对象映射Serilog 进行日志记录Redis 进行分布式缓存。
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ HoneyBox.Api │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Controllers │ │ Filters │ │ Middlewares │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────┐
│ HoneyBox.Core │ │ HoneyBox.Model │
│ ┌─────────────────┐ │ │ ┌─────────────────────┐ │
│ │ Services │ │ │ │ Entities │ │
│ ├─────────────────┤ │ │ ├─────────────────────┤ │
│ │ Interfaces │ │ │ │ Models │ │
│ ├─────────────────┤ │ │ ├─────────────────────┤ │
│ │ Mappings │ │ │ │ Data │ │
│ └─────────────────┘ │ │ ├─────────────────────┤ │
└─────────────────────────┘ │ │ Base │ │
│ │ └─────────────────────┘ │
▼ └─────────────────────────────┘
┌─────────────────────────┐
│ HoneyBox.Infrastructure │
│ ┌─────────────────┐ │
│ │ Cache │ │
│ ├─────────────────┤ │
│ │ External │ │
│ ├─────────────────┤ │
│ │ Modules │ │
│ └─────────────────┘ │
└─────────────────────────┘
```
### 依赖关系
```
Api → Core, Model
Core → Model, Infrastructure
Infrastructure → 无依赖
Model → 无依赖
```
## Components and Interfaces
### HoneyBox.Model 组件
#### ApiResponse 基类
```csharp
// Base/ApiResponse.cs
public class ApiResponse
{
public int Code { get; set; }
public string Msg { get; set; } = string.Empty;
public static ApiResponse Success(string msg = "success");
public static ApiResponse Fail(string msg, int code = -1);
}
public class ApiResponse<T> : ApiResponse
{
public T? Data { get; set; }
public static ApiResponse<T> Success(T data, string msg = "success");
public new static ApiResponse<T> Fail(string msg, int code = -1);
}
```
#### HoneyBoxDbContext
```csharp
// Data/HoneyBoxDbContext.cs
public partial class HoneyBoxDbContext : DbContext
{
public HoneyBoxDbContext(DbContextOptions<HoneyBoxDbContext> options);
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Goods> Goods { get; set; }
public virtual DbSet<Order> Orders { get; set; }
// ... 其他 DbSet
}
```
### HoneyBox.Infrastructure 组件
#### ICacheService 接口
```csharp
// Cache/ICacheService.cs
public interface ICacheService
{
Task<T?> GetAsync<T>(string key);
Task SetAsync<T>(string key, T value, TimeSpan? expiry = null);
Task RemoveAsync(string key);
Task<bool> ExistsAsync(string key);
Task<bool> IsConnectedAsync();
}
```
#### RedisCacheService 实现
```csharp
// Cache/RedisCacheService.cs
public class RedisCacheService : ICacheService
{
private readonly IDatabase _database;
private readonly ConnectionMultiplexer _connection;
public RedisCacheService(IConfiguration configuration);
public Task<T?> GetAsync<T>(string key);
public Task SetAsync<T>(string key, T value, TimeSpan? expiry = null);
public Task RemoveAsync(string key);
public Task<bool> ExistsAsync(string key);
public Task<bool> IsConnectedAsync();
}
```
#### Autofac 模块
```csharp
// Modules/ServiceModule.cs
public class ServiceModule : Module
{
protected override void Load(ContainerBuilder builder);
}
// Modules/InfrastructureModule.cs
public class InfrastructureModule : Module
{
protected override void Load(ContainerBuilder builder);
}
```
### HoneyBox.Core 组件
#### MappingConfig
```csharp
// Mappings/MappingConfig.cs
public static class MappingConfig
{
public static void Configure();
}
```
### HoneyBox.Api 组件
#### GlobalExceptionFilter
```csharp
// Filters/GlobalExceptionFilter.cs
public class GlobalExceptionFilter : IExceptionFilter
{
public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger);
public void OnException(ExceptionContext context);
}
```
#### HealthController
```csharp
// Controllers/HealthController.cs
[ApiController]
[Route("api/[controller]")]
public class HealthController : ControllerBase
{
public HealthController(HoneyBoxDbContext dbContext, ICacheService cacheService);
[HttpGet]
public Task<ApiResponse<HealthCheckData>> GetHealth();
}
```
## Data Models
### 健康检查响应模型
```csharp
public class HealthCheckData
{
public string Status { get; set; } = string.Empty;
public string Database { get; set; } = string.Empty;
public string Redis { get; set; } = string.Empty;
public DateTime Timestamp { get; set; }
}
```
### 统一响应格式
所有 API 接口返回格式:
```json
{
"code": 0,
"msg": "success",
"data": { ... }
}
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
由于本阶段主要是基础架构搭建,大部分验收标准是结构性检查(文件是否存在、配置是否正确),属于示例测试而非属性测试。以下是可以进行属性测试的场景:
### Property 1: ApiResponse 格式一致性
*For any* API 响应,返回的 JSON 结构 SHALL 始终包含 code、msg 字段,当有数据时包含 data 字段
**Validates: Requirements 6.4**
### Property 2: 缓存读写一致性
*For any* 缓存键值对,写入后立即读取 SHALL 返回相同的值
**Validates: Requirements 3.5**
## Error Handling
### 全局异常处理策略
1. 所有未捕获异常由 GlobalExceptionFilter 统一处理
2. 异常信息记录到日志Serilog
3. 返回统一格式的错误响应:`{ "code": 500, "msg": "服务器内部错误" }`
4. 开发环境可返回详细错误信息,生产环境隐藏敏感信息
### 连接失败处理
1. 数据库连接失败:健康检查返回 Database: "Disconnected"
2. Redis 连接失败:健康检查返回 Redis: "Disconnected",但不影响应用启动
## Testing Strategy
### 验证方式
由于本阶段是基础架构搭建,主要通过以下方式验证:
1. **编译验证**`dotnet build` 确保项目能正常编译
2. **运行验证**:启动应用,访问 Swagger 文档
3. **健康检查验证**:调用 `/api/health` 接口验证数据库和 Redis 连接
4. **日志验证**:检查控制台和日志文件输出
### 手动测试清单
- [ ] 解决方案能正常编译
- [ ] 应用能正常启动
- [ ] Swagger 文档可访问 (http://localhost:5000/swagger)
- [ ] 健康检查接口返回正确格式
- [ ] 日志输出到控制台
- [ ] 日志输出到文件 (logs/log-*.txt)