# 资源识别与待识别池运行手册(DEC-1) 新观察到的资源(RSS、站点列表快照、搜索结果)先进待识别池,只在有理由时才查 TMDB。只有和订阅或本地作品相关、 又需要你决定的资源才进待处理。对照 MoviePilot:RSS / 站点资源只在匹配订阅或用户搜索时才识别,识别失败只写日志、不告警 (`app/chain/subscribe/match.py` `_prepare_match_torrents`:未识别的种子最多重试 3 次,之后跳过)。 需求依据:REQ §4.2–4.3(观察不等于事实)、§6.3(新作品收录 / 追更补缺 / 升级都由规则触发)、§7.5(待识别池可检索、 不污染正式库、有界复查、不留死数据)、§13(待处理按作品与问题类型合并)。 ## 识别流程(resolveObservation) 1. 解析标题(release-parser),本地召回:显式外部 ID、`title_alias` 精确 / pg_trgm ≥ 0.45(本地作品 = 订阅、追踪、已登记的作品)。 2. 判断是否查 TMDB(`lookup`,记在 `source_release.resolution_evidence.lookup` 和池条目 `query.lookup`): | lookup | 条件 | |---|---| | `manual` | 任务输入 `trigger: "manual"`:池里点「重新识别」、Agent / 能力 `identity.resolve` | | `search` | 任务输入 `trigger: "search"`:搜索结果 | | `tracked_alias` | 本地召回有候选(标题命中订阅 / 本地作品的别名) | | `previously_looked_up` | 周期复查,且这条池条目以前查过 TMDB(旧数据、手动、规则触发) | | `eager` | 设置 `identity.eagerTmdbLookup = true` | | `new_title_rule` | 有已发布、开启 `newTitle` 且有有效持续授权的获取策略,资源类型在规则的 `mediaKinds` 内,标题年份(若有)不早于窗口能覆盖的年份 | 都不满足:只进池,`reason = unmatched`,不查 TMDB,不开待处理。 3. 查了 TMDB 的,走原来的 `domain.resolveIdentity`:auto 建档 / 关联并发 `release.resolved`;否则进池。 任务输入 `trigger` 缺省:`force` 为 true 视为 `review`(池复查),否则 `observed`。 搜索模块想让搜索结果直接识别,入队 `resolveObservation` 时传 `trigger: "search"`(目前搜索结果经 `release.observed` 进来, 按 observed 处理;命中订阅别名的照样会查)。 ## 待处理只收相关的 | 结果 | 开事项? | |---|---| | `unmatched` | 否 | | `ambiguous` / `proposed`(查过 TMDB,有候选) | 是,`identity_ambiguous`,级别 warning | | `no_match` / 复查已停的 `lookup_failed` | 只有本地召回有候选(与本地作品相关)时开 `identity_unresolved`,级别 warning | 合并:dedupeKey `identity-group::<归一化标题>`,同来源同标题的资源并成一条。成员 = `identity_candidate.decision_id` 指向该事项且仍 `pending` 的条目。标题 1 条时写资源原标题,多条时写「来源「X」的 N 条资源待识别 / 待确认身份:<标题>」, `evidence.releases` 列前 50 条,`evidence.count` 为总数。 - 处理(选候选 / 手动 TMDB ID / 选本地作品):先处理代表资源(subject),再把确定的作品套到组内其它资源(都加人工锁)。 - 忽略:组内每条池条目都 `dismissed`。 - 组内某条被单独识别 / 指定 / 忽略:从组里摘除,代表资源和候选选项换成剩下的最近一条;组空了才关事项。 - 旧式单条事项(`identity:`)在该资源下次复查时并入合并事项并关闭。 收件箱:顶栏角标和待处理页缺省只算 warning 及以上(`minSeverity=warning`),"仅信息"类在待处理页「级别 → 含仅信息」里看。 待处理页按问题类型 + 作品 / 来源分组,前 3 组展开,其余折叠;合并事项卡片可展开组内资源。 ## 池的治理 - 复查有上限:`unmatched` 每天一次本地召回,最多 3 次;查过 TMDB 的按原退避(无结果 1h 起、查询失败 15min 起,翻倍到 7 天,最多 8 次)。 - 新证据即重试:`title_alias` 插入触发器 `title_alias_wake_identity_pool`,把归一化标题相同或相似度 ≥ 0.45 的 `unmatched` / `no_match` 池条目的 `next_review_at` 设为现在。建档、手动加别名、合并作品都会触发。 - 过期归档:`identity.poolArchiveDays`(缺省 30)天没有新尝试的 `unmatched` 条目改为 `archived`,在池复查定时任务里做, 每进程每小时最多一次。归档不删资源,仍可按状态筛出、手动指定。 - 检索:媒体概览 → 待识别,按原始标题 / 解析标题检索,原因筛「未命中订阅」即 unmatched。条目详情里可「重新识别」 (手动触发,会查 TMDB)、手动指定 TMDB ID / 本地作品(复用 `/identity-pool/{id}/assign`,加人工锁)或忽略。 ## 设置 设置 → 元数据 → 资源识别: - `identity.eagerTmdbLookup`(缺省关):打开即旧行为,每条新资源都查 TMDB。每条约 1–2 次搜索 + 命中时 1 次详情 (识别缓存命中为 0);每小时 100 条的 RSS 约每天 2400–7200 次请求,站点独有的短剧 / 综艺多半查不到。 打开后无结果的资源仍只进池,不开事项。 - `identity.poolArchiveDays`(缺省 30)。 ## 存量清理(迁移 0047_identity_pool) 未关闭的 `identity_unresolved` 事项中,资源未关联作品、池里没有候选、归一化标题也不命中任何本地别名的: 事项改 `dismissed`,`resolution = {"resolution":"moved_to_pool","by":"migration:0047_identity_pool"}`; 池条目改 `reason = unmatched`、清 `decision_id`、停自动复查。相关的保留原样,下次复查时并入合并事项。 需要重建镜像 / 重启 api + worker 才生效(迁移随启动执行)。 ## 排查 ```sql -- 池分布 select reason, status, count(*) from identity_candidate group by 1, 2 order by 3 desc; -- 某条资源为什么没查 TMDB select resolution_status, resolution_evidence->>'lookup' as lookup, resolution_evidence->>'detail' as detail from source_release where id = ''; -- 某个合并事项的成员 select p.source_release_id, r.title, p.reason from identity_candidate p join source_release r on r.id = p.source_release_id where p.decision_id = '' and p.status = 'pending'; -- 迁移搬走的事项 select count(*) from decision where resolution->>'resolution' = 'moved_to_pool'; ```