chore(prep): shared groundwork for batch-3 (admin/golden/cache)
第三批(T12 后台/T13 黄金集/T14 检索缓存)协调提交: - kb:KbAssetService(登记/审核,tryon_ready 只能随 approved 打开)+ Asset 模型与 repo - retrieval:list_gaps 缺口看板查询 + invalidate_cache() 钩子(T14 背后实现真缓存) - 配置:ADMIN_TOKEN(空=后台 404)+ 检索缓存三参数 - pytest golden marker(默认跳过,CI 强制跑)+ Makefile golden + CI 防线 5c - 测试隔离修复:test_auth_sms 加 autouse 清 sms:* 键夹具(频控计数跨运行 累积会毒化后续运行——随机 IP 空间仅 254 且部分用例固定 device_id)
This commit is contained in:
@@ -261,3 +261,24 @@ async def record_gap(
|
||||
else:
|
||||
gap.hit_count += 1
|
||||
gap.last_seen_at = datetime.now(UTC)
|
||||
|
||||
|
||||
#: 进程内缓存代数:invalidate_cache() 自增,缓存键带上它即可整体失效(T-P2-10)。
|
||||
#: 放 repo 而非 service,是因为 T14 的缓存模块会同文件引用,避免循环 import。
|
||||
INVALIDATION_VERSION = 1
|
||||
|
||||
|
||||
async def list_gaps(session: AsyncSession, *, limit: int = 50, offset: int = 0) -> list[RowMapping]:
|
||||
"""缺口看板查询:hit_count 降序,同频次按最近出现降序。"""
|
||||
from sqlalchemy import select
|
||||
|
||||
from packages.shared.models import KbGap
|
||||
|
||||
stmt = (
|
||||
select(KbGap)
|
||||
.order_by(KbGap.hit_count.desc(), KbGap.last_seen_at.desc())
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
)
|
||||
result = await session.execute(stmt)
|
||||
return list(result.mappings().all())
|
||||
|
||||
@@ -112,3 +112,31 @@ class RetrievalService:
|
||||
logger.error("retrieval_gap_record_failed", query_len=len(query_text))
|
||||
logger.info("retrieval_gap", query_len=len(query_text), **ctx.filter_ctx())
|
||||
return SearchOutcome(results=[], degraded=True)
|
||||
|
||||
|
||||
class GapSummary:
|
||||
"""kb_gap 的一行摘要(缺口看板的数据形状)。V1 用普通类:字段还会随
|
||||
看板需求演进,先不冻结成 dataclass。"""
|
||||
|
||||
def __init__(self, row: Any) -> None:
|
||||
self.gap_id = row.gap_id
|
||||
self.query_text = row.query_text
|
||||
self.filter_ctx = row.filter_ctx
|
||||
self.hit_count = row.hit_count
|
||||
self.first_seen_at = row.first_seen_at
|
||||
self.last_seen_at = row.last_seen_at
|
||||
|
||||
|
||||
async def list_gaps(session: AsyncSession, *, limit: int = 50, offset: int = 0) -> list[GapSummary]:
|
||||
"""缺口看板:按 hit_count 降序(最常被问到的缺口排最前,T-P2-06)。"""
|
||||
rows = await repo.list_gaps(session, limit=limit, offset=offset)
|
||||
return [GapSummary(r) for r in rows]
|
||||
|
||||
|
||||
def invalidate_cache() -> None:
|
||||
"""发布/归档知识后调用:让检索结果缓存整体失效(T-P2-10)。
|
||||
|
||||
第三批 T14 会在背后实现真正的进程内缓存;本桩保证调用方(运营后台的
|
||||
发布编排)现在就能接上这个钩子,T14 合并后无需再改调用点。
|
||||
"""
|
||||
repo.INVALIDATION_VERSION += 1
|
||||
|
||||
Reference in New Issue
Block a user