mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 07:27:15 +08:00
fix(subscribe): fail closed on lock timeout (#6384)
This commit is contained in:
+14
-2
@@ -1375,7 +1375,13 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
|||||||
):
|
):
|
||||||
logger.debug(f"search lock acquired at {datetime.now()}")
|
logger.debug(f"search lock acquired at {datetime.now()}")
|
||||||
else:
|
else:
|
||||||
logger.warn("search上锁超时")
|
logger.error("订阅搜索锁等待超时,已中止本轮执行")
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(
|
||||||
|
value=100,
|
||||||
|
text="订阅搜索锁等待超时,已跳过本轮",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
subscribeoper = SubscribeOper()
|
subscribeoper = SubscribeOper()
|
||||||
if sid:
|
if sid:
|
||||||
@@ -1819,7 +1825,13 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
|
|||||||
):
|
):
|
||||||
logger.debug(f"match lock acquired at {datetime.now()}")
|
logger.debug(f"match lock acquired at {datetime.now()}")
|
||||||
else:
|
else:
|
||||||
logger.warn("match上锁超时")
|
logger.error("订阅匹配锁等待超时,已中止本轮执行")
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(
|
||||||
|
value=100,
|
||||||
|
text="订阅匹配锁等待超时,已跳过本轮",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
# 预识别所有未识别的种子
|
# 预识别所有未识别的种子
|
||||||
processed_torrents: Dict[str, List[Context]] = {}
|
processed_torrents: Dict[str, List[Context]] = {}
|
||||||
|
|||||||
@@ -309,6 +309,8 @@
|
|||||||
"微信 ClawBot 通知未启用或配置尚未保存,请先保存并启用当前渠道": "WeChat ClawBot notification is not enabled or the configuration has not been saved. Please save and enable this channel first",
|
"微信 ClawBot 通知未启用或配置尚未保存,请先保存并启用当前渠道": "WeChat ClawBot notification is not enabled or the configuration has not been saved. Please save and enable this channel first",
|
||||||
"请输入至少一个有效的站点 ID": "Enter at least one valid site ID",
|
"请输入至少一个有效的站点 ID": "Enter at least one valid site ID",
|
||||||
"所有订阅搜索完成": "All subscription searches are complete",
|
"所有订阅搜索完成": "All subscription searches are complete",
|
||||||
|
"订阅搜索锁等待超时,已跳过本轮": "Subscription search lock timed out, this round was skipped",
|
||||||
|
"订阅匹配锁等待超时,已跳过本轮": "Subscription matching lock timed out, this round was skipped",
|
||||||
"请输入订阅 ID,多个 ID 用空格分隔,或输入 all": "Enter subscription IDs separated by spaces, or enter all",
|
"请输入订阅 ID,多个 ID 用空格分隔,或输入 all": "Enter subscription IDs separated by spaces, or enter all",
|
||||||
"请输入至少一个有效的订阅 ID": "Enter at least one valid subscription ID",
|
"请输入至少一个有效的订阅 ID": "Enter at least one valid subscription ID",
|
||||||
"格式错误,请输入:cookie <id> <username> <password> [2fa_code/secret]": "Invalid format. Enter: cookie <id> <username> <password> [2fa_code/secret]",
|
"格式错误,请输入:cookie <id> <username> <password> [2fa_code/secret]": "Invalid format. Enter: cookie <id> <username> <password> [2fa_code/secret]",
|
||||||
|
|||||||
@@ -34,6 +34,18 @@ class _SubscribeOper:
|
|||||||
self.updates.append((sid, payload))
|
self.updates.append((sid, payload))
|
||||||
|
|
||||||
|
|
||||||
|
class _TimedOutLock:
|
||||||
|
"""模拟订阅搜索锁在等待窗口内始终无法取得。"""
|
||||||
|
|
||||||
|
def acquire(self, **_kwargs):
|
||||||
|
"""返回未取得锁,验证调用方不会越过互斥边界继续执行。"""
|
||||||
|
return False
|
||||||
|
|
||||||
|
def release(self):
|
||||||
|
"""超时路径不应释放未持有的锁。"""
|
||||||
|
raise AssertionError("未持有的订阅锁不应被释放")
|
||||||
|
|
||||||
|
|
||||||
def _new_subscribe(created_at: datetime) -> SimpleNamespace:
|
def _new_subscribe(created_at: datetime) -> SimpleNamespace:
|
||||||
"""
|
"""
|
||||||
构造一个新建电影订阅。
|
构造一个新建电影订阅。
|
||||||
@@ -90,3 +102,31 @@ def test_new_subscribe_search_marks_state_after_attempt(monkeypatch) -> None:
|
|||||||
|
|
||||||
media_chain.recognize_media.assert_called_once()
|
media_chain.recognize_media.assert_called_once()
|
||||||
assert _SubscribeOper.updates == [(31, {"state": "R"})]
|
assert _SubscribeOper.updates == [(31, {"state": "R"})]
|
||||||
|
|
||||||
|
|
||||||
|
def test_subscribe_search_aborts_when_lock_times_out(monkeypatch) -> None:
|
||||||
|
"""订阅搜索锁超时后必须中止,不能在无锁状态下继续访问订阅。"""
|
||||||
|
monkeypatch.setattr(SubscribeChain, "_rlock", _TimedOutLock())
|
||||||
|
subscribe_oper = Mock()
|
||||||
|
monkeypatch.setattr(subscribe_module, "SubscribeOper", subscribe_oper)
|
||||||
|
progress = Mock()
|
||||||
|
|
||||||
|
chain = object.__new__(SubscribeChain)
|
||||||
|
chain.search(state="N", progress_callback=progress)
|
||||||
|
|
||||||
|
subscribe_oper.assert_not_called()
|
||||||
|
progress.assert_called_once_with(
|
||||||
|
value=100,
|
||||||
|
text="订阅搜索锁等待超时,已跳过本轮",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_subscribe_match_aborts_when_lock_times_out(monkeypatch) -> None:
|
||||||
|
"""订阅匹配锁超时后必须中止,不能绕过防重复下载边界。"""
|
||||||
|
monkeypatch.setattr(SubscribeChain, "_rlock", _TimedOutLock())
|
||||||
|
progress = Mock()
|
||||||
|
|
||||||
|
chain = object.__new__(SubscribeChain)
|
||||||
|
chain.match({"example.org": []}, progress_callback=progress)
|
||||||
|
|
||||||
|
progress.assert_any_call(value=100, text="订阅匹配锁等待超时,已跳过本轮")
|
||||||
|
|||||||
Reference in New Issue
Block a user