refactor: route tmdb supplement through module dispatch

This commit is contained in:
jxxghp
2026-08-25 06:59:18 +08:00
parent 0489bb1f43
commit 9c44eeb493
3 changed files with 38 additions and 13 deletions
+4 -5
View File
@@ -623,12 +623,11 @@ class MediaChain(ChainBase, metaclass=Singleton):
if mediainfo.tmdb_id and mediainfo.tmdb_info and mediainfo.genre_ids: if mediainfo.tmdb_id and mediainfo.tmdb_info and mediainfo.genre_ids:
return mediainfo return mediainfo
tmdb_meta = self._build_tmdb_supplement_meta(mediainfo, metainfo) tmdb_meta = self._build_tmdb_supplement_meta(mediainfo, metainfo)
tmdb_module = self.modulemanager.get_running_module("TheMovieDbModule") # 按 source 路由走统一 dispatch:宿主识别模块对非自身来源都会快速返回 None,
if not tmdb_module: # 指定 TMDB 来源时只有 TheMovieDbModule 会应答,链层无需点名具体模块
logger.warn("TMDB 模块未启用,无法补充 TMDB 辅助信息")
return mediainfo
try: try:
tmdb_media = tmdb_module.recognize_media( tmdb_media = self.run_module(
"recognize_media",
meta=tmdb_meta, meta=tmdb_meta,
mtype=mediainfo.type, mtype=mediainfo.type,
media_source=MediaSource.TMDB, media_source=MediaSource.TMDB,
@@ -62,6 +62,14 @@ chain 层零 `app.db` / `app.modules` 内部直连,domain 与 chain 层配置
* `scraping.py:584-598` 自行聚合 `metadata_img` 多模块结果 * `scraping.py:584-598` 自行聚合 `metadata_img` 多模块结果
dispatcher 已有 aggregation contract 可表达)。 dispatcher 已有 aggregation contract 可表达)。
> 处理进展(2026-08-24):`media.py` 的 TMDB 补充已改为按 source 路由的
> `run_module("recognize_media")` 统一调度(宿主识别模块对非自身来源快速返回 None,
> 与 `_recognition.py` 既有模式一致)。`scraping.py` 的 `metadata_img` 合并经复核
> **不能直接替换**:手写循环是"按键合并、宿主模块限定",而 dispatcher 现有聚合只有
> 整体短路或后值覆盖,且 dispatch 全局插件优先会让第三方插件图片覆盖内置源图片。
> 如需收口,须先做显式架构决策:新增"按键填充"聚合模式并提供调用方可控的
> provider 排序策略,否则维持现状是行为最安全的选择。
## 四、全局状态:"通道已建、存量过半" ## 四、全局状态:"通道已建、存量过半"
| 全局点 | 现状 | 建议 | | 全局点 | 现状 | 建议 |
+26 -8
View File
@@ -1,8 +1,10 @@
from types import SimpleNamespace from types import SimpleNamespace
from unittest.mock import Mock
from app.chain.media import MediaChain from app.chain.media import MediaChain
from app.domain.context import MediaInfo from app.domain.context import MediaInfo
from app.domain.metainfo import MetaInfo from app.domain.metainfo import MetaInfo
from app.runtime.extensions.module.dispatcher import ModuleInvocationDispatcher
from app.schemas.types import MediaSource, MediaType from app.schemas.types import MediaSource, MediaType
@@ -13,19 +15,35 @@ class _FakeTmdbModule:
"""保存测试需要返回的 TMDB 媒体信息。""" """保存测试需要返回的 TMDB 媒体信息。"""
self.result = result self.result = result
def recognize_media(self, **_kwargs): def get_name(self) -> str:
"""同步返回固定 TMDB 媒体信息""" """返回模块展示名"""
return "FakeTmdbModule"
def get_priority(self) -> int:
"""返回模块调度优先级。"""
return 0
def recognize_media(self, **kwargs):
"""与宿主识别模块一致:只应答 TMDB 来源的请求。"""
if kwargs.get("media_source") != MediaSource.TMDB:
return None
return self.result return self.result
def _make_chain(tmdb_media: MediaInfo) -> MediaChain: def _make_chain(tmdb_media: MediaInfo) -> MediaChain:
"""构造不加载真实模块的媒体处理链。""" """构造经真实 dispatch 算法路由、但不加载真实模块的媒体处理链。"""
chain = object.__new__(MediaChain)
module = _FakeTmdbModule(tmdb_media) module = _FakeTmdbModule(tmdb_media)
chain.modulemanager = SimpleNamespace( module_manager = Mock()
get_running_module=lambda module_id: ( module_manager.get_running_modules.return_value = [module]
module if module_id == "TheMovieDbModule" else None plugin_manager = Mock()
) plugin_manager.get_plugin_modules.return_value = {}
chain = object.__new__(MediaChain)
chain._module_dispatcher = ModuleInvocationDispatcher(
module_catalog=module_manager,
plugin_catalog=plugin_manager,
plugin_error_handler=lambda *args, **kwargs: None,
system_error_handler=lambda *args, **kwargs: None,
rate_limit_handler=lambda *args, **kwargs: None,
) )
return chain return chain