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.
5.6 KiB
5.6 KiB
Project Repository 事务管理架构修复
日期: 2026-02-04
类型: 架构重构 + Bug 修复
影响范围: Repository 层、测试框架
问题背景
项目 Repository 层存在严重的架构设计问题:
- Repository 层错误地管理事务 - 所有方法都调用
await session.commit() - 测试无法通过 - 与 conftest.py 的事务回滚机制冲突
- 违反单一职责原则 - Repository 应该只负责数据访问,不应该管理事务
错误示例
# ❌ 错误:Repository 不应该 commit
async def create(self, project: Project) -> Project:
self.session.add(project)
await self.session.commit() # 错误!
await self.session.refresh(project)
return project
解决方案
1. Repository 层重构
将所有 commit() 改为 flush(),移除 refresh():
# ✅ 正确:Repository 只负责数据访问
async def create(self, project: Project) -> Project:
self.session.add(project)
await self.session.flush() # 仅 flush,不 commit
return project
修改的方法:
create()- 创建项目update()- 更新项目move_to_trash()- 移至回收站restore_from_trash()- 从回收站恢复permanent_delete()- 永久删除add_member()- 添加成员remove_member()- 移除成员update_member_role()- 更新成员角色create_share()- 创建分享delete_share()- 删除分享move_to_folder()- 移动到文件夹
2. 测试重构
旧测试问题:
- 使用
sample_projectfixture 在测试事务内创建数据 - 导致
cannot use Connection.transaction() in a manually started transaction错误
新测试模式(参考文件夹服务):
async def test_create_project(self, db_session):
"""测试创建项目"""
repo = ProjectRepository(db_session)
# 直接在测试中创建数据,不使用 fixture
project = Project(
name="新项目",
type=ProjectType.MINE,
owner_type="user",
owner_id=UUID("00000000-0000-0000-0000-000000000001"),
status=ProjectStatus.ACTIVE
)
created = await repo.create(project)
assert created.id is not None
assert created.name == "新项目"
测试结果
✅ 14/14 测试全部通过
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_create_project PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_get_by_id PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_get_by_id_not_found PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_update_project PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_move_to_trash PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_restore_from_trash PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_permanent_delete PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_get_by_user PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_exists_by_name PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_add_member PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_remove_member PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_create_share PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_get_share_by_token PASSED
tests/unit/repositories/test_project_repository.py::TestProjectRepository::test_delete_share PASSED
架构原则
Repository 层职责
✅ 应该做:
- 数据访问逻辑(CRUD)
- 查询构建
- 数据转换
- 使用
flush()确保数据可见性
❌ 不应该做:
- 调用
commit()管理事务 - 调用
refresh()刷新对象(调用方负责) - 业务逻辑判断
Service 层职责
✅ 应该做:
- 事务管理(
commit()/rollback()) - 业务逻辑编排
- 调用多个 Repository
- 异常处理
测试最佳实践
✅ 应该做:
- 在测试方法内直接创建测试数据
- 使用
db_sessionfixture(由 conftest 管理事务) - 依赖 conftest 的自动回滚机制
❌ 不应该做:
- 在 fixture 中创建需要 flush/commit 的数据
- 在测试中手动 commit
- 破坏 conftest 的事务管理
影响范围
需要更新的代码
- Service 层 - 需要添加
await session.commit() - API 层 - 确保在请求结束时提交事务
- 其他 Repository - 检查是否有类似问题
示例:Service 层事务管理
class ProjectService:
async def create_project(self, data: ProjectCreate) -> Project:
try:
project = Project(**data.dict())
created = await self.repo.create(project)
# Service 层负责提交事务
await self.session.commit()
return created
except Exception as e:
await self.session.rollback()
raise
后续任务
- 检查其他 Repository 是否有类似问题
- 更新 Service 层添加事务管理
- 创建 ADR 文档记录架构决策
- 更新开发文档说明 Repository/Service 职责划分
参考
- 文件夹服务测试:
tests/unit/repositories/test_folder_share_repository.py - conftest 事务管理:
server/tests/conftest.py - Repository 模式最佳实践:Martin Fowler - Patterns of Enterprise Application Architecture