Numbering 已有纯算法、Store 基础、架构所有权和双 ORM 元数据测试,但真正高风险的并发、事务、补偿 claim、规则发布和生产消费尚未形成完整门禁。
1. 已有测试证据
| 测试族 | 当前覆盖 |
|---|---|
NumberingSequenceNumberStoreTests | 演示规则组装、从已有事实递增 |
BusinessSerialContextTests | 回调可选、MAX/Exists fake、接续算法示意 |
| 条件/分段单测 | selector 与 assembler 的多个纯逻辑场景 |
NumberingInfrastructureArchitectureTests | owner 路径、ORM 中立、Host 注册、seed/metadata |
PortRepositoryParityTests | 三张 owner 行在 SqlSugar/EF Core 的基础一致性 |
| AOT metadata tests | 字段长度与生成模型等价 |
部分 BusinessSerialContext 测试只模拟公式,没有调用真实 Store;不能当成端到端接续证明。
2. 最大测试缺口
必须补:100+ 并发唯一性、冲突后事务可用性、业务表冲突推进、补偿原子 claim、租户隔离、规则热变更、不同 provider 异常、回滚与空号策略。
3. 运行指标
至少暴露:
numbering_generate_total{table,field,result};- unique conflict/retry/exhausted 次数;
- rule-not-found/no-segments;
- 业务表 fallback/duplicate;
- compensation hit/miss/conflict;
- 每分区事实数与 MAX 查询耗时;
- 规则版本/资产 hash;
- 生成事实与业务表不一致数量。
标签不得包含完整流水号或敏感业务字段,避免高基数与隐私泄露。
4. 日志现状
实现记录完整 FullString、Table、Field、Prefix、Attempt。完整业务号可能携带分支/业务字段,应做分类和脱敏策略。
日志没有规则 Id、租户、条件命中、段版本或 structured provider error code,诊断规则漂移较困难。
5. 故障诊断
RuleNotFound:核对租户、TableName/Field、IsActive、IsEnabled、软删与默认条件优先级。
NoSegments:核对运行时计算 RuleId 与 Setting.RuleId、租户过滤、软删和 seed 710 是否执行。
ConcurrencyExhausted:检查唯一冲突日志、外层事务隔离、provider 异常、热点 prefix 和事实可见性。
BusinessTableConflict:检查事实表是否缺失业务历史;当前算法可能三次生成同一候选号。
6. 数据完整性巡检
定期报告:
- 同租户重复 Table/Field/RuleName;
- 同 Table/Field 多个空条件或优先级反转;
- 非法 Condition JSON/字段/操作符;
- 无设置、重复 Sort、未知 SectionType;
- 非法日期/Branch JSON;
- 非一个 SequenceNumber;
- Prefix/FullString 超长风险;
- 同 Prefix+SequenceNumber 多行;
- 未激活事实长期积压;
- 子号父引用缺失;
- 事实 MAX 低于业务表 MAX。
7. 安全边界
TableName/Field 只用于规则匹配;业务表访问必须通过 owner 回调,不得拼动态 SQL。EntityValues 仅传必要字段,避免日志/编号泄露敏感数据。
当前没有规则管理权限。直接数据库修改应被限制为受审计运维过程。
8. 发布前检查
- 在影子库执行两个 seed step并检查行数;
- lint 所有条件与段配置;
- 固定时钟验证日期/财年边界;
- 在两种 ORM 上运行相同规则集;
- 真实数据库做热点 prefix 并发压测;
- 验证事务内唯一冲突后的恢复;
- 演练事实表丢失后的业务 MAX 接续;
- 演练未激活号补偿竞争;
- 核对业务消费者 Feature gate;
- 准备规则回滚和事实修复 runbook。
9. 正确压测断言
// ① 并发发起同一租户/规则/前缀的分配。var results = await Task.WhenAll( Enumerable.Range(0, 200) .Select(_ => generator.GenerateAsync(request, cancellationToken)));
// ② 所有成功字符串必须唯一;失败必须是已知类型化错误。var successful = results.Where(x => x.IsSuccess).Select(x => x.Value!).ToList();successful.Select(x => x.SequenceNumberStr).Distinct().Count() .ShouldBe(successful.Count);
// ③ 是否允许空号是产品策略,不能默认用连续性掩盖重试事实。测试必须使用真实数据库连接与独立 scope,内存 EntitySet 不能复现唯一约束竞态。
10. P0 GA 项
- 原子水位/compare-and-swap 端口,避免全分区 List+MAX;
- provider 结构化唯一异常翻译;
- 补偿原子 claim 与业务表判重;
- 规则/分段严格 validator;
- StartValue 真正生效或删除字段;
- 默认规则/重复 Sort/段数量数据库与发布约束;
- 真实生产消费者 tracer bullet;
- Feature 在统一入口强制。
11. P1 GA 项
- 规则版本、草稿、审批、预览和定时发布;
- 幂等请求键与业务聚合关联;
- 事实/业务写原子性或明确 saga;
- 迁移水位导入与对账;
- 监控、告警、修复 CLI 与 runbook;
- RuleId/父号引用完整性;
- 配置化时区与财年起始月;
- 性能容量与归档策略。
详细任务会同步进入 Architecture-Hub Numbering GA backlog。
12. 当前上线判断
两个演示规则和低并发内部场景可以作为技术验证。未经过真实数据库并发、生产业务消费、规则治理和恢复演练前,不应对外宣称“并发安全商业序列服务”。
13. 测试命令
# 纯算法/Store 单元测试。dotnet test tests/BitzOrcas.Unit.Tests --filter FullyQualifiedName~Numbering
# 所有权和编译期元数据。dotnet test tests/BitzOrcas.Architecture.Tests --filter FullyQualifiedName~NumberingInfrastructureArchitectureTests
# 双 ORM owner 行 parity。dotnet test tests/BitzOrcas.Integration.Tests --filter FullyQualifiedName~NumberingOwnerRows_Should_Behave_The_Same14. 全局扫描
# 尚未落地的原子/治理能力;预期当前 Numbering 无实质命中。rg -n "CompareAndSwap|AtomicIncrement|IdempotencyKey|RuleVersion|Approval" src/Platform/Numbering -g '*.cs'
# 遗留技术债:财年配置化。rg -n "TODO" src/Framework/BitzOrcas.Application/Numbering src/Platform/Numbering -g '*.cs'