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.
 

8.1 KiB

Timeline Service 技术栈规范符合性修订

日期: 2026-01-29
类型: 文档修订
影响范围: docs/requirements/backend/04-services/project/timeline-service.md


修订概述

timeline-service.md 文档进行全面修订,确保完全符合 jointo-tech-stack 技术栈规范。


修订内容

1. 添加日志系统

问题: 原文档代码示例完全没有使用日志

修订:

  • TimelineService 类中添加模块级 logger
  • 所有关键操作添加日志记录(INFO 级别)
  • 所有异常添加错误日志(ERROR 级别 + exc_info=True
  • 使用中文日志消息
  • 使用 %-formatting 格式化

示例:

import logging

logger = logging.getLogger(__name__)

logger.info(
    "获取时间轴数据 | 用户: %s | 项目: %s | 轨道类型: %s",
    user_id,
    project_id,
    track_types or "全部"
)

logger.error(
    "获取时间轴数据失败 | 项目: %s | 错误: %s",
    project_id,
    str(e),
    exc_info=True
)

2. 完善异常处理

问题: 异常处理不完整,没有日志记录

修订:

  • 所有 Service 方法添加 try-except 块
  • 异常日志使用 exc_info=True 记录堆栈
  • 区分业务异常和系统异常
  • 业务异常直接 raise,系统异常记录后 raise

3. 添加数据库设计章节

问题: 缺少 Model 层和数据库设计说明

修订:

  • 添加完整的 Storyboard Model 定义
  • 使用 TIMESTAMPTZ 时间戳(ADR 006)
  • 应用层生成 UUID v7(generate_uuid()
  • 配置 Relationship(无物理外键,使用 primaryjoin
  • 添加数据库迁移 SQL 示例
  • 添加表级和列级注释

4. 引用完整性验证

问题: reorder_storyboards 没有验证分镜是否存在

修订:

  • 添加 batch_exists() 批量验证
  • 使用事务 async with self.db.begin() 确保原子性
  • 验证失败时抛出 NotFoundError

示例:

# 验证所有分镜是否存在
storyboard_ids = [UUID(sid) for sid in reorder_data.storyboard_orders.keys()]
storyboards_exist = await self.storyboard_repo.batch_exists(storyboard_ids)

missing_ids = [
    str(sid) for sid, exists in storyboards_exist.items() if not exists
]
if missing_ids:
    raise NotFoundError(f"分镜不存在: {missing_ids}")

# 使用事务批量更新
async with self.db.begin():
    for storyboard_id, new_order in reorder_data.storyboard_orders.items():
        await self.storyboard_repo.update(...)

5. 统一 API 响应格式

问题: API 接口直接返回数据对象

修订:

  • 所有 API 使用 ApiResponse 统一格式(RFC-135)
  • 添加完整的 API 实现代码
  • 添加 API 日志记录
  • 响应示例使用 UUID v7 格式

示例:

return ApiResponse.success_response(
    data=timeline_data,
    message="时间轴数据获取成功"
)

6. 时间戳规范

问题: 没有明确时间戳字段类型

修订:

  • Model 层使用 datetime.now(timezone.utc)
  • 数据库使用 TIMESTAMPTZ(ADR 006 强制规范)
  • 添加时区说明注释

7. UUID v7 生成说明

问题: 没有说明 UUID 如何生成

修订:

  • 明确应用层生成(generate_uuid()
  • 禁止数据库默认值(server_default
  • 添加代码示例

8. Relationship 配置说明

问题: 使用了关联但没有说明如何配置

修订:

  • 添加完整的 Relationship 配置示例
  • 使用 primaryjoinforeign_keys(因为无物理外键)
  • 添加 TYPE_CHECKING 导入

9. 性能优化增强

问题: 缓存示例可能暗示使用 loguru

修订:

  • 缓存方法添加日志记录(使用标准库 logging
  • 添加批量操作优化示例
  • 添加异常处理

10. 技术栈约束章节

新增:

  • 添加"技术栈约束"章节
  • 列出 7 条核心规范
  • 更新数据流图说明

技术栈符合度检查

符合项

  1. 异步编程: 所有方法使用 async/await
  2. 日志系统: 使用标准库 logging,禁止 loguru
  3. UUID v7: 应用层生成,禁止数据库默认值
  4. 无物理外键: 应用层验证引用完整性
  5. 时间戳: 使用 TIMESTAMPTZ(ADR 006)
  6. 统一响应: 所有 API 使用 ApiResponse 格式
  7. 事务处理: 批量操作使用 async with self.session.begin()
  8. 仓储模式: 正确使用 Repository 层
  9. 依赖注入: Service 层正确注入 Repository
  10. Schema 定义: 使用 Pydantic BaseModel
  11. 软删除: 使用 deleted_at 字段
  12. 索引: 所有关联字段创建索引

文档结构优化

新增章节

  1. 技术栈约束: 列出核心规范
  2. 数据库设计: Model 定义和迁移脚本
  3. 性能优化: 缓存、分页、批量操作

更新章节

  1. 服务实现: 添加完整日志和异常处理
  2. API 接口: 添加完整 API 实现代码
  3. Schema 定义: 添加示例和说明
  4. 相关文档: 添加 ADR、RFC 链接

代码示例改进

日志记录

修订前:

# 没有日志
has_permission = await self.project_repo.check_user_permission(...)

修订后:

logger.info(
    "获取时间轴数据 | 用户: %s | 项目: %s",
    user_id,
    project_id
)

has_permission = await self.project_repo.check_user_permission(...)

if not has_permission:
    logger.warning("权限不足 | 用户: %s | 项目: %s", user_id, project_id)
    raise PermissionError("没有权限访问此项目")

引用完整性验证

修订前:

# 直接更新,没有验证
for storyboard_id, new_order in reorder_data.storyboard_orders.items():
    await self.storyboard_repo.update(...)

修订后:

# 批量验证
storyboard_ids = [UUID(sid) for sid in reorder_data.storyboard_orders.keys()]
storyboards_exist = await self.storyboard_repo.batch_exists(storyboard_ids)

missing_ids = [str(sid) for sid, exists in storyboards_exist.items() if not exists]
if missing_ids:
    raise NotFoundError(f"分镜不存在: {missing_ids}")

# 使用事务
async with self.db.begin():
    for storyboard_id, new_order in reorder_data.storyboard_orders.items():
        await self.storyboard_repo.update(...)

API 响应格式

修订前:

return timeline_data  # 直接返回数据

修订后:

return ApiResponse.success_response(
    data=timeline_data,
    message="时间轴数据获取成功"
)

影响范围

文档

  • docs/requirements/backend/04-services/project/timeline-service.md

代码实现

  • ⚠️ 需要根据修订后的文档实现 TimelineService
  • ⚠️ 需要实现 StoryboardRepository.batch_exists()
  • ⚠️ 需要实现 API 路由(app/api/v1/timeline.py

后续工作

1. 实现 TimelineService

# 创建服务文件
touch server/app/services/timeline_service.py

# 实现完整的 TimelineService 类
# 包含日志、异常处理、引用完整性验证

2. 实现 Repository 方法

# 在 StoryboardRepository 中添加
# - batch_exists()
# - get_by_project() with pagination

3. 实现 API 路由

# 创建 API 文件
touch server/app/api/v1/timeline.py

# 实现 4 个 API 端点
# - GET /projects/{project_id}/timeline
# - POST /projects/{project_id}/timeline/reorder
# - GET /projects/{project_id}/timeline/tracks/{track_type}
# - GET /projects/{project_id}/timeline/items/time-range

4. 编写测试

# 单元测试
touch server/tests/unit/test_timeline_service.py

# 集成测试
touch server/tests/integration/test_timeline_api.py

相关文档


修订人: Kiro AI
审核状态: 已完成
文档版本: v3.0