From 6267b3f6707b06b3106c37ff036fd3926b5046c0 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 30 Jun 2024 11:41:00 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20run=5Fmodule=E6=94=AF=E6=8C=81raise?= =?UTF-8?q?=5Fexception?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/chain/__init__.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/chain/__init__.py b/app/chain/__init__.py index 6e6ebbe4..156eda94 100644 --- a/app/chain/__init__.py +++ b/app/chain/__init__.py @@ -10,8 +10,7 @@ from ruamel.yaml import CommentedMap from transmission_rpc import File from app.core.config import settings -from app.core.context import Context -from app.core.context import MediaInfo, TorrentInfo +from app.core.context import Context, MediaInfo, TorrentInfo from app.core.event import EventManager from app.core.meta import MetaBase from app.core.module import ModuleManager @@ -79,6 +78,7 @@ class ChainBase(metaclass=ABCMeta): def run_module(self, method: str, *args, **kwargs) -> Any: """ 运行包含该方法的所有模块,然后返回结果 + 当kwargs包含命名参数raise_exception时,如模块方法抛出异常且raise_exception为True,则同步抛出异常 """ def is_result_empty(ret): @@ -117,6 +117,8 @@ class ChainBase(metaclass=ABCMeta): # 中止继续执行 break except Exception as err: + if kwargs.get("raise_exception"): + raise logger.error( f"运行模块 {module_id}.{method} 出错:{str(err)}\n{traceback.format_exc()}") self.messagehelper.put(title=f"{module_name}发生了错误", @@ -166,7 +168,8 @@ class ChainBase(metaclass=ABCMeta): tmdbid=tmdbid, doubanid=doubanid, bangumiid=bangumiid, cache=cache) 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: 标题 @@ -174,9 +177,10 @@ class ChainBase(metaclass=ABCMeta): :param mtype: 类型 :param year: 年份 :param season: 季 + :param raise_exception: 触发速率限制时是否抛出异常 """ 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, year: str = None, season: int = None) -> Optional[dict]: @@ -214,14 +218,15 @@ class ChainBase(metaclass=ABCMeta): image_prefix=image_prefix, image_type=image_type, 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 mtype: 媒体类型 :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]: """ From 0f7a7ef44f76c8668a6b2ba295dcf455fb9c76a9 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 30 Jun 2024 11:43:11 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ImmediateExceptio?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/schemas/exception.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/schemas/exception.py diff --git a/app/schemas/exception.py b/app/schemas/exception.py new file mode 100644 index 00000000..8a536d71 --- /dev/null +++ b/app/schemas/exception.py @@ -0,0 +1,6 @@ +class ImmediateException(Exception): + """ + 用于立即抛出异常而不重试的特殊异常类。 + 当不希望使用重试机制时,可以抛出此异常。 + """ + pass From 57cdb573312c2fae28f7fcf0b06aa00df871739d Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 30 Jun 2024 11:44:33 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20retry=E6=94=AF=E6=8C=81=E7=AB=8B?= =?UTF-8?q?=E5=8D=B3=E6=8A=9B=E5=87=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/utils/common.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/utils/common.py b/app/utils/common.py index 5708fbfd..497ad15b 100644 --- a/app/utils/common.py +++ b/app/utils/common.py @@ -6,6 +6,8 @@ from typing import Any from Crypto import Random from Crypto.Cipher import AES +from app.schemas.exception import ImmediateException + def retry(ExceptionToCheck: Any, tries: int = 3, delay: int = 3, backoff: int = 2, logger: Any = None): @@ -23,6 +25,8 @@ def retry(ExceptionToCheck: Any, while mtries > 1: try: return f(*args, **kwargs) + except ImmediateException: + raise except ExceptionToCheck as e: msg = f"{str(e)}, {mdelay} 秒后重试 ..." if logger: From b9d91c5cd7291bb9c5fd017df195f2914ae2f710 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 30 Jun 2024 11:48:29 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20DoubanModule=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=E9=99=90=E6=B5=81=E6=97=B6=E6=94=AF=E6=8C=81=E7=AB=8B=E5=8D=B3?= =?UTF-8?q?=E6=8A=9B=E5=87=BA=E9=99=90=E6=B5=81=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/modules/douban/__init__.py | 23 ++++++++++++++++++----- app/schemas/exception.py | 8 ++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/app/modules/douban/__init__.py b/app/modules/douban/__init__.py index f63ed112..337ec39f 100644 --- a/app/modules/douban/__init__.py +++ b/app/modules/douban/__init__.py @@ -15,6 +15,7 @@ from app.modules.douban.apiv2 import DoubanApi from app.modules.douban.douban_cache import DoubanCache from app.modules.douban.scraper import DoubanScraper from app.schemas import MediaPerson +from app.schemas.exception import APIRateLimitException from app.schemas.types import MediaType from app.utils.common import retry from app.utils.http import RequestUtils @@ -147,11 +148,12 @@ class DoubanModule(_ModuleBase): 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 mtype: 媒体类型 + :param raise_exception: 触发速率限制时是否抛出异常 :return: 豆瓣信息 """ """ @@ -427,7 +429,10 @@ class DoubanModule(_ModuleBase): info = self.doubanapi.tv_detail(doubanid) if info: 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 celebrities = self.doubanapi.tv_celebrities(doubanid) if celebrities: @@ -442,7 +447,10 @@ class DoubanModule(_ModuleBase): info = self.doubanapi.movie_detail(doubanid) if info: 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 celebrities = self.doubanapi.movie_celebrities(doubanid) if celebrities: @@ -601,7 +609,8 @@ class DoubanModule(_ModuleBase): @retry(Exception, 5, 3, 3, logger=logger) 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: 名称 @@ -609,6 +618,7 @@ class DoubanModule(_ModuleBase): :param mtype: 类型 :param year: 年份 :param season: 季号 + :param raise_exception: 触发速率限制时是否抛出异常 """ if imdbid: # 优先使用IMDBID查询 @@ -629,7 +639,10 @@ class DoubanModule(_ModuleBase): return {} # 触发rate limit 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 {} if not result.get("items"): logger.warn(f"未找到 {name} 的豆瓣信息") diff --git a/app/schemas/exception.py b/app/schemas/exception.py index 8a536d71..63ef784e 100644 --- a/app/schemas/exception.py +++ b/app/schemas/exception.py @@ -4,3 +4,11 @@ class ImmediateException(Exception): 当不希望使用重试机制时,可以抛出此异常。 """ pass + + +class APIRateLimitException(ImmediateException): + """ + 用于表示API速率限制的异常类。 + 当API调用触发速率限制时,可以抛出此异常以立即终止操作并报告错误。 + """ + pass From e56d31fedcf903a060f3dc61a0901f8e7ef47ed8 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Sun, 30 Jun 2024 11:50:26 +0800 Subject: [PATCH 5/5] fix exception --- app/schemas/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/schemas/__init__.py b/app/schemas/__init__.py index eb421d1b..cae4e8c1 100644 --- a/app/schemas/__init__.py +++ b/app/schemas/__init__.py @@ -15,3 +15,4 @@ from .tmdb import * from .transfer import * from .file import * from .filetransfer import * +from .exception import *