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.
42 lines
4.3 KiB
42 lines
4.3 KiB
|
2 weeks ago
|
---
|
||
|
|
status: accepted
|
||
|
|
---
|
||
|
|
|
||
|
|
# 跨模块批量编排执行器:BatchRunner(收拢两份同构 runBatch 的统一协议)
|
||
|
|
|
||
|
|
## Context
|
||
|
|
|
||
|
|
ADR-0023 定下批量操作范式(非原子、逐条委派 self 代理、部分成功、`BatchResult` 骨架 + 各域自持失败项),但「逐条委派 + 失败翻译收集 + 结果组装」的编排皮留下两份同构实现:
|
||
|
|
|
||
|
|
1. crm-lead `LeadServiceImpl.runBatch`(私有 19 行,8 个批量方法一行委派它)。
|
||
|
|
2. crm-rule `LeadPoolServiceImpl.deletePoolBatch`(同一 try-catch 结构内联展开 19 行,差异仅失败项类型与 log 文案)。
|
||
|
|
|
||
|
|
后果:改兜底行为 / catch 结构要人肉排查两个模块——P1-6 类缺陷(规则两处实现漂移)的诞生结构;ADR-0023 D5 预言「此模式作为后续任何模块批量接口的范式」,但没有执行器载体,后续域(商机)只能再抄第三份。
|
||
|
|
|
||
|
|
## Considered Options
|
||
|
|
|
||
|
|
(grilling 2026-08-20,五问五钉)
|
||
|
|
|
||
|
|
- **范围与落位**:crm-base 泛型执行器 + 两侧接线(选中)/`com.crm.lead.batch` 只收 lead 侧(一个调用方 = 假 seam;crm-rule 因依赖方向收不进来,跨模块重复留着)/再加 lead 门面包(为收而收)。事实修正:Controller 侧无编排逻辑(纯透传);批量不直接调 CAS 守卫(守卫在单条方法与状态机内),收的是编排皮。
|
||
|
|
- **interface 形态**:静态 final 工具类 `run(ids, op, bizFail, unknownFail)` 四参数(选中——两个 ServiceImpl 构造器零变化、现有测试模式原样保留)/@Component bean(零依赖无状态,interface 是假 seam;两侧构造器各 +1 参数、测试构造全要动)/BatchAction record(op 每调用点必变,打包零复利)。
|
||
|
|
- **测试分工**:两侧现有测试一行不动(静态执行器真实穿过,自动升级为端到端锁)+ 新建 `BatchRunnerTest` 锁泛型协议(选中)/删两侧编排用例只留 BatchRunnerTest(被测对象没换家——删的是映射真值 + 端到端锁,净亏)。不套用候选 ② P1-6 平移先例。
|
||
|
|
- **命名落位**:`BatchRunner` @ `com.crm.base.domain.result`(与 BatchResult 同包的协议家族,选中)/utils 包(成员皆无协议语义的通用工具,BatchRunner 吃 `BusinessErrorException` 吐 `BatchResult`,是协议件不是工具件)。
|
||
|
|
- **交付切分**:单步一票(选中——改动面小于 LeadDeadlines 先例;建了不接线 = dead code 入库,无有意义的中间态)。
|
||
|
|
|
||
|
|
## Decision
|
||
|
|
|
||
|
|
crm-base `domain.result.BatchRunner`:静态 `run(ids, op, bizFail, unknownFail)`——空判短路 → 逐条委派 → 业务异常经 `bizFail(id, e)` 翻译收集 → 未知异常 log + `unknownFail(id, e)` 兜底且不中断后续 → 组装 `BatchResult<F>`。
|
||
|
|
|
||
|
|
- **翻译工厂落各域失败项类**:`LeadBatchFailItem.bizOf/unknownOf`(兜底文案「操作失败」)、`PoolBatchFailItem.bizOf/unknownOf`(「删除失败」)——code→reason 映射与兜底文案由域自持,ADR-0023 D5 原样成立。
|
||
|
|
- **失败项类型 F 经函数参数注入**,BatchRunner 无业务枚举依赖——ADR-0023 D2「crm-base 非业务纯净」原样成立。
|
||
|
|
- **self-injection 留守两侧 service**(AOP 每条独立事务,ADR-0023 D1 原样成立)。
|
||
|
|
- 8 个 lead 批量方法与 `deletePoolBatch` 全部一行委派;`runBatch` 私有方法与内联编排删除(replace 不 layer)。
|
||
|
|
|
||
|
|
## Consequences
|
||
|
|
|
||
|
|
- 编排协议唯一家:改兜底行为 / catch 结构只动 crm-base 一处;商机等后续域批量接口直接复用,第三份实现不会诞生。
|
||
|
|
- 两个 ServiceImpl **构造器零变化**(静态方法不注入)——`LeadBatchServiceTest`(7)/ `LeadPoolBatchDeleteTest`(4)/ `LeadPoolServiceImplTest` P0-1 一行不动,自动升级为「委派 + 真实执行器 + 域翻译工厂」的端到端锁。
|
||
|
|
- crm-base 测试 33 → 38 用例(+`BatchRunnerTest` 5:空判短路、全成功依序、bizFail 喂 (id, e)、unknownFail 兜底不中断、混合计数);crm-lead 116、crm-rule 30 不变。
|
||
|
|
- 唯一行为微调:执行器内 log 统一为「批量操作单条异常:id={}」(原 leadId= / poolId= 域内文案消失;log 非 HTTP 契约)。
|
||
|
|
- 决策来源:`/improve-codebase-architecture` 第三轮审查(2026-08-20,候选 ③)+ grilling 五问;实现票据见 `.scratch/batch-runner-module/spec.md`。
|