mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-07-09 05:16:56 +08:00
Revert "fix: trigger initial subscribe search"
This reverts commit 76803ae7a3.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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分钟
|
||||
|
||||
@@ -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 == []
|
||||
@@ -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),
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user