mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-04 06:15:14 +08:00
fix(mediaserver): 翻页按总数收敛,剧集定位命中即返回
按代码审查意见再修两处,都与上一轮引入的关键字翻页有关: - 末页恰好装满时仍会多请求一页。响应里已带可靠总数,改为累计条数达到总数即 结束,只有没有总数时才按页是否满额判断;那次多余请求一旦失败,会把完整结果 误报成服务不可达 - 按标题定位剧集先把所有页读完再检查匹配,第一页已命中的目标会因后续页请求 失败而返回不可达,比改动前更差;改为逐行检查、命中即返回,只有在命中前中断 才报告不可达 补 2 条回归,均已确认在修正前失败。
This commit is contained in:
@@ -244,10 +244,18 @@ class MediaVault:
|
||||
def rows() -> Generator[Dict[str, Any], Any, None]:
|
||||
result: Dict[str, Any] = first
|
||||
page = 1
|
||||
seen = 0
|
||||
while True:
|
||||
batch = result.get("items") or []
|
||||
seen += len(batch)
|
||||
yield from batch
|
||||
if len(batch) < self.PAGE_LIMIT:
|
||||
total = result.get("total")
|
||||
# 有可靠总数时以它为准:末页恰好满额也不再多发一次请求,
|
||||
# 那次多余请求一旦失败会把完整结果误报成服务不可达
|
||||
if isinstance(total, int):
|
||||
if seen >= total:
|
||||
return
|
||||
elif len(batch) < self.PAGE_LIMIT:
|
||||
return
|
||||
page += 1
|
||||
following = self.__query_items(
|
||||
@@ -355,18 +363,19 @@ class MediaVault:
|
||||
if rows is None:
|
||||
return None
|
||||
try:
|
||||
search_rows = list(rows)
|
||||
# 逐行检查、命中即返回:预取全部页会让第一页已命中的目标
|
||||
# 因后续页请求失败被误报成服务不可达
|
||||
for row in rows:
|
||||
item = self.__format_item_info(row)
|
||||
if not item or item.title != title:
|
||||
continue
|
||||
if year and str(item.year) != str(year):
|
||||
continue
|
||||
if not MediaServerIdentityHelper.is_compatible(item, media_source, media_id):
|
||||
continue
|
||||
return str(item.item_id)
|
||||
except _SearchInterrupted:
|
||||
return None
|
||||
for row in search_rows:
|
||||
item = self.__format_item_info(row)
|
||||
if not item or item.title != title:
|
||||
continue
|
||||
if year and str(item.year) != str(year):
|
||||
continue
|
||||
if not MediaServerIdentityHelper.is_compatible(item, media_source, media_id):
|
||||
continue
|
||||
return str(item.item_id)
|
||||
return ""
|
||||
|
||||
def get_season_episode_ids(self, item_id: str, season: int) -> Dict[int, str]:
|
||||
|
||||
@@ -549,7 +549,8 @@ def _failing_second_page(total_rows: list):
|
||||
|
||||
def test_get_movies_reports_unreachable_when_a_later_page_fails():
|
||||
"""翻页中途断连必须返回 None,不能把残缺结果当成「不在库中」。"""
|
||||
rows = [_item_row(i, title=f"沙丘{i}") for i in range(MediaVault.PAGE_LIMIT)]
|
||||
# total 必须超过一页,否则第一页就判定取完,构造不出「中途失败」
|
||||
rows = [_item_row(i, title=f"沙丘{i}") for i in range(MediaVault.PAGE_LIMIT + 1)]
|
||||
client = _client({"/items": _failing_second_page(rows)})
|
||||
|
||||
assert client.get_movies(title="沙丘") is None
|
||||
@@ -557,7 +558,33 @@ def test_get_movies_reports_unreachable_when_a_later_page_fails():
|
||||
|
||||
def test_find_series_reports_unreachable_when_a_later_page_fails():
|
||||
"""同上:剧集定位不能把断连误判成整部剧未入库。"""
|
||||
rows = [_item_row(i, kind="Series", title=f"剧{i}") for i in range(MediaVault.PAGE_LIMIT)]
|
||||
rows = [_item_row(i, kind="Series", title=f"剧{i}") for i in range(MediaVault.PAGE_LIMIT + 1)]
|
||||
client = _client({"/items": _failing_second_page(rows)})
|
||||
|
||||
assert client.get_tv_episodes(title="剧A") == (None, None)
|
||||
|
||||
|
||||
def test_search_stops_at_reported_total_without_an_extra_request():
|
||||
"""末页恰好满额时用 total 判定取完,不再多发一次可能失败的请求。"""
|
||||
rows = [_item_row(i, title="沙丘", year=2021) for i in range(MediaVault.PAGE_LIMIT)]
|
||||
client = _client({"/items": _paged_items(rows)})
|
||||
|
||||
matched = client.get_movies(title="沙丘")
|
||||
|
||||
assert len(matched) == MediaVault.PAGE_LIMIT
|
||||
assert [call["params"]["page"] for call in client._api.calls] == [1]
|
||||
|
||||
|
||||
def test_find_series_returns_first_page_hit_even_if_a_later_page_fails():
|
||||
"""第一页已命中就该直接返回,不因后续页失败被误报成服务不可达。"""
|
||||
rows = [_item_row(0, kind="Series", title="剧A", year=2020)]
|
||||
rows += [_item_row(i, kind="Series", title=f"其它{i}") for i in range(1, MediaVault.PAGE_LIMIT + 1)]
|
||||
routes = {
|
||||
"/items": _failing_second_page(rows),
|
||||
"/items/id-0/episodes": Result(True, {"seasons": {"1": [1]}}),
|
||||
}
|
||||
|
||||
item_id, seasons = _client(routes).get_tv_episodes(title="剧A", year="2020")
|
||||
|
||||
assert item_id == "id-0"
|
||||
assert seasons == {1: [1]}
|
||||
|
||||
Reference in New Issue
Block a user