feat(search): 资源搜索结果附带规则判定
关联到本地作品的资源按作品收录版本的评估口径(硬条件 + 规则组链 + 阶梯,同自动获取的 evaluateCandidate)给出 ruleVerdict:命中第几档 / 不满足哪些维度 / 与库里当前版本相比高几档。 只调用 acquisition-organize 导出的 loadRuleCatalog、slotSpecWithRules、parsedOf、contextOf、 currentFacts;现有版本 pri 按 rulePriOfAsset 同口径在 search 模块里组合。一页最多判定 100 条、 20 个作品,收录版本 / 订阅 / 资源行 / 规则目录批量查一次;没关联作品或没有规则时为 null。 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
fb6c76875c
commit
a7d20ca370
4 files changed
+556
-1
No files matched your search
@@ -16,6 +16,7 @@ import type { SourcesRuntime } from "../sources-identity/runtime.ts";
|
||||
import { upsertSiteRelease } from "../sources-identity/service/snapshot.ts";
|
||||
import { siteCan } from "../sources-identity/site-kinds.ts";
|
||||
import { raceAbort } from "./media.ts";
|
||||
import { ruleVerdicts } from "./rule-verdict.ts";
|
||||
|
||||
// 跨站资源搜索:选中的已启用站点逐站调适配器 search(每站共享限流器 + 单站超时 + 站点级并发上限);
|
||||
// 按(站点, 查询词)并发合并、短缓存 —— 换站点选择时已查过的站点直接复用;结果 upsert 为资源
|
||||
@@ -23,7 +24,7 @@ import { raceAbort } from "./media.ts";
|
||||
// 作品关联与库存叠加在每次请求时现算(不进缓存),识别完成后刷新即可看到。
|
||||
|
||||
/** 缓存里的资源条目(不含作品关联与库存叠加) */
|
||||
export type BaseRelease = Omit<SearchRelease, "mediaEntityId" | "entityMatch" | "entity" | "inventory">;
|
||||
export type BaseRelease = Omit<SearchRelease, "mediaEntityId" | "entityMatch" | "entity" | "inventory" | "ruleVerdict">;
|
||||
|
||||
export interface Fanout {
|
||||
items: BaseRelease[];
|
||||
@@ -502,6 +503,18 @@ export async function decorate(
|
||||
entities.set(e.id, e);
|
||||
}
|
||||
const inv = entityIds.length ? await loadInventory(entityIds) : new Map<string, InventoryEntry>();
|
||||
// 规则判定:失败只记警告,不影响结果列表
|
||||
const verdicts = await ruleVerdicts(
|
||||
db,
|
||||
items.map((it) => {
|
||||
const link = links.get(it.key);
|
||||
const e = link ? entities.get(link.id) : undefined;
|
||||
return { key: it.key, sourceReleaseId: it.sourceReleaseId, entity: e ? { id: e.id, kind: e.kind } : null };
|
||||
}),
|
||||
).catch((err: Error) => {
|
||||
rt.ctx.logger.warn({ err: { message: err.message } }, "搜索结果规则判定失败");
|
||||
return new Map<string, never>();
|
||||
});
|
||||
return items.map((it) => {
|
||||
const link = links.get(it.key);
|
||||
const e = link ? entities.get(link.id) : undefined;
|
||||
@@ -512,6 +525,7 @@ export async function decorate(
|
||||
entityMatch: e ? link!.match : null,
|
||||
entity: e ? { id: e.id, title: e.title, year: e.year, kind: e.kind as never } : null,
|
||||
inventory: entry ? overlay(entry, it.sourceReleaseId) : null,
|
||||
ruleVerdict: verdicts.get(it.key) ?? null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user