Skip to content
bitzorcas
中EN

Guide

Search 测试、可观测性与 GA 门禁

从 Lucene 行为、消息字节、权限/数据泄漏、双 ORM、索引新鲜度、重建演练、多副本和利冲证据定义 Search 的生产验收。

Last updated

Search 最危险的失败通常不是 500,而是“查询成功但漏数据、越权、过期或错误判定无冲突”。GA 验收必须围绕结果可信度,而不是只验证 DI 能解析和 Handler 调过某个 Mock。

1. 当前证据边界

现有测试证明:

  • ListSegmentWords.Handler 委托给 ISegmentWordStore;
  • Catalog store 可用内存 EntitySet 读/更新一行;
  • Segment store 的串行 add/list/delete/cache 基本路径;
  • owner-local 行与生成式 metadata 存在;
  • Search Infrastructure 无具体 ORM 依赖;
  • API/JobHost 项目引用、API composition 和 provider manifest 存在;
  • Search ports 有 unavailable 默认和显式生产覆盖。

它们不证明:

  • Lucene 实际能按 TenantId 隔离并返回预期字段/排序;
  • 九条 endpoint 的授权和错误契约;
  • search.index.changed 字节可绑定、可重放或能写 Created/Updated;
  • StoredFields/Total 不泄漏未授权资源;
  • 利冲在索引延迟、规则变化和 provider 失败时不会给出错误“无冲突”;
  • 重建、多副本、损坏恢复和隐私擦除可执行。

2. 测试金字塔

规则与投影单测
输入、字段、决策

双 ORM Store 契约
唯一、排序、缓存

真实 Lucene provider
写/删/查/commit

消息字节契约
topic/schema/version

HTTP + 授权 + 数据范围

重建/损坏/多副本演练

利冲证据与隐私

GA 证据包

外部 Search 包也必须作为 consumer contract 被测;“包有单测”不能替代本平台对配置、字段 schema、租户和升级的保证。

3. 真实 Lucene 行为套件

使用每测试独立临时目录,并确保 finally 清理。至少覆盖:

  1. 同 DocumentId 在 Tenant A/B 的隔离;
  2. Upsert 后查询、更新覆盖、Delete 幂等;
  3. Name/Subject/Content 与中文、拼音、NGram;
  4. LegalSuffix/OrgWeak/GeoWeak 和停用词;
  5. Skip/Take、Total、确定排序和相同分值;
  6. StoredFields 类型/空值/超长/Unicode;
  7. delayed commit 前后可见性;
  8. 并发 writer/reader 与文件锁;
  9. 目录损坏、磁盘满、只读目录;
  10. package 升级前后索引兼容;
  11. cancellation/timeout;
  12. 重建切换期间持续查询。
租户隔离必须在真实 provider 中固定
[Fact]
public async Task SameDocumentId_InDifferentTenants_MustNeverCrossRead()
{
await using var fixture = await LuceneFixture.CreateIsolatedAsync();
// 两个租户使用相同业务 ID,内容刻意不同。
await fixture.Engine.UpsertAsync(Document("tenant-a", "case-42", "Alpha secret"));
await fixture.Engine.UpsertAsync(Document("tenant-b", "case-42", "Beta secret"));
await fixture.ForceCommitAsync();
// tenant-a 的查询不能返回 tenant-b 内容或 StoredFields。
var result = await fixture.SearchAsync("tenant-a", "Beta");
result.Hits.ShouldBeEmpty();
result.TotalHits.ShouldBe(0);
}

4. 消息契约与投影序列

测试必须从 owner 实际 outbox bytes 开始,而非手工 new consumer DTO。固定 topic、envelope、schema、枚举编码、SourceVersion 和缺失字段失败。

序列矩阵:

序列目标结果
Create v1文档 v1 可查询
Create v1, Create v1Duplicate,不重复
Update v2替换字段与 ACL
Delete v3不可查询并保留 tombstone
Delete v3, Update v2Stale,不复活
Update v5 after v2GapDetected,触发 repair
unknown action/schemaquarantine,不广播伪更新
provider transient failCAP 有界 retry

当前 Created/Updated no-op 和无 publisher 会让这些测试首先失败,这是有价值的真实红灯。

5. 授权与泄漏测试

  • .check/.search 和 .manage/.create/.update/.delete 精确 200/403;
  • Feature 禁用时拒绝;
  • unified 不能绕过 conflict 专用权限;
  • tenant filter 写入和查询双侧验证;
  • owner ACL/DataScope 撤权后旧 index token 不泄漏;
  • StoredFields allowlist/脱敏;
  • unauthorized hits 不通过 Total/hasMore/耗时泄漏;
  • global catalog/segment word 只对平台范围管理员开放;
  • 日志、trace 和 Problem Details 不回显 keyword/party/物理路径。

安全测试要用生产 authorization pipeline 和真实 Search schema,不要注入 always-allow authorizer。

6. 利冲验收

