mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-04 23:17:20 +08:00
refactor: govern background tasks and query ownership
This commit is contained in:
@@ -4,7 +4,7 @@ import json
|
||||
import time
|
||||
from typing import Protocol, Union, Any, List, Optional
|
||||
|
||||
from fastapi import BackgroundTasks, Depends, Request
|
||||
from fastapi import Depends, Request
|
||||
from starlette.responses import PlainTextResponse
|
||||
|
||||
from app.schemas.message import MessageClearBefore as _SchemaMessageClearBefore
|
||||
@@ -32,6 +32,8 @@ from app.runtime.extensions.service_config import ServiceConfigHelper
|
||||
from app.runtime.log import logger
|
||||
from app.adapters.external.wechat_crypt import WXBizMsgCrypt
|
||||
from app.schemas.types import NotificationChannel, SystemConfigKey
|
||||
from app.api.context import get_background_task_registry, resolve_background_task_registry
|
||||
from app.runtime.tasks import TaskRegistry
|
||||
|
||||
router = ResponseAPIRouter()
|
||||
|
||||
@@ -116,7 +118,7 @@ def start_message_chain(body: Any, form: Any, args: Any):
|
||||
|
||||
@router.post("/", summary="接收用户消息", response_model=_SchemaResponse[None])
|
||||
async def user_message(
|
||||
background_tasks: BackgroundTasks,
|
||||
task_registry: Annotated[TaskRegistry, Depends(get_background_task_registry)],
|
||||
request: Request,
|
||||
_: _SchemaTokenPayload = Depends(verify_apitoken),
|
||||
):
|
||||
@@ -150,7 +152,9 @@ async def user_message(
|
||||
list(form.keys()) if form else [],
|
||||
image_markers,
|
||||
)
|
||||
background_tasks.add_task(start_message_chain, body, form, args)
|
||||
resolve_background_task_registry(task_registry).create_sync(
|
||||
start_message_chain, body, form, args, owner="api.message.user"
|
||||
)
|
||||
return _SchemaResponse(success=True)
|
||||
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ from app.adapters.system.plugin.package import PluginPackageManager
|
||||
from app.application.database import DatabaseWorkerOverloadedError
|
||||
from app.runtime.log import logger
|
||||
from app.schemas.types import SystemConfigKey
|
||||
from app.api.context import get_background_task_registry, resolve_background_task_registry
|
||||
from app.runtime.tasks import TaskRegistry
|
||||
|
||||
router = ResponseAPIRouter()
|
||||
_plugin_release_refresh_tasks: set[asyncio.Task] = set()
|
||||
@@ -112,11 +114,17 @@ async def _refresh_plugin_release_versions(plugin_id: str, repo_url: str) -> Non
|
||||
logger.warning(f"后台刷新插件 {plugin_id} Release 列表失败:{e}")
|
||||
|
||||
|
||||
def _schedule_plugin_release_refresh(plugin_id: str, repo_url: str) -> None:
|
||||
def _schedule_plugin_release_refresh(
|
||||
plugin_id: str, repo_url: str, task_registry: TaskRegistry | None = None
|
||||
) -> None:
|
||||
"""
|
||||
保留后台任务引用,避免任务被回收,同时让 helper 负责同仓库强刷合并。
|
||||
"""
|
||||
task = asyncio.create_task(_refresh_plugin_release_versions(plugin_id, repo_url))
|
||||
registry = resolve_background_task_registry(task_registry)
|
||||
task = registry.create(
|
||||
_refresh_plugin_release_versions(plugin_id, repo_url),
|
||||
owner="api.plugin.release_refresh",
|
||||
)
|
||||
_plugin_release_refresh_tasks.add(task)
|
||||
|
||||
def _discard_task(completed_task: asyncio.Task) -> None:
|
||||
@@ -368,6 +376,7 @@ async def plugin_releases(
|
||||
_: ApiPrincipal = Depends(get_current_active_superuser_async),
|
||||
repo_url: Optional[str] = "",
|
||||
force: bool = False,
|
||||
task_registry: TaskRegistry = Depends(get_background_task_registry),
|
||||
) -> dict:
|
||||
"""
|
||||
查询指定插件可直接安装的 GitHub Release 版本。
|
||||
@@ -404,7 +413,11 @@ async def plugin_releases(
|
||||
)
|
||||
release_items = await plugin_helper.async_get_plugin_release_versions(plugin_id, repo_url)
|
||||
if force and has_release_cache:
|
||||
_schedule_plugin_release_refresh(plugin_id, repo_url)
|
||||
_schedule_plugin_release_refresh(
|
||||
plugin_id,
|
||||
repo_url,
|
||||
resolve_background_task_registry(task_registry),
|
||||
)
|
||||
items = []
|
||||
for item in release_items:
|
||||
version = item.get("version")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import List, Any, Dict, Optional
|
||||
|
||||
from fastapi import Depends, HTTPException
|
||||
from starlette.background import BackgroundTasks
|
||||
from typing import Annotated
|
||||
|
||||
from app.schemas.common import JsonObject as _SchemaJsonObject
|
||||
from app.schemas.response import Response as _SchemaResponse
|
||||
@@ -42,6 +42,8 @@ from app.runtime.log import logger
|
||||
from app.application.scheduling import Scheduler
|
||||
from app.schemas.types import SystemConfigKey, MediaType
|
||||
from app.domain import site as site_rules
|
||||
from app.api.context import get_background_task_registry, resolve_background_task_registry
|
||||
from app.runtime.tasks import TaskRegistry
|
||||
|
||||
router = ResponseAPIRouter()
|
||||
|
||||
@@ -169,13 +171,15 @@ async def update_site(
|
||||
|
||||
@router.get("/cookiecloud", summary="CookieCloud同步", response_model=_SchemaResponse[None])
|
||||
async def cookie_cloud_sync(
|
||||
background_tasks: BackgroundTasks,
|
||||
task_registry: Annotated[TaskRegistry, Depends(get_background_task_registry)],
|
||||
_: ApiPrincipal = Depends(get_current_active_superuser_async),
|
||||
) -> Any:
|
||||
"""
|
||||
运行CookieCloud同步站点信息
|
||||
"""
|
||||
background_tasks.add_task(Scheduler().start, job_id="cookiecloud")
|
||||
resolve_background_task_registry(task_registry).create_sync(
|
||||
Scheduler().start, job_id="cookiecloud", owner="api.site.cookiecloud_sync"
|
||||
)
|
||||
return _SchemaResponse(success=True, message="CookieCloud同步任务已启动!")
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import List, Any, Annotated, Optional
|
||||
|
||||
import cn2an
|
||||
from fastapi import Request, BackgroundTasks, Depends, HTTPException, Header
|
||||
from fastapi import Request, Depends, HTTPException, Header
|
||||
|
||||
from app.schemas.common import IdData as _SchemaIdData
|
||||
from app.schemas.response import Response as _SchemaResponse
|
||||
@@ -12,6 +12,10 @@ from app.schemas.token import TokenPayload as _SchemaTokenPayload
|
||||
from app.schemas.workflow import MediaInfo as _SchemaMediaInfo
|
||||
from app.schemas.workflow import Subscribe as _SchemaSubscribe
|
||||
from app.api.response import ResponseAPIRouter
|
||||
from app.api.context import (
|
||||
get_background_task_registry,
|
||||
resolve_background_task_registry,
|
||||
)
|
||||
from app.chain.subscribe import SubscribeChain
|
||||
from app.runtime.events import eventmanager
|
||||
from app.domain.context import MediaInfo
|
||||
@@ -52,6 +56,7 @@ from app.api.dependencies.subscription import (
|
||||
)
|
||||
from app.adapters.external.server import MoviePilotServerHelper
|
||||
from app.application.scheduling import Scheduler
|
||||
from app.runtime.tasks import TaskRegistry
|
||||
from app.schemas.event import SubscribeModifiedEventData
|
||||
from app.schemas.types import (
|
||||
MUSIC_ENTITY_ALBUM,
|
||||
@@ -489,7 +494,7 @@ async def delete_subscribe_by_media_identity(
|
||||
)
|
||||
async def seerr_subscribe(
|
||||
request: Request,
|
||||
background_tasks: BackgroundTasks,
|
||||
task_registry: Annotated[TaskRegistry, Depends(get_background_task_registry)],
|
||||
authorization: Annotated[str | None, Header()] = None,
|
||||
) -> Any:
|
||||
"""
|
||||
@@ -521,7 +526,7 @@ async def seerr_subscribe(
|
||||
user_name = req_json.get("request", {}).get("requestedBy_username")
|
||||
# 添加订阅
|
||||
if media_type == MediaType.MOVIE:
|
||||
background_tasks.add_task(
|
||||
resolve_background_task_registry(task_registry).create_sync(
|
||||
start_subscribe_add,
|
||||
mtype=media_type,
|
||||
media_source=MediaSource.TMDB,
|
||||
@@ -531,6 +536,7 @@ async def seerr_subscribe(
|
||||
# 电影不传季号,避免被误判为剧集(S00)并污染通知标题
|
||||
season=None,
|
||||
username=user_name,
|
||||
owner="api.subscribe.seerr",
|
||||
)
|
||||
else:
|
||||
seasons = []
|
||||
@@ -543,7 +549,7 @@ async def seerr_subscribe(
|
||||
]
|
||||
break
|
||||
for season in seasons:
|
||||
background_tasks.add_task(
|
||||
resolve_background_task_registry(task_registry).create_sync(
|
||||
start_subscribe_add,
|
||||
mtype=media_type,
|
||||
media_source=MediaSource.TMDB,
|
||||
@@ -552,6 +558,7 @@ async def seerr_subscribe(
|
||||
year="",
|
||||
season=season,
|
||||
username=user_name,
|
||||
owner="api.subscribe.seerr",
|
||||
)
|
||||
|
||||
return _SchemaResponse(success=True)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
from typing import Any, Annotated
|
||||
|
||||
from fastapi import BackgroundTasks, Request, Depends
|
||||
from fastapi import Depends, Request
|
||||
|
||||
from app.schemas.response import Response as _SchemaResponse
|
||||
from app.api.response import ResponseAPIRouter
|
||||
from app.chain.webhook import WebhookChain
|
||||
from app.adapters.web.security.access import verify_apitoken
|
||||
from app.api.context import get_background_task_registry, resolve_background_task_registry
|
||||
from app.runtime.tasks import TaskRegistry
|
||||
|
||||
router = ResponseAPIRouter()
|
||||
|
||||
@@ -19,7 +21,7 @@ def start_webhook_chain(body: Any, form: Any, args: Any):
|
||||
|
||||
@router.post("/", summary="Webhook消息响应", response_model=_SchemaResponse[None])
|
||||
async def webhook_message(
|
||||
background_tasks: BackgroundTasks,
|
||||
task_registry: Annotated[TaskRegistry, Depends(get_background_task_registry)],
|
||||
request: Request,
|
||||
_: Annotated[str, Depends(verify_apitoken)],
|
||||
) -> Any:
|
||||
@@ -29,13 +31,15 @@ async def webhook_message(
|
||||
body = await request.body()
|
||||
form = await request.form()
|
||||
args = request.query_params
|
||||
background_tasks.add_task(start_webhook_chain, body, form, args)
|
||||
resolve_background_task_registry(task_registry).create_sync(
|
||||
start_webhook_chain, body, form, args, owner="api.webhook.message"
|
||||
)
|
||||
return _SchemaResponse(success=True)
|
||||
|
||||
|
||||
@router.get("/", summary="Webhook消息响应", response_model=_SchemaResponse[None])
|
||||
async def webhook_message_get(
|
||||
background_tasks: BackgroundTasks,
|
||||
task_registry: Annotated[TaskRegistry, Depends(get_background_task_registry)],
|
||||
request: Request,
|
||||
_: Annotated[str, Depends(verify_apitoken)],
|
||||
) -> Any:
|
||||
@@ -43,5 +47,7 @@ async def webhook_message_get(
|
||||
Webhook响应,配置请求中需要添加参数:token=API_TOKEN&source=媒体服务器名
|
||||
"""
|
||||
args = request.query_params
|
||||
background_tasks.add_task(start_webhook_chain, None, None, args)
|
||||
resolve_background_task_registry(task_registry).create_sync(
|
||||
start_webhook_chain, None, None, args, owner="api.webhook.message"
|
||||
)
|
||||
return _SchemaResponse(success=True)
|
||||
|
||||
Reference in New Issue
Block a user