领域驱动设计中聚合、事务与并发:项目成员约束失效求解
聚合根事务边界问题探讨(TypeORM + PostgreSQL Serializable隔离级别)
场景背景
基于TypeORM与PostgreSQL,采用Serializable隔离级别(注:此隔离级别与TypeORM事务管理机制相关)。
业务规则:
Project作为聚合根,可包含任意数量的Member- 每个
Member拥有角色,一个项目最多只能有3个Admin角色的成员
Project 类代码示例:
class Project { private readonly members: Member[] = []; addMember(userId: string, role: string) { // 若角色为Admin,校验当前Admin数量(此处代码仅示意逻辑) this.members.push(new Member(userId, role)); } }
为确保不变量约束,所有成员需一次性加载至内存后操作(假设成员数量较少)。
并发冲突问题
当项目已有2个Admin成员时,两名用户同时执行以下操作:
执行流程1
const project = projectRepository.getById(projectId); project.addMember({ userId: "xxx", role: "Admin" }); projectRepository.save(project);
执行流程2
const project = projectRepository.getById(projectId); project.addMember({ userId: "yyy", role: "Admin" }); projectRepository.save(project);
两个流程通过TypeORM生成的事务均为:
BEGIN; INSERT INTO members (user_id, role) values ('zzz', 'ADMIN'); COMMIT;
最终两个事务都执行成功,导致项目出现4个Admin成员,破坏了最多3个Admin的不变量约束。
现有解决方案思路
方案1 - 自定义事务:删除重插所有成员
每次保存项目时,先删除该项目的所有成员记录,再重新插入全部成员。此方案可在分布式环境下保护不变量约束。
对应的事务SQL:
BEGIN; DELETE FROM members WHERE project_id = 'aaa'; -- 插入所有成员的语句 COMMIT;
方案2 - 调整聚合边界
若方案1不合理,当前的聚合边界无法提供有效事务约束。可考虑将 Member 设为独立聚合根,每次添加成员时直接校验该项目的Admin数量是否超过3,必要时配合分布式锁使用。
疑问
我是否遗漏了其他更合理的解决方案?期待各位的见解!
注:已尝试多种基于TypeORM的事务处理方式,此问题兼具实践与理论探讨价值。
内容的提问来源于stack exchange,提问作者Ricardo Ferraris
相关产品推荐
相关产品推荐

