--- status: accepted --- # 转商机的事务一致性前提:OpportunityCreationPort 首个实现须与 crm-lead 同库同事务 线索「转商机」在同一本地事务里完成四步:调 `OpportunityCreationPort#createOpportunity` 建商机、`UPDATE lead SET status='已转商机'`(带状态 CAS)、写 CONVERT history、冻结 N/M。商机模块**尚不存在**,crm-lead 只定义出站端口。我们**显式约定:`OpportunityCreationPort` 的首个实现必须与 crm-lead 共享同一数据库本地事务**,从而「本地事务性回滚、线索状态不变」这句一致性保证才成立。这是一个隐含假设,必须白纸黑字记下,否则将来商机模块独立部署时无人记得这里踩过坑。 ## Considered Options - **现在就设计跨服务最终一致 + 补偿**(先本地 CAS 改态 → 再调端口建商机 → 靠 `UNIQUE(source_lead_id)` 幂等 + 对账收敛)——被否为过度设计:商机模块连影子都没有,近期大概率同库单体。 - **同库同事务 + 显式前提约束(选中)**:近期最简单且正确;把「同库」这个前提写成端口契约约束,作为将来重新设计的触发条件。 ## Consequences - `OpportunityCreationPort` 的实现方(未来的商机模块)在同库阶段必须参与 crm-lead 的事务,不得吞异常。 - **触发重新设计的条件**:一旦商机模块改为独立库/独立部署,§6.5 的事务语义必须改为最终一致 + 补偿(`UNIQUE(source_lead_id)` 幂等 + 失败置中间态由重试/对账收敛)。届时应新开 ADR supersede 本条。 - 决策来源:`.scratch/clue-module/线索业务-PRD.md` §6.5 + ticket 08(2026-08-13 grill #10)。