利冲测试既要检索准确性,也要流程证据:

  • exact name、former/foreign name、credit code;
  • 同名假阳性、简称、拼音、弱词与地理词;
  • party role/opposing role;
  • ExcludeCaseId 仅排除目标案件;
  • 多 party 同名不会覆盖;
  • 索引 watermark 过期时 fail closed/标记不可判定;
  • provider timeout 不能返回 HasConflict=false;
  • reviewer/override/blocked/cleared 状态;
  • 规则、analyzer、词库版本可复盘;
  • 输入/命中敏感信息的保留、导出、擦除。

建立经法务确认的 golden corpus,版本化预期匹配和误报/漏报容忍度。算法升级要跑差异报告,不只看总通过率。

7. 双 ORM Store 契约

对 SqlSugar/EF Core 跑同一套:

  1. catalog GetAll/Get/Update;
  2. unknown status 应 fail closed;
  3. LastRebuiltAt UTC/precision;
  4. missing catalog update 的显式结果;
  5. segment unique/case/collation/Unicode;
  6. 并发 Add 同词;
  7. Delete missing 幂等;
  8. List 稳定排序;
  9. 非法 SegmentType;
  10. 大词库加载性能与 cancellation。

当前内存测试不会触发数据库唯一约束、collation 或时间转换。

8. 可观测性

层次必要指标
producer/outboxpublished、pending、oldest age、schema version
CAP consumerapplied、duplicate、stale、gap、failed、DLQ
Lucene writerqueue、commit latency、lock、directory bytes、disk free
index partitiondocument count、source/index watermark、drift
queryQPS、p50/p95/p99、timeout、zero-hit、oversample/filter ratio
conflictchecks、potential matches、review outcome、false-positive sample
rebuildstate、processed/total、ETA、verify errors、cutover/rollback

日志键:TenantId(允许时 hash)、IndexKey、DocumentId(敏感场景可 hash)、EventId、SourceVersion、index version、result、duration、trace id。禁止完整 keyword、party、StoredFields。

9. SLO 与新鲜度

查询延迟 SLO 之外,还要有 freshness SLO,例如“已提交 owner change 在 60 秒内进入可查询版本”。响应或 status endpoint 提供:

  • index version;
  • source watermark / last applied occurred-at;
  • lag;
  • rebuilding/degraded;
  • result 是否经过 owner authorization;
  • 对利冲,规则/词库版本。

如果 freshness 超限,普通搜索可显式 degraded;利冲等高价值决策应返回“无法确认”而不是 false。

10. 事故处置

搜索持续返回 0

先区分真正无数据和索引未生产:检查 producer/outbox、consumer applied、Lucene document count、catalog/watermark。当前源码没有 producer且 Create/Update no-op,重启 API 不会补数据。

API 副本结果不一致

记录响应实例与 index version,检查每个 BasePath 和 volume。若事件只由一个 consumer 实例处理,本地目录必然分叉;停止把流量随机路由到不完整副本,再按选定拓扑重建。

Lucene 目录损坏/锁死

停止 writer,保留只读诊断副本,不直接删除唯一目录。用已验证 source 在 shadow path 重建,对账后切换。若无数据源,必须按数据丢失事故处理,不能声称索引“随时可重建”。

利冲疑似漏报

冻结关联接案决策,记录 index/rule/词库版本与 watermark,对 authoritative source 复核并扩大样本,修复 producer/rebuild 后重跑受影响时间窗,保留旧/新结果和人工处置。

11. GA 门禁

  • 业务 owner 生产契约和 byte tests 通过;
  • Created/Updated/Delete 全生命周期、版本/inbox/gap 完成;
  • 工作的 data source、shadow rebuild、对账、回滚演练通过;
  • 权限/Feature/IndexKey/命中级授权闭环;
  • StoredFields schema 与敏感字段策略生效;
  • 利冲有记录、人工复核、override、审计和 freshness fail-closed;
  • 真实 Lucene、双 ORM、九端点与多副本测试通过;
  • 绝对持久路径、容量、单 writer 和拓扑明确;
  • 指标、告警、SLO、Runbook 与 on-call owner 完整;
  • package alpha 升级有兼容矩阵和回滚;
  • 隐私擦除/撤权贯穿 active、shadow、backup;
  • 文档每个“支持”结论可指向源码/测试/运行证据。

按当前源码,Search 不能宣告数据索引与利冲 GA。Lucene provider 可注册是基础能力,不是生产闭环。

12. 评审命令

Terminal window
# 当前 Search 行为测试非常少;目标应有 provider、consumer、endpoint、security、rebuild 套件。
rg -n "Search|Lucene|Conflict" tests -g '*.cs'
# 暴露 no-op、吞错、未就绪重建和缺 publisher。
rg -n "deferred|suppress|RebuildPendingDataSource|SearchIndexChangedIntegrationEvent" \
src/Platform/Search src -g '*.cs'
# 检查生产配置、相对路径和多 Host 组合。
rg -n "AddBitzOrcasSearchPlatform|LuceneBasePath|search-index|SearchIndexEventHandler" \
src/Hosts src/Platform/Search -g '*.cs'

返回 Search 总览 · 统一搜索与利冲 · 事件与重建 · Provider 与目录

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%