From 992031ef95cfee41fe6aa6b361db64aa66c51cd5 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 6 Jul 2026 19:14:42 +0800 Subject: [PATCH] Revert "fix: trigger initial subscribe search" This reverts commit 76803ae7a37456bc0405c32c674687edac135580. --- app/api/endpoints/subscribe.py | 25 +--- app/chain/subscribe.py | 2 +- tests/test_subscribe_create_search.py | 176 -------------------------- tests/test_subscribe_endpoint.py | 9 +- 4 files changed, 6 insertions(+), 206 deletions(-) delete mode 100644 tests/test_subscribe_create_search.py diff --git a/app/api/endpoints/subscribe.py b/app/api/endpoints/subscribe.py index 4859cad8..15ef4219 100644 --- a/app/api/endpoints/subscribe.py +++ b/app/api/endpoints/subscribe.py @@ -27,24 +27,9 @@ from app.schemas.types import MediaType, EventType, SystemConfigKey router = APIRouter() -def _schedule_subscribe_search( - background_tasks: Optional[BackgroundTasks], subscribe_id: Optional[int] -) -> None: - """ - 入队新增订阅的首次搜索任务。 - """ - if not background_tasks or not subscribe_id: - return - background_tasks.add_task( - Scheduler().start, - job_id="new_subscribe_search", - **{"sid": subscribe_id, "state": None, "manual": False}, - ) - - def start_subscribe_add( title: str, year: str, mtype: MediaType, tmdbid: int, season: int, username: str -) -> None: +): """ 启动订阅任务 """ @@ -146,7 +131,6 @@ async def list_subscribes(_: Annotated[str, Depends(verify_apitoken)]) -> Any: async def create_subscribe( *, subscribe_in: schemas.Subscribe, - background_tasks: BackgroundTasks, current_user: User = Depends(get_current_active_user_async), ) -> schemas.Response: """ @@ -183,8 +167,6 @@ async def create_subscribe( owner_scope=not current_user.is_superuser, **subscribe_dict, ) - if message == "新增订阅成功": - _schedule_subscribe_search(background_tasks, sid) return schemas.Response(success=bool(sid), message=message, data={"id": sid}) @@ -746,7 +728,6 @@ async def subscribe_share_delete( @router.post("/fork", summary="复用订阅", response_model=schemas.Response) async def subscribe_fork( sub: schemas.SubscribeShare, - background_tasks: BackgroundTasks, current_user: User = Depends(get_current_active_user_async), ) -> Any: """ @@ -758,9 +739,7 @@ async def subscribe_fork( if not hasattr(schemas.Subscribe(), key): sub_dict.pop(key) result = await create_subscribe( - subscribe_in=schemas.Subscribe(**sub_dict), - background_tasks=background_tasks, - current_user=current_user, + subscribe_in=schemas.Subscribe(**sub_dict), current_user=current_user ) if result.success: await MoviePilotServerHelper.async_sub_fork(share_id=sub.id) diff --git a/app/chain/subscribe.py b/app/chain/subscribe.py index 790707b8..9b66d832 100644 --- a/app/chain/subscribe.py +++ b/app/chain/subscribe.py @@ -1190,7 +1190,7 @@ class SubscribeChain(ChainBase): if subscribe.date: now = datetime.now() subscribe_time = datetime.strptime(subscribe.date, '%Y-%m-%d %H:%M:%S') - if not sid and not manual and (now - subscribe_time).total_seconds() < 60: + if (now - subscribe_time).total_seconds() < 60: logger.debug(f"订阅标题:{subscribe.name} 新增小于1分钟,暂不搜索...") continue # 随机休眠1-5分钟 diff --git a/tests/test_subscribe_create_search.py b/tests/test_subscribe_create_search.py deleted file mode 100644 index ebbc9fba..00000000 --- a/tests/test_subscribe_create_search.py +++ /dev/null @@ -1,176 +0,0 @@ -import asyncio -from datetime import datetime -from types import SimpleNamespace -from typing import Any, Callable, Optional -from unittest.mock import AsyncMock, patch - -from app.api.endpoints.subscribe import create_subscribe -from app.chain.subscribe import SubscribeChain -from app.schemas.subscribe import Subscribe -from app.schemas.types import MediaType - - -class _BackgroundTasks: - """ - 最小后台任务替身,记录订阅创建接口入队的任务。 - """ - - def __init__(self) -> None: - self.tasks = [] - - def add_task(self, func: Callable[..., Any], **kwargs: Any) -> None: - """ - 记录后台任务函数和参数。 - """ - self.tasks.append({"func": func, "kwargs": kwargs}) - - -class _User(SimpleNamespace): - """ - 最小用户替身,模拟订阅创建接口依赖的用户字段。 - """ - - def __init__(self, name: str, is_superuser: bool) -> None: - super().__init__(name=name, is_superuser=is_superuser) - - -class _SubscribeOper: - """ - 最小订阅 Oper 替身,隔离 SubscribeChain.search 的数据库访问。 - """ - - subscribe: Optional[SimpleNamespace] = None - updates: list[tuple[int, dict[str, Any]]] = [] - - def get(self, sid: int) -> Optional[SimpleNamespace]: - """ - 按 ID 返回测试订阅对象。 - """ - return self.subscribe if self.subscribe and self.subscribe.id == sid else None - - def list(self, _state: str) -> list[SimpleNamespace]: - """ - 返回批量搜索需要的测试订阅列表。 - """ - return [self.subscribe] if self.subscribe else [] - - def update(self, sid: int, payload: dict[str, Any]) -> None: - """ - 记录订阅状态更新请求。 - """ - self.updates.append((sid, payload)) - - -def _new_subscribe() -> SimpleNamespace: - """ - 构造一个刚创建的电影订阅。 - """ - return SimpleNamespace( - id=31, - name="测试电影", - year="2026", - type=MediaType.MOVIE.value, - tmdbid=12345, - doubanid=None, - season=None, - custom_words=None, - date=datetime.now().strftime("%Y-%m-%d %H:%M:%S"), - state="N", - episode_group=None, - ) - - -def test_create_subscribe_schedules_first_search_for_new_subscribe() -> None: - """ - API 新增订阅成功后应立即入队该订阅的首次后台搜索。 - """ - background_tasks = _BackgroundTasks() - subscribe_in = Subscribe( - name="测试电影", - year="2026", - type=MediaType.MOVIE.value, - ) - - with patch( - "app.api.endpoints.subscribe.SubscribeChain.async_add", - new=AsyncMock(return_value=(31, "新增订阅成功")), - ), patch("app.api.endpoints.subscribe.Scheduler") as scheduler: - response = asyncio.run( - create_subscribe( - subscribe_in=subscribe_in, - background_tasks=background_tasks, - current_user=_User(name="alice", is_superuser=False), - ) - ) - - assert response.success - assert len(background_tasks.tasks) == 1 - assert background_tasks.tasks[0]["func"] == scheduler.return_value.start - assert background_tasks.tasks[0]["kwargs"] == { - "job_id": "new_subscribe_search", - "sid": 31, - "state": None, - "manual": False, - } - - -def test_create_subscribe_does_not_search_existing_subscribe() -> None: - """ - 重复订阅返回已存在时不应额外触发首次搜索。 - """ - background_tasks = _BackgroundTasks() - subscribe_in = Subscribe( - name="测试电影", - year="2026", - type=MediaType.MOVIE.value, - ) - - with patch( - "app.api.endpoints.subscribe.SubscribeChain.async_add", - new=AsyncMock(return_value=(31, "订阅已存在")), - ), patch("app.api.endpoints.subscribe.Scheduler") as scheduler: - response = asyncio.run( - create_subscribe( - subscribe_in=subscribe_in, - background_tasks=background_tasks, - current_user=_User(name="alice", is_superuser=False), - ) - ) - - assert response.success - assert background_tasks.tasks == [] - scheduler.assert_not_called() - - -def test_subscribe_search_runs_single_new_subscribe_immediately(monkeypatch) -> None: - """ - 指定订阅 ID 的首次搜索不应被新建 60 秒保护挡住。 - """ - subscribe = _new_subscribe() - _SubscribeOper.subscribe = subscribe - _SubscribeOper.updates = [] - monkeypatch.setattr("app.chain.subscribe.SubscribeOper", _SubscribeOper) - - with patch.object(SubscribeChain, "recognize_media", return_value=None) as recognize: - chain = object.__new__(SubscribeChain) - chain.search(sid=subscribe.id, state=None, manual=False) - - recognize.assert_called_once() - assert _SubscribeOper.updates == [(subscribe.id, {"state": "R"})] - - -def test_subscribe_search_keeps_batch_new_subscribe_delay(monkeypatch) -> None: - """ - 定时批量扫描新订阅时仍保留 60 秒编辑窗口。 - """ - subscribe = _new_subscribe() - _SubscribeOper.subscribe = subscribe - _SubscribeOper.updates = [] - monkeypatch.setattr("app.chain.subscribe.SubscribeOper", _SubscribeOper) - - with patch.object(SubscribeChain, "recognize_media", return_value=None) as recognize: - chain = object.__new__(SubscribeChain) - chain.search(state="N", manual=False) - - recognize.assert_not_called() - assert _SubscribeOper.updates == [] diff --git a/tests/test_subscribe_endpoint.py b/tests/test_subscribe_endpoint.py index cb775698..2e34d8b5 100644 --- a/tests/test_subscribe_endpoint.py +++ b/tests/test_subscribe_endpoint.py @@ -362,7 +362,7 @@ class SubscribeEndpointTest(TestCase): with patch( "app.api.endpoints.subscribe.Subscribe.async_list_by_username", new=AsyncMock(return_value=owned), - ), patch("app.api.endpoints.subscribe.Scheduler"): + ): response = asyncio.run( search_subscribes( background_tasks=background_tasks, @@ -610,11 +610,10 @@ class SubscribeEndpointTest(TestCase): with patch( "app.api.endpoints.subscribe.SubscribeChain.async_add", new=AsyncMock(return_value=(1, "新增订阅成功")), - ) as async_add, patch("app.api.endpoints.subscribe.Scheduler"): + ) as async_add: response = asyncio.run( create_subscribe( subscribe_in=subscribe_in, - background_tasks=_EndpointBackgroundTasks(), current_user=_EndpointUser(name="moviepilot-user", is_superuser=False), ) ) @@ -644,11 +643,10 @@ class SubscribeEndpointTest(TestCase): ), patch( "app.api.endpoints.subscribe.SubscribeChain.async_add", new=AsyncMock(return_value=(1, "新增订阅成功")), - ) as async_add, patch("app.api.endpoints.subscribe.Scheduler"): + ) as async_add: response = asyncio.run( create_subscribe( subscribe_in=subscribe_in, - background_tasks=_EndpointBackgroundTasks(), current_user=_EndpointUser(name="moviepilot-user", is_superuser=False), ) ) @@ -674,7 +672,6 @@ class SubscribeEndpointTest(TestCase): response = asyncio.run( create_subscribe( subscribe_in=subscribe_in, - background_tasks=_EndpointBackgroundTasks(), current_user=_EndpointUser(name="admin", is_superuser=True), ) )