Merge pull request #2463 from InfinityPacer/main
处理链run_module支持raise_exception
This commit is contained in:
commit
d4a9643f47
@ -10,8 +10,7 @@ from ruamel.yaml import CommentedMap
|
|||||||
from transmission_rpc import File
|
from transmission_rpc import File
|
||||||
|
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.core.context import Context
|
from app.core.context import Context, MediaInfo, TorrentInfo
|
||||||
from app.core.context import MediaInfo, TorrentInfo
|
|
||||||
from app.core.event import EventManager
|
from app.core.event import EventManager
|
||||||
from app.core.meta import MetaBase
|
from app.core.meta import MetaBase
|
||||||
from app.core.module import ModuleManager
|
from app.core.module import ModuleManager
|
||||||
@ -79,6 +78,7 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
def run_module(self, method: str, *args, **kwargs) -> Any:
|
def run_module(self, method: str, *args, **kwargs) -> Any:
|
||||||
"""
|
"""
|
||||||
运行包含该方法的所有模块,然后返回结果
|
运行包含该方法的所有模块,然后返回结果
|
||||||
|
当kwargs包含命名参数raise_exception时,如模块方法抛出异常且raise_exception为True,则同步抛出异常
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def is_result_empty(ret):
|
def is_result_empty(ret):
|
||||||
@ -117,6 +117,8 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
# 中止继续执行
|
# 中止继续执行
|
||||||
break
|
break
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
if kwargs.get("raise_exception"):
|
||||||
|
raise
|
||||||
logger.error(
|
logger.error(
|
||||||
f"运行模块 {module_id}.{method} 出错:{str(err)}\n{traceback.format_exc()}")
|
f"运行模块 {module_id}.{method} 出错:{str(err)}\n{traceback.format_exc()}")
|
||||||
self.messagehelper.put(title=f"{module_name}发生了错误",
|
self.messagehelper.put(title=f"{module_name}发生了错误",
|
||||||
@ -166,7 +168,8 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
tmdbid=tmdbid, doubanid=doubanid, bangumiid=bangumiid, cache=cache)
|
tmdbid=tmdbid, doubanid=doubanid, bangumiid=bangumiid, cache=cache)
|
||||||
|
|
||||||
def match_doubaninfo(self, name: str, imdbid: str = None,
|
def match_doubaninfo(self, name: str, imdbid: str = None,
|
||||||
mtype: MediaType = None, year: str = None, season: int = None) -> Optional[dict]:
|
mtype: MediaType = None, year: str = None, season: int = None,
|
||||||
|
raise_exception: bool = False) -> Optional[dict]:
|
||||||
"""
|
"""
|
||||||
搜索和匹配豆瓣信息
|
搜索和匹配豆瓣信息
|
||||||
:param name: 标题
|
:param name: 标题
|
||||||
@ -174,9 +177,10 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
:param mtype: 类型
|
:param mtype: 类型
|
||||||
:param year: 年份
|
:param year: 年份
|
||||||
:param season: 季
|
:param season: 季
|
||||||
|
:param raise_exception: 触发速率限制时是否抛出异常
|
||||||
"""
|
"""
|
||||||
return self.run_module("match_doubaninfo", name=name, imdbid=imdbid,
|
return self.run_module("match_doubaninfo", name=name, imdbid=imdbid,
|
||||||
mtype=mtype, year=year, season=season)
|
mtype=mtype, year=year, season=season, raise_exception=raise_exception)
|
||||||
|
|
||||||
def match_tmdbinfo(self, name: str, mtype: MediaType = None,
|
def match_tmdbinfo(self, name: str, mtype: MediaType = None,
|
||||||
year: str = None, season: int = None) -> Optional[dict]:
|
year: str = None, season: int = None) -> Optional[dict]:
|
||||||
@ -214,14 +218,15 @@ class ChainBase(metaclass=ABCMeta):
|
|||||||
image_prefix=image_prefix, image_type=image_type,
|
image_prefix=image_prefix, image_type=image_type,
|
||||||
season=season, episode=episode)
|
season=season, episode=episode)
|
||||||
|
|
||||||
def douban_info(self, doubanid: str, mtype: MediaType = None) -> Optional[dict]:
|
def douban_info(self, doubanid: str, mtype: MediaType = None, raise_exception: bool = False) -> Optional[dict]:
|
||||||
"""
|
"""
|
||||||
获取豆瓣信息
|
获取豆瓣信息
|
||||||
:param doubanid: 豆瓣ID
|
:param doubanid: 豆瓣ID
|
||||||
:param mtype: 媒体类型
|
:param mtype: 媒体类型
|
||||||
:return: 豆瓣信息
|
:return: 豆瓣信息
|
||||||
|
:param raise_exception: 触发速率限制时是否抛出异常
|
||||||
"""
|
"""
|
||||||
return self.run_module("douban_info", doubanid=doubanid, mtype=mtype)
|
return self.run_module("douban_info", doubanid=doubanid, mtype=mtype, raise_exception=raise_exception)
|
||||||
|
|
||||||
def tvdb_info(self, tvdbid: int) -> Optional[dict]:
|
def tvdb_info(self, tvdbid: int) -> Optional[dict]:
|
||||||
"""
|
"""
|
||||||
|
@ -15,6 +15,7 @@ from app.modules.douban.apiv2 import DoubanApi
|
|||||||
from app.modules.douban.douban_cache import DoubanCache
|
from app.modules.douban.douban_cache import DoubanCache
|
||||||
from app.modules.douban.scraper import DoubanScraper
|
from app.modules.douban.scraper import DoubanScraper
|
||||||
from app.schemas import MediaPerson
|
from app.schemas import MediaPerson
|
||||||
|
from app.schemas.exception import APIRateLimitException
|
||||||
from app.schemas.types import MediaType
|
from app.schemas.types import MediaType
|
||||||
from app.utils.common import retry
|
from app.utils.common import retry
|
||||||
from app.utils.http import RequestUtils
|
from app.utils.http import RequestUtils
|
||||||
@ -147,11 +148,12 @@ class DoubanModule(_ModuleBase):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def douban_info(self, doubanid: str, mtype: MediaType = None) -> Optional[dict]:
|
def douban_info(self, doubanid: str, mtype: MediaType = None, raise_exception: bool = True) -> Optional[dict]:
|
||||||
"""
|
"""
|
||||||
获取豆瓣信息
|
获取豆瓣信息
|
||||||
:param doubanid: 豆瓣ID
|
:param doubanid: 豆瓣ID
|
||||||
:param mtype: 媒体类型
|
:param mtype: 媒体类型
|
||||||
|
:param raise_exception: 触发速率限制时是否抛出异常
|
||||||
:return: 豆瓣信息
|
:return: 豆瓣信息
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
@ -427,7 +429,10 @@ class DoubanModule(_ModuleBase):
|
|||||||
info = self.doubanapi.tv_detail(doubanid)
|
info = self.doubanapi.tv_detail(doubanid)
|
||||||
if info:
|
if info:
|
||||||
if "subject_ip_rate_limit" in info.get("msg", ""):
|
if "subject_ip_rate_limit" in info.get("msg", ""):
|
||||||
logger.warn(f"触发豆瓣IP速率限制,错误信息:{info} ...")
|
msg = f"触发豆瓣IP速率限制,错误信息:{info} ..."
|
||||||
|
logger.warn(msg)
|
||||||
|
if raise_exception:
|
||||||
|
raise APIRateLimitException(msg)
|
||||||
return None
|
return None
|
||||||
celebrities = self.doubanapi.tv_celebrities(doubanid)
|
celebrities = self.doubanapi.tv_celebrities(doubanid)
|
||||||
if celebrities:
|
if celebrities:
|
||||||
@ -442,7 +447,10 @@ class DoubanModule(_ModuleBase):
|
|||||||
info = self.doubanapi.movie_detail(doubanid)
|
info = self.doubanapi.movie_detail(doubanid)
|
||||||
if info:
|
if info:
|
||||||
if "subject_ip_rate_limit" in info.get("msg", ""):
|
if "subject_ip_rate_limit" in info.get("msg", ""):
|
||||||
logger.warn(f"触发豆瓣IP速率限制,错误信息:{info} ...")
|
msg = f"触发豆瓣IP速率限制,错误信息:{info} ..."
|
||||||
|
logger.warn(msg)
|
||||||
|
if raise_exception:
|
||||||
|
raise APIRateLimitException(msg)
|
||||||
return None
|
return None
|
||||||
celebrities = self.doubanapi.movie_celebrities(doubanid)
|
celebrities = self.doubanapi.movie_celebrities(doubanid)
|
||||||
if celebrities:
|
if celebrities:
|
||||||
@ -601,7 +609,8 @@ class DoubanModule(_ModuleBase):
|
|||||||
|
|
||||||
@retry(Exception, 5, 3, 3, logger=logger)
|
@retry(Exception, 5, 3, 3, logger=logger)
|
||||||
def match_doubaninfo(self, name: str, imdbid: str = None,
|
def match_doubaninfo(self, name: str, imdbid: str = None,
|
||||||
mtype: MediaType = None, year: str = None, season: int = None) -> dict:
|
mtype: MediaType = None, year: str = None, season: int = None,
|
||||||
|
raise_exception: bool = False) -> dict:
|
||||||
"""
|
"""
|
||||||
搜索和匹配豆瓣信息
|
搜索和匹配豆瓣信息
|
||||||
:param name: 名称
|
:param name: 名称
|
||||||
@ -609,6 +618,7 @@ class DoubanModule(_ModuleBase):
|
|||||||
:param mtype: 类型
|
:param mtype: 类型
|
||||||
:param year: 年份
|
:param year: 年份
|
||||||
:param season: 季号
|
:param season: 季号
|
||||||
|
:param raise_exception: 触发速率限制时是否抛出异常
|
||||||
"""
|
"""
|
||||||
if imdbid:
|
if imdbid:
|
||||||
# 优先使用IMDBID查询
|
# 优先使用IMDBID查询
|
||||||
@ -629,7 +639,10 @@ class DoubanModule(_ModuleBase):
|
|||||||
return {}
|
return {}
|
||||||
# 触发rate limit
|
# 触发rate limit
|
||||||
if "search_access_rate_limit" in result.values():
|
if "search_access_rate_limit" in result.values():
|
||||||
logger.warn(f"触发豆瓣API速率限制,错误信息:{result} ...")
|
msg = f"触发豆瓣API速率限制,错误信息:{result} ..."
|
||||||
|
logger.warn(msg)
|
||||||
|
if raise_exception:
|
||||||
|
raise APIRateLimitException(msg)
|
||||||
return {}
|
return {}
|
||||||
if not result.get("items"):
|
if not result.get("items"):
|
||||||
logger.warn(f"未找到 {name} 的豆瓣信息")
|
logger.warn(f"未找到 {name} 的豆瓣信息")
|
||||||
|
@ -15,3 +15,4 @@ from .tmdb import *
|
|||||||
from .transfer import *
|
from .transfer import *
|
||||||
from .file import *
|
from .file import *
|
||||||
from .filetransfer import *
|
from .filetransfer import *
|
||||||
|
from .exception import *
|
||||||
|
14
app/schemas/exception.py
Normal file
14
app/schemas/exception.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
class ImmediateException(Exception):
|
||||||
|
"""
|
||||||
|
用于立即抛出异常而不重试的特殊异常类。
|
||||||
|
当不希望使用重试机制时,可以抛出此异常。
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class APIRateLimitException(ImmediateException):
|
||||||
|
"""
|
||||||
|
用于表示API速率限制的异常类。
|
||||||
|
当API调用触发速率限制时,可以抛出此异常以立即终止操作并报告错误。
|
||||||
|
"""
|
||||||
|
pass
|
@ -6,6 +6,8 @@ from typing import Any
|
|||||||
from Crypto import Random
|
from Crypto import Random
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
|
|
||||||
|
from app.schemas.exception import ImmediateException
|
||||||
|
|
||||||
|
|
||||||
def retry(ExceptionToCheck: Any,
|
def retry(ExceptionToCheck: Any,
|
||||||
tries: int = 3, delay: int = 3, backoff: int = 2, logger: Any = None):
|
tries: int = 3, delay: int = 3, backoff: int = 2, logger: Any = None):
|
||||||
@ -23,6 +25,8 @@ def retry(ExceptionToCheck: Any,
|
|||||||
while mtries > 1:
|
while mtries > 1:
|
||||||
try:
|
try:
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
except ImmediateException:
|
||||||
|
raise
|
||||||
except ExceptionToCheck as e:
|
except ExceptionToCheck as e:
|
||||||
msg = f"{str(e)}, {mdelay} 秒后重试 ..."
|
msg = f"{str(e)}, {mdelay} 秒后重试 ..."
|
||||||
if logger:
|
if logger:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user