# Project Repository 事务管理架构修复 **日期**: 2026-02-04 **类型**: 架构重构 + Bug 修复 **影响范围**: Repository 层、测试框架 ## 问题背景 项目 Repository 层存在严重的架构设计问题: 1. **Repository 层错误地管理事务** - 所有方法都调用 `await session.commit()` 2. **测试无法通过** - 与 conftest.py 的事务回滚机制冲突 3. **违反单一职责原则** - Repository 应该只负责数据访问,不应该管理事务 ### 错误示例 ```python # ❌ 错误: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()`: ```python # ✅ 正确: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_project` fixture 在测试事务内创建数据 - 导致 `cannot use Connection.transaction() in a manually started transaction` 错误 **新测试模式**(参考文件夹服务): ```python 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_session` fixture(由 conftest 管理事务) - 依赖 conftest 的自动回滚机制 ❌ **不应该做**: - 在 fixture 中创建需要 flush/commit 的数据 - 在测试中手动 commit - 破坏 conftest 的事务管理 ## 影响范围 ### 需要更新的代码 1. **Service 层** - 需要添加 `await session.commit()` 2. **API 层** - 确保在请求结束时提交事务 3. **其他 Repository** - 检查是否有类似问题 ### 示例:Service 层事务管理 ```python 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