You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.1 KiB
7.1 KiB
SMS 服务文档技术栈合规性修正
日期: 2026-01-29
类型: 文档更新
影响范围: docs/requirements/backend/04-services/user/sms-service.md
变更概述
修正短信验证码服务文档,使其完全符合 jointo-tech-stack 规范,包括异步编程、依赖注入、错误处理、日志记录和测试规范。
主要变更
1. 修正导入和类型错误
问题: 缺少 timezone 导入,导致 datetime.now(timezone.utc) 无法使用
修正:
from datetime import datetime, timedelta, timezone # 添加 timezone
from app.core.logging import logger # 添加日志记录
2. 优化依赖注入
问题: Service 层直接创建 Redis 和 HTTP 客户端,违反依赖注入原则
修正前:
def __init__(self, session: AsyncSession):
self.redis_client = Redis.from_url(settings.REDIS_URL)
self.http_client = httpx.AsyncClient(timeout=10.0)
修正后:
def __init__(self, session: AsyncSession, redis_client: Redis):
self.redis_client = redis_client # 由依赖注入提供
self._http_client: Optional[httpx.AsyncClient] = None # 懒加载
@property
def http_client(self) -> httpx.AsyncClient:
"""懒加载 HTTP 客户端"""
if self._http_client is None:
self._http_client = httpx.AsyncClient(timeout=10.0)
return self._http_client
3. 添加资源管理
问题: 缺少异步上下文管理器,资源清理不规范
修正:
async def __aenter__(self):
"""异步上下文管理器入口"""
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
"""异步上下文管理器退出,清理资源"""
if self._http_client is not None:
await self._http_client.aclose()
4. 增强错误处理和日志
Service 层:
async def send_verification_code(...) -> dict:
try:
# 业务逻辑
logger.info("验证码已发送", extra={...})
return result
except (RateLimitError, ValidationError):
raise
except Exception as e:
logger.error(f"发送验证码失败: {str(e)}", exc_info=True)
raise ValidationError("发送验证码失败,请稍后重试")
Repository 层:
async def create(self, code: SmsVerificationCode) -> SmsVerificationCode:
try:
self.session.add(code)
await self.session.commit()
await self.session.refresh(code)
return code
except SQLAlchemyError as e:
await self.session.rollback()
logger.error(f"创建验证码失败: {str(e)}", exc_info=True)
raise DatabaseError("创建验证码失败")
5. 完善 Schema 层
问题: 缺少 ConfigDict 配置和字段验证
修正:
class SmsCodeSendRequest(BaseModel):
model_config = ConfigDict(populate_by_name=True)
phone: str = Field(..., min_length=11, max_length=11, description="手机号")
country_code: str = Field(default="+86", alias="countryCode", description="国家代码")
purpose: SmsPurposeEnum = Field(default=SmsPurposeEnum.LOGIN, description="用途")
@field_validator("phone")
@classmethod
def validate_phone(cls, v: str) -> str:
if not v.isdigit():
raise ValueError("手机号必须为纯数字")
return v
6. 补充 API 路由层
新增内容:
- 完整的 FastAPI 路由实现
- 依赖注入配置(
get_session、get_redis_client) - 统一的
ApiResponse响应格式 - 完整的 API 文档注释
@router.post(
"/sms/send",
response_model=ApiResponse[SmsCodeSendResponse],
summary="发送短信验证码"
)
async def send_sms_code(
request: Request,
body: SmsCodeSendRequest,
session: AsyncSession = Depends(get_session),
redis_client = Depends(get_redis_client)
):
service = SmsService(session, redis_client)
# ...
return ApiResponse.success(data=result)
7. 添加测试规范
新增章节:
- 单元测试示例(
test_sms_service.py) - 集成测试示例(
test_sms_api.py) - 测试运行命令
测试覆盖:
- ✅ 生成验证码
- ✅ 发送验证码成功
- ✅ IP 限流
- ✅ 手机号限流
- ✅ 验证验证码成功
- ✅ 验证码错误
- ✅ 验证码过期
- ✅ API 集成测试
8. 统一响应格式
修正前:
{
"code": 200,
"message": "Success",
"data": {...}
}
修正后:
{
"code": 200,
"message": "Success",
"data": {...},
"timestamp": "2026-01-29T10:30:00Z"
}
技术栈合规性检查
✅ 已符合规范
- 异步编程(
async/await、AsyncSession、asyncpg) - UUID v7 主键(
generate_uuid) - 枚举类型(
IntEnum+SMALLINT) - 仓储模式(Service/Repository 分层)
- 时间戳字段(
TIMESTAMPTZ+timezone.utc) - 索引设计(单列、组合、条件索引)
- 无物理外键
- Redis 异步客户端
- HTTP 异步客户端
✅ 新增合规项
- 依赖注入(Redis 客户端由 FastAPI 提供)
- 资源管理(异步上下文管理器)
- 错误处理(
try-except+ 异常转换) - 日志记录(结构化日志 +
extra字段) - Schema 配置(
ConfigDict+populate_by_name) - 字段验证(
@field_validator) - API 路由层(完整实现)
- 统一响应格式(
ApiResponse+timestamp) - 测试规范(单元测试 + 集成测试)
文档结构优化
新增章节
- API 路由层实现 - 完整的 FastAPI 路由代码
- 依赖注入配置 -
get_session和get_redis_client - 测试规范 - 单元测试和集成测试示例
优化章节
- 服务实现 - 添加文档字符串、错误处理、日志记录
- Schema 层 - 添加
ConfigDict和字段验证 - Repository 层 - 添加异常处理和事务回滚
- API 接口 - 添加响应示例和
timestamp字段
影响评估
文档变更
- 文档版本: v2.0 → v3.0
- 最后更新: 2026-01-26 → 2026-01-29
- 新增内容: ~200 行代码示例和测试用例
代码影响
- 无破坏性变更: 文档修正不影响现有代码
- 建议同步: 实际代码应参考文档进行相应优化
后续建议
1. 代码实现同步
建议按照文档规范更新实际代码:
- 优化依赖注入
- 添加结构化日志
- 完善错误处理
- 补充单元测试
2. 性能优化
- 考虑使用 Redis Pipeline 批量操作
- 添加验证码发送成功率监控
- 优化数据库查询索引
3. 安全增强
- 添加验证码尝试次数限制
- 实现验证码加密存储
- 添加异常 IP 黑名单机制
相关文档
变更作者: Kiro AI
审核状态: 待审核
文档版本: v1.0