RSS/list releases that match no subscription or local work no longer hit
TMDB or open a pending item; they go to the identity pool as `unmatched`.
TMDB is queried only on a local alias hit, a published new-title rule whose
prefilter passes, manual/Agent retry, search results, or when the new
setting identity.eagerTmdbLookup (default off) is on. Mirrors MoviePilot:
torrents are recognised only when matched to a subscription or searched,
and recognition failures are logged, not alerted.
- Pending items only for related releases (ambiguous after lookup, or
related to a local work but unresolved); same source + normalized title
merge into one decision ("来源「X」的 N 条资源待识别"), resolve/dismiss
applies to the whole group, members detach as they get resolved.
- Pool governance: unmatched reviews capped (daily, 3x), title_alias
insert trigger wakes similar entries, stale unmatched entries archived
after identity.poolArchiveDays (30); review idempotency keys include the
due time.
- Migration 0047_identity_pool: reason/outcome `unmatched`,
identity_candidate.normalized_title (+trgm index), wake trigger, and
cleanup of open identity_unresolved items with no related work
(dismissed, resolution=moved_to_pool).
- Inbox: group by type + work/source with collapse, hide info-only items
by default (minSeverity=warning), badge counts warning+ only; pool sheet
gets manual TMDB/local-work assign and dismiss; settings card for the
new identity settings.
- Runbook docs/runbook/identity.md.
Requires rebuild/restart (migration runs on start).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
92 lines
6.0 KiB
Markdown
92 lines
6.0 KiB
Markdown
# 资源识别与待识别池运行手册(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:<siteId>:<归一化标题>`,同来源同标题的资源并成一条。成员 = `identity_candidate.decision_id`
|
|
指向该事项且仍 `pending` 的条目。标题 1 条时写资源原标题,多条时写「来源「X」的 N 条资源待识别 / 待确认身份:<标题>」,
|
|
`evidence.releases` 列前 50 条,`evidence.count` 为总数。
|
|
|
|
- 处理(选候选 / 手动 TMDB ID / 选本地作品):先处理代表资源(subject),再把确定的作品套到组内其它资源(都加人工锁)。
|
|
- 忽略:组内每条池条目都 `dismissed`。
|
|
- 组内某条被单独识别 / 指定 / 忽略:从组里摘除,代表资源和候选选项换成剩下的最近一条;组空了才关事项。
|
|
- 旧式单条事项(`identity:<releaseId>`)在该资源下次复查时并入合并事项并关闭。
|
|
|
|
收件箱:顶栏角标和待处理页缺省只算 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 = '<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 = '<decisionId>' and p.status = 'pending';
|
|
-- 迁移搬走的事项
|
|
select count(*) from decision where resolution->>'resolution' = 'moved_to_pool';
|
|
```
|