fix(api): preserve startup import budget

This commit is contained in:
jxxghp
2026-09-04 19:04:08 +08:00
parent 8b74063908
commit 0d0bcf8a3b
11 changed files with 34 additions and 18 deletions
+4 -1
View File
@@ -44,7 +44,6 @@ from app.application.transfer.execution import (
TransferExecutionRepository,
TransferRetryRequestResult,
)
from app.runtime.errors import public_error_message
from app.runtime.log import logger
from app.runtime.loop import main_loop_registry
from app.runtime.progress import AsyncProgressHelper
@@ -90,6 +89,8 @@ def _format_retry_rejections(
rejections: list[tuple[int, TransferRetryRequestResult]],
) -> str:
"""把批量整理重试拒绝原因格式化为前端可直接理解的提示。"""
from app.runtime.errors import public_error_message
return "".join(
f"{history_id} 条:{public_error_message(result.message, context='transfer')}"
for history_id, result in rejections
@@ -461,6 +462,8 @@ async def ai_redo_transfer_history(
"""
手动触发单条历史记录的 AI 重新整理,并返回进度键。
"""
from app.runtime.errors import public_error_message
runtime_config = resolve_api_runtime_config(runtime_config)
history = await query.get_transfer(history_id)
if not history:
+10 -4
View File
@@ -61,7 +61,6 @@ from app.application.subscription.status import SubscriptionExecutionStatusServi
from app.chain.subscribe.facade import SubscribeChain
from app.domain.context import MediaInfo
from app.domain.metainfo import MetaInfo
from app.runtime.errors import public_error_message
from app.runtime.execution import run_in_threadpool
from app.runtime.log import logger
from app.runtime.tasks import TaskRegistry
@@ -87,6 +86,13 @@ from app.schemas.workflow import Subscribe as _SchemaSubscribe
router = ResponseAPIRouter()
def _public_subscription_message(message: Optional[object]) -> str:
"""延迟加载订阅错误转换器,避免启动阶段增加宿主模块。"""
from app.runtime.errors import public_error_message
return public_error_message(message, context="subscription")
async def _attach_execution_status(
subscribes: list[_SchemaSubscribe],
status_service: object,
@@ -292,7 +298,7 @@ async def create_subscribe(
return _SchemaResponse(
success=bool(sid),
message=(
public_error_message(message, context="subscription")
_public_subscription_message(message)
if message
else ""
),
@@ -806,7 +812,7 @@ async def subscribe_share(
return _SchemaResponse(
success=state,
message=(
public_error_message(errmsg, context="subscription")
_public_subscription_message(errmsg)
if errmsg
else ""
),
@@ -824,7 +830,7 @@ async def subscribe_share_delete(
return _SchemaResponse(
success=state,
message=(
public_error_message(errmsg, context="subscription")
_public_subscription_message(errmsg)
if errmsg
else ""
),
+2 -1
View File
@@ -26,7 +26,6 @@ from app.application.transfer.execution import (
)
from app.chain.media import MediaChain
from app.chain.transfer.facade import TransferChain
from app.runtime.errors import public_error_message
from app.runtime.log import logger
from app.runtime.stop import runtime_stop_state
from app.schemas.common import NameData as _SchemaNameData
@@ -55,6 +54,8 @@ def _public_transfer_message(message: Optional[object]) -> Optional[str]:
"""把整理链返回的错误转换为前端可直接展示的文案。"""
if message is None or not str(message).strip():
return None
from app.runtime.errors import public_error_message
return public_error_message(message, context="transfer")
+2 -1
View File
@@ -18,7 +18,6 @@ from app.chain.subscribe.facade import SubscribeChain
from app.chain.tvdb import TvdbChain
from app.domain.context import MediaInfo
from app.domain.metainfo import MetaInfo
from app.runtime.errors import public_error_message
from app.runtime.version import get_app_version
from app.schemas.response import Response as _SchemaResponse
from app.schemas.servarr import RadarrMovie, SonarrSeries
@@ -37,6 +36,8 @@ arr_router = APIRouter(tags=["servarr"], responses=ERROR_RESPONSES)
def _subscribe_error_message(error: Optional[object]) -> str:
"""将 Servarr 订阅失败转换为调用方能理解的提示。"""
from app.runtime.errors import public_error_message
return public_error_message(
error or "订阅操作失败",
context="subscription",
+2 -1
View File
@@ -5,7 +5,6 @@ from dataclasses import dataclass
from typing import Optional, Protocol
from app.application.subscription.execution import SearchBatchSnapshot, SearchTaskSnapshot
from app.runtime.errors import public_error_message
@dataclass(frozen=True, slots=True)
@@ -219,4 +218,6 @@ class SubscriptionExecutionStatusService:
"""压平并限制内部错误文本,避免把堆栈或超长响应暴露给界面。"""
if not error:
return None
from app.runtime.errors import public_error_message
return public_error_message(error, context="subscription")[:500]
+1 -1
View File
@@ -8,7 +8,6 @@ from app.chain.media import MediaChain
from app.chain.transfer.contract import _TransferOwnerBase
from app.domain.context import MediaInfo, MusicInfo
from app.domain.meta.metabase import MetaBase
from app.runtime.errors import public_error_message
from app.runtime.log import logger
from app.schemas.message import Message
from app.schemas.tmdb import TmdbEpisode
@@ -36,6 +35,7 @@ class TransferHistoryOwner(_TransferOwnerBase):
"""
远程重新整理,参数为历史记录 ID,或媒体来源、原生 ID 与类型。
"""
from app.runtime.errors import public_error_message
def args_error():
self.post_message(
+3 -1
View File
@@ -17,7 +17,6 @@ from app.chain.media import MediaChain
from app.chain.storage import StorageChain
from app.chain.transfer.contract import _TransferOwnerBase
from app.domain.context import MusicInfo
from app.runtime.errors import public_error_message
from app.runtime.log import logger
from app.runtime.loop import main_loop_registry
from app.runtime.tasks import get_task_registry
@@ -155,6 +154,8 @@ class FailedRetryMixin(_TransferOwnerBase):
"""
立即重新整理一条失败的整理记录。
"""
from app.runtime.errors import public_error_message
self.post_message(
Message(
channel=channel,
@@ -206,6 +207,7 @@ class FailedRetryMixin(_TransferOwnerBase):
"""
由智能助手接管一条失败的整理记录。
"""
from app.runtime.errors import public_error_message
history = self.transfer_history_repository.get(history_id)
if not history:
+2 -3
View File
@@ -39,7 +39,6 @@ from app.chain.transfer.contract import _TransferOwnerBase
from app.domain import episode as episode_rules
from app.domain.context import MediaInfo, MusicInfo
from app.domain.meta.metabase import MetaBase
from app.runtime.errors import public_error_message
from app.runtime.log import logger
from app.runtime.loop import main_loop_registry
from app.schemas.message import Message
@@ -524,11 +523,11 @@ class TransferSettlementOwner(_TransferOwnerBase):
manual_identity: bool = False,
) -> None:
"""按配置逐条发送或按媒体聚合整理失败通知,供第三方整理补丁复用。"""
from app.runtime.errors import public_error_message
notification = TransferFailureNotification(
media_title=(
task.mediainfo.title_year
if task.mediainfo
else task.fileitem.name if task.fileitem else "未知媒体"
if task.mediainfo else task.fileitem.name if task.fileitem else "未知媒体"
),
season_episode=getattr(task.meta, "season_episode", "") or "",
reason=public_error_message(transferinfo.message, context="transfer") or "整理失败",
+2 -1
View File
@@ -23,7 +23,6 @@ from app.application.plugin.routes import configure_plugin_routes
from app.application.plugin.runtime import get_plugin_manager
from app.application.security.token import create_access_token, decode_access_token
from app.runtime.correlation import get_correlation_id
from app.runtime.errors import public_error_message
from app.runtime.localization import LocaleHelper
from app.runtime.log import configure_correlation_id_provider, logger
from app.runtime.loop import main_loop_registry
@@ -203,6 +202,8 @@ async def localized_http_exception_handler(
:param exc: FastAPI HTTP 异常
:return: 统一 JSON 错误响应
"""
from app.runtime.errors import public_error_message
message = _localize_exception_message(
request,
public_error_message(_get_http_exception_message(exc.detail)),
+3 -2
View File
@@ -3,7 +3,6 @@ from typing import List, Literal, Optional
from pydantic import BaseModel, ConfigDict, Field
from pydantic import field_validator as _field_validator
from app.runtime.errors import public_error_message as _public_error_message
from app.schemas.common import JsonData
from app.schemas.media import OptionalMediaIdentityMixin
from app.schemas.types import MediaSource
@@ -157,7 +156,9 @@ class TransferHistory(OptionalMediaIdentityMixin, BaseModel):
"""历史接口只返回可理解的整理失败原因,数据库原文仍用于诊断。"""
if value is None or not str(value).strip():
return None
return _public_error_message(value, context="transfer")
from app.runtime.errors import public_error_message
return public_error_message(value, context="transfer")
class BatchTransferHistoryRedoRequest(BaseModel):
+3 -2
View File
@@ -2,7 +2,6 @@ from typing import Any, Generic, Optional, TypeVar
from pydantic import BaseModel, ConfigDict, field_validator
from app.runtime.errors import public_error_message as _public_error_message
from app.runtime.localization import LocaleHelper
DataT = TypeVar("DataT")
@@ -32,7 +31,9 @@ class Response(BaseModel, Generic[DataT]):
raw_message = str(value)
if not raw_message.strip():
return ""
message = _public_error_message(raw_message)
from app.runtime.errors import public_error_message
message = public_error_message(raw_message)
if not message:
return ""
return LocaleHelper.translate_text(