fix: 修复 11 个代码架构审计问题

H1: AppConfig 自定义 __init__ 改用 from_dict() 类方法
H2: list_collections_with_stats 改为从 ChromaDB 直接查询
H3: RateLimiter 过期 key 自动清理, 防止内存泄漏
M1: delete_by_source 区分 ValueError 与真实异常, 记日志
M2: VectorDB 新增 list_collections() 封装方法
M3: _remove_by_source 异常记日志, 不再静默吞掉
M4: CLI 集合回退支持 MD_VECTOR_DB_COLLECTION 环境变量
L1: DEFAULT_CONFIG_PATH 自动从项目根目录解析
L2: ingest 命令内重复 import 移至模块顶部
L3: 新增死循环回归测试 + 密集分隔符分块测试
L4: 统一 logger 名称为 md-vector-db
删除旧版审计文档

测试: 48 passed
This commit is contained in:
2026-07-06 13:16:26 +08:00
parent 7e77c31e16
commit 832201186d
13 changed files with 815 additions and 50 deletions
+26
View File
@@ -68,6 +68,32 @@ def hello():
all_content = " ".join(c["content"] for c in chunks)
assert "def hello()" in all_content
def test_separator_near_start_does_not_loop(self, splitter):
"""分隔符紧挨 start 时不会死循环 (回归测试, fix: start=max(start+1, next_start)).
场景: 超长段落中, 分隔符出现在距离 start 小于 overlap 的位置,
_split_single_paragraph 的 start 会回退为负数, str.rfind 负索引绕回导致死循环.
"""
# 100 个句号 + 大量内容 → 句号密集在开头且很近
text = "" * 80 + "内容文本" * 500
md = f"# 边界测试\n{text}"
chunks = splitter.split(md, source_file="edge.md")
# 不卡死即通过
assert len(chunks) > 0
# 验证内容完整
all_text = "".join(c["content"] for c in chunks)
assert "内容文本" in all_text
def test_dense_separators_in_long_para(self, splitter):
"""超长段落中分隔符密集分布也能正确分块."""
# ~2000 字符: 每段 20 个"内容文本" + "。",共 30 段
text = ""
for i in range(30):
text += "内容文本" * 20 + "" * (3 if i % 5 == 0 else 1) + "\n"
md = f"# 密集分隔符\n{text}"
chunks = splitter.split(md, source_file="dense.md")
assert len(chunks) > 1 # 超过 1000 字符应被拆分
class TestDocumentIngestor:
"""文档入库器测试."""