205 lines
6.6 KiB
Markdown
205 lines
6.6 KiB
Markdown
|
|
# lsfx Mock 规则命中模式切换设计
|
||
|
|
|
||
|
|
## 1. 背景
|
||
|
|
|
||
|
|
`lsfx-mock-server` 当前在生成流水命中计划时,默认按 `log_id` 稳定随机抽取规则子集。现需要在保持默认行为不变的前提下,支持通过启动命令切换到“全部兼容规则命中”模式,便于联调时一次性覆盖更多规则。
|
||
|
|
|
||
|
|
本次设计仅面向 Mock 服务,不涉及主 Java 工程、前端页面或真实规则引擎逻辑调整。
|
||
|
|
|
||
|
|
## 2. 目标与范围
|
||
|
|
|
||
|
|
### 2.1 目标
|
||
|
|
|
||
|
|
- 默认启动时继续使用现有“随机子集命中”逻辑
|
||
|
|
- 支持通过命令行参数切换命中模式
|
||
|
|
- 普通启动与热重载启动都支持命中模式切换
|
||
|
|
- 在“全部兼容规则命中”模式下,避免互斥规则同时出现
|
||
|
|
- 保持现有流水生成、命中计划持久化、基线补齐链路不变
|
||
|
|
|
||
|
|
### 2.2 非目标
|
||
|
|
|
||
|
|
- 不修改任意规则编码、样本构造规则、流水拼装顺序
|
||
|
|
- 不新增第三种命中模式
|
||
|
|
- 不兼容原生 `uvicorn main:app ...` 直接附带自定义业务参数的形式
|
||
|
|
- 不改前端、不改主系统后端接口
|
||
|
|
|
||
|
|
## 3. 术语定义
|
||
|
|
|
||
|
|
### 3.1 `subset`
|
||
|
|
|
||
|
|
默认模式。沿用当前逻辑,按 `log_id` 稳定随机抽取每类规则池中的部分规则,保证同一 `log_id` 结果稳定。
|
||
|
|
|
||
|
|
### 3.2 `all`
|
||
|
|
|
||
|
|
“全部兼容规则命中”模式。该模式不是字面意义上的“无条件命中全部规则”,而是:
|
||
|
|
|
||
|
|
- 优先命中当前已实现的全部可共存规则
|
||
|
|
- 若存在显式定义的互斥规则组,则每个互斥组仅保留一个固定代表规则
|
||
|
|
- 最终返回的命中计划必须稳定、可解释、可测试
|
||
|
|
|
||
|
|
对外文案统一使用“全部兼容规则命中”,避免误解为无约束全开。
|
||
|
|
|
||
|
|
## 4. 现状分析
|
||
|
|
|
||
|
|
当前规则命中计划由 `services/file_service.py` 中的 `_build_rule_hit_plan(log_id)` 负责生成:
|
||
|
|
|
||
|
|
- 使用 `random.Random(f"rule-plan:{log_id}")` 保证稳定性
|
||
|
|
- 分别为四类规则池抽取 2 到 4 条规则
|
||
|
|
- 生成结果写入 `FileRecord`
|
||
|
|
- 后续流水样本生成与第二期基线补齐均消费这份 `rule_plan`
|
||
|
|
|
||
|
|
当前启动入口 `main.py` 未解析业务命令行参数,配置由 `config/settings.py` 基于 `BaseSettings` 读取。
|
||
|
|
|
||
|
|
## 5. 设计方案
|
||
|
|
|
||
|
|
### 5.1 总体思路
|
||
|
|
|
||
|
|
将“规则命中模式”收敛为统一配置,由启动层负责解析命令行参数并注入配置,由规则计划编排层根据模式生成最终 `rule_plan`。
|
||
|
|
|
||
|
|
整体链路如下:
|
||
|
|
|
||
|
|
1. 启动命令读取 `--rule-hit-mode`
|
||
|
|
2. 启动层将模式值写入进程配置
|
||
|
|
3. `settings` 暴露统一的 `RULE_HIT_MODE`
|
||
|
|
4. `FileService` 根据模式生成规则命中计划
|
||
|
|
5. 后续流水生成、基线补齐继续复用该计划
|
||
|
|
|
||
|
|
这样只改变“命中计划如何生成”,不改变“命中计划如何被使用”。
|
||
|
|
|
||
|
|
### 5.2 配置设计
|
||
|
|
|
||
|
|
在 `config/settings.py` 中新增:
|
||
|
|
|
||
|
|
- `RULE_HIT_MODE: str = "subset"`
|
||
|
|
|
||
|
|
可选值仅允许:
|
||
|
|
|
||
|
|
- `subset`
|
||
|
|
- `all`
|
||
|
|
|
||
|
|
非法值在启动阶段直接报错并退出,不做自动兜底。
|
||
|
|
|
||
|
|
### 5.3 启动设计
|
||
|
|
|
||
|
|
保留两类启动方式:
|
||
|
|
|
||
|
|
#### 普通启动
|
||
|
|
|
||
|
|
```bash
|
||
|
|
python main.py --rule-hit-mode all
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 热重载启动
|
||
|
|
|
||
|
|
新增项目级启动脚本,例如:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
python dev.py --reload --rule-hit-mode all
|
||
|
|
```
|
||
|
|
|
||
|
|
设计上不再要求裸命令 `uvicorn main:app --reload ...` 直接支持业务参数。README 中将明确推荐项目脚本作为热重载入口。
|
||
|
|
|
||
|
|
### 5.4 规则计划编排设计
|
||
|
|
|
||
|
|
规则计划生成逻辑拆分为两层:
|
||
|
|
|
||
|
|
1. 基础规则池定义
|
||
|
|
2. 模式对应的计划编排
|
||
|
|
|
||
|
|
在 `subset` 模式下:
|
||
|
|
|
||
|
|
- 完全沿用当前按 `log_id` 稳定抽样逻辑
|
||
|
|
|
||
|
|
在 `all` 模式下:
|
||
|
|
|
||
|
|
- 默认取四类规则池当前已实现规则的全集
|
||
|
|
- 再应用显式互斥组裁剪
|
||
|
|
- 输出“全部兼容规则命中”计划
|
||
|
|
|
||
|
|
### 5.5 互斥规则处理
|
||
|
|
|
||
|
|
为避免“全部命中”时出现语义自相矛盾的测试数据,引入显式互斥组定义。
|
||
|
|
|
||
|
|
互斥组处理规则:
|
||
|
|
|
||
|
|
- 互斥关系必须通过常量显式维护,不允许散落在样本 builder 内隐式判断
|
||
|
|
- 每个互斥组按固定优先级保留一个代表规则
|
||
|
|
- 未被声明为互斥的规则,默认视为可共存
|
||
|
|
|
||
|
|
第一版实现中,若现有规则样本已能共存,则允许互斥组为空;但结构必须预留,确保后续新增互斥规则时不破坏 `all` 模式语义。
|
||
|
|
|
||
|
|
### 5.6 对现有样本的兼容判断
|
||
|
|
|
||
|
|
根据当前样本实现与测试约束:
|
||
|
|
|
||
|
|
- `SALARY_QUICK_TRANSFER` 与 `SALARY_UNUSED` 已通过不同主体拆分,可共存
|
||
|
|
- 大额交易、一期规则、二期流水规则目前主要通过不同对手方、不同时间或不同主体构造,未发现必须立即裁剪的硬冲突
|
||
|
|
- 二期基线规则可继续按命中计划幂等写入
|
||
|
|
|
||
|
|
因此,第一版预计“互斥组定义为空或极少数”,但仍要通过独立常量与测试明确这一口径。
|
||
|
|
|
||
|
|
## 6. 代码改动边界
|
||
|
|
|
||
|
|
本次设计预期改动集中在以下位置:
|
||
|
|
|
||
|
|
- `lsfx-mock-server/config/settings.py`
|
||
|
|
- `lsfx-mock-server/main.py`
|
||
|
|
- `lsfx-mock-server/services/file_service.py`
|
||
|
|
- `lsfx-mock-server/README.md`
|
||
|
|
- `lsfx-mock-server/tests/`
|
||
|
|
- 新增热重载启动脚本
|
||
|
|
|
||
|
|
不触碰规则样本库的大规模重构,不改接口协议。
|
||
|
|
|
||
|
|
## 7. 测试设计
|
||
|
|
|
||
|
|
### 7.1 单元测试
|
||
|
|
|
||
|
|
- `subset` 模式下同一 `log_id` 仍返回稳定子集
|
||
|
|
- `all` 模式下返回四类规则池的兼容全集
|
||
|
|
- 若存在互斥组,验证不会同时出现同组规则
|
||
|
|
- 启动参数仅允许 `subset|all`
|
||
|
|
|
||
|
|
### 7.2 集成测试
|
||
|
|
|
||
|
|
- 普通启动时可切换到 `all`
|
||
|
|
- 热重载入口可切换到 `all`
|
||
|
|
- `all` 模式生成的 `rule_plan` 会被正确写入 `FileRecord`
|
||
|
|
- 后续流水查询与第二期基线补齐继续消费同一份计划
|
||
|
|
|
||
|
|
### 7.3 回归重点
|
||
|
|
|
||
|
|
- 默认不传参数时行为不变
|
||
|
|
- 现有随机子集链路测试不回归
|
||
|
|
- 已有规则样本生成顺序与分页查询稳定性不回归
|
||
|
|
|
||
|
|
## 8. 风险与控制
|
||
|
|
|
||
|
|
### 8.1 风险
|
||
|
|
|
||
|
|
- “全部规则命中”表述容易被误解为无条件全开
|
||
|
|
- 热重载启动若继续依赖裸 `uvicorn main:app`,无法自然接入业务参数
|
||
|
|
- 后续新增规则若存在互斥关系,可能破坏 `all` 模式语义
|
||
|
|
|
||
|
|
### 8.2 控制措施
|
||
|
|
|
||
|
|
- 文档与 README 统一使用“全部兼容规则命中”
|
||
|
|
- 热重载统一走项目级启动脚本
|
||
|
|
- 互斥组通过显式常量维护,并由测试守护
|
||
|
|
|
||
|
|
## 9. 预期交付
|
||
|
|
|
||
|
|
- 设计文档 1 份
|
||
|
|
- 后续实施计划 2 份:
|
||
|
|
- 后端实施计划
|
||
|
|
- 前端实施计划(明确本次无需前端代码改动)
|
||
|
|
- Mock 服务代码、README 与测试更新
|
||
|
|
|
||
|
|
## 10. 验收标准
|
||
|
|
|
||
|
|
- 默认启动仍为随机子集命中
|
||
|
|
- 显式传入命令行参数后可切换至“全部兼容规则命中”
|
||
|
|
- 普通启动与热重载启动均可切换
|
||
|
|
- `all` 模式下不会同时出现已定义互斥规则
|
||
|
|
- 所有相关测试通过,且无残留测试进程
|