mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-02 05:17:23 +08:00
fix(transfer): tolerate mtime precision drift in history gate
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from app.application.configuration import TransferRetryConfig, get_transfer_retry_config
|
||||
@@ -17,6 +18,8 @@ from app.runtime.log import logger
|
||||
MIN_FAILED_RETRIES = 1
|
||||
MAX_FAILED_RETRIES = 10
|
||||
FAILED_RETRY_TTL = 24 * 3600
|
||||
# 不同存储后端对秒级修改时间的浮点和序列化误差可能达到毫秒;更大的变化仍视为新版本。
|
||||
MODIFY_TIME_TOLERANCE = 1e-3
|
||||
|
||||
# 缓存值会同时保存文件指纹,使同一路径的新版本获得独立重试预算。
|
||||
_failed_retry_counts = TTLCache(
|
||||
@@ -140,14 +143,23 @@ def _is_file_version_changed(
|
||||
recorded_fingerprint: Dict[str, Any],
|
||||
current_fingerprint: Dict[str, Any],
|
||||
) -> bool:
|
||||
"""判断两个可比文件指纹是否指向不同版本。"""
|
||||
"""判断两个可比文件指纹是否指向不同版本,忽略修改时间的毫秒级误差。"""
|
||||
for field in ("fileid", "modify_time", "size"):
|
||||
recorded_value = recorded_fingerprint.get(field)
|
||||
current_value = current_fingerprint.get(field)
|
||||
if (
|
||||
recorded_value is not None
|
||||
and current_value is not None
|
||||
and recorded_value != current_value
|
||||
and (
|
||||
not math.isclose(
|
||||
recorded_value,
|
||||
current_value,
|
||||
rel_tol=0.0,
|
||||
abs_tol=MODIFY_TIME_TOLERANCE,
|
||||
)
|
||||
if field == "modify_time"
|
||||
else recorded_value != current_value
|
||||
)
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -591,7 +591,7 @@ class TransferExecutionOwner(_TransferOwnerBase):
|
||||
if task.mediainfo.tmdb_id:
|
||||
error_message = "TMDB 信息未匹配到媒体分类,无法按媒体类别整理"
|
||||
else:
|
||||
error_message = "未识别到 TMDB 辅助信息,无法按媒体类别整理"
|
||||
error_message = "媒体识别结果未匹配到媒体分类,无法按媒体类别整理"
|
||||
logger.error(f"{task.fileitem.name} {error_message}")
|
||||
if task.preview:
|
||||
return False, error_message
|
||||
|
||||
@@ -79,6 +79,28 @@ def test_evaluate_history_gate_skips_when_success_size_unchanged():
|
||||
assert action == HistoryGateAction.SKIP
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"current_modify_time, expected",
|
||||
[
|
||||
(100.0005, HistoryGateAction.SKIP),
|
||||
(100.01, HistoryGateAction.PASS_SIZE_CHANGED),
|
||||
],
|
||||
)
|
||||
def test_evaluate_history_gate_uses_tolerance_for_modify_time(
|
||||
current_modify_time, expected,
|
||||
):
|
||||
"""修改时间仅有毫秒级浮点漂移时应保持原版本,明显变化仍应放行。"""
|
||||
history = make_history(status=True, size=1024, modify_time=100.0)
|
||||
|
||||
action = evaluate_history_gate(
|
||||
history,
|
||||
file_size=1024,
|
||||
file_modify_time=current_modify_time,
|
||||
)
|
||||
|
||||
assert action == expected
|
||||
|
||||
|
||||
def test_evaluate_history_gate_skips_when_recorded_size_missing():
|
||||
"""成功记录缺少大小信息(如蓝光目录)时无法比对,保守跳过。"""
|
||||
history = make_history(status=True, has_src_fileitem=False)
|
||||
|
||||
@@ -161,7 +161,7 @@ def test_transfer_stops_when_automatic_category_has_no_tmdb_result(monkeypatch)
|
||||
state, message = chain._TransferChain__handle_transfer(task)
|
||||
|
||||
assert not state
|
||||
assert message == "未识别到 TMDB 辅助信息,无法按媒体类别整理"
|
||||
assert message == "媒体识别结果未匹配到媒体分类,无法按媒体类别整理"
|
||||
assert task.mediainfo.media_source == MediaSource.AniList
|
||||
assert task.mediainfo.media_id == "1234"
|
||||
assert task.plan_checkpoint is not None
|
||||
|
||||
Reference in New Issue
Block a user