Merge pull request #5091 from wikrin/cached

This commit is contained in:
jxxghp
2025-11-03 09:51:37 +08:00
committed by GitHub
4 changed files with 27 additions and 101 deletions
+4
View File
@@ -1025,10 +1025,12 @@ def fresh(fresh: bool = True):
result = some_cached_function() result = some_cached_function()
""" """
token = _fresh.set(fresh) token = _fresh.set(fresh)
logger.debug(f"Setting fresh mode to {fresh}. {id(token):#x}")
try: try:
yield yield
finally: finally:
_fresh.reset(token) _fresh.reset(token)
logger.debug(f"Reset fresh mode. {id(token):#x}")
@asynccontextmanager @asynccontextmanager
async def async_fresh(fresh: bool = True): async def async_fresh(fresh: bool = True):
@@ -1040,10 +1042,12 @@ async def async_fresh(fresh: bool = True):
result = await some_async_cached_function() result = await some_async_cached_function()
""" """
token = _fresh.set(fresh) token = _fresh.set(fresh)
logger.debug(f"Setting async_fresh mode to {fresh}. {id(token):#x}")
try: try:
yield yield
finally: finally:
_fresh.reset(token) _fresh.reset(token)
logger.debug(f"Reset async_fresh mode. {id(token):#x}")
def is_fresh() -> bool: def is_fresh() -> bool:
""" """
+5 -11
View File
@@ -18,7 +18,7 @@ from starlette import status
from watchfiles import watch from watchfiles import watch
from app import schemas from app import schemas
from app.core.cache import cached from app.core.cache import fresh, async_fresh
from app.core.config import settings from app.core.config import settings
from app.core.event import eventmanager, Event from app.core.event import eventmanager, Event
from app.db.plugindata_oper import PluginDataOper from app.db.plugindata_oper import PluginDataOper
@@ -915,14 +915,10 @@ class PluginManager(metaclass=Singleton):
""" """
return list(self._running_plugins.keys()) return list(self._running_plugins.keys())
@cached(maxsize=1, ttl=1800)
def get_online_plugins(self, force: bool = False) -> List[schemas.Plugin]: def get_online_plugins(self, force: bool = False) -> List[schemas.Plugin]:
""" """
获取所有在线插件信息 获取所有在线插件信息
""" """
if force:
self.get_online_plugins.cache_clear()
if not settings.PLUGIN_MARKET: if not settings.PLUGIN_MARKET:
return [] return []
@@ -1080,7 +1076,8 @@ class PluginManager(metaclass=Singleton):
# 已安装插件 # 已安装插件
installed_apps = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or [] installed_apps = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
# 获取在线插件 # 获取在线插件
online_plugins = PluginHelper().get_plugins(market, package_version, force) with fresh(force):
online_plugins = PluginHelper().get_plugins(market, package_version)
if online_plugins is None: if online_plugins is None:
logger.warning( logger.warning(
f"获取{package_version if package_version else ''}插件库失败:{market},请检查 GitHub 网络连接") f"获取{package_version if package_version else ''}插件库失败:{market},请检查 GitHub 网络连接")
@@ -1218,15 +1215,11 @@ class PluginManager(metaclass=Singleton):
return plugin return plugin
@cached(maxsize=1, ttl=1800)
async def async_get_online_plugins(self, force: bool = False) -> List[schemas.Plugin]: async def async_get_online_plugins(self, force: bool = False) -> List[schemas.Plugin]:
""" """
异步获取所有在线插件信息 异步获取所有在线插件信息
:param force: 是否强制刷新(忽略缓存) :param force: 是否强制刷新(忽略缓存)
""" """
if force:
await self.async_get_online_plugins.cache_clear()
if not settings.PLUGIN_MARKET: if not settings.PLUGIN_MARKET:
return [] return []
@@ -1291,7 +1284,8 @@ class PluginManager(metaclass=Singleton):
# 已安装插件 # 已安装插件
installed_apps = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or [] installed_apps = SystemConfigOper().get(SystemConfigKey.UserInstalledPlugins) or []
# 获取在线插件 # 获取在线插件
online_plugins = await PluginHelper().async_get_plugins(market, package_version, force) async with async_fresh(force):
online_plugins = await PluginHelper().async_get_plugins(market, package_version)
if online_plugins is None: if online_plugins is None:
logger.warning( logger.warning(
f"获取{package_version if package_version else ''}插件库失败:{market},请检查 GitHub 网络连接") f"获取{package_version if package_version else ''}插件库失败:{market},请检查 GitHub 网络连接")
+4 -49
View File
@@ -48,34 +48,11 @@ class PluginHelper(metaclass=WeakSingleton):
if self.install_report(): if self.install_report():
self.systemconfig.set(SystemConfigKey.PluginInstallReport, "1") self.systemconfig.set(SystemConfigKey.PluginInstallReport, "1")
def get_plugins(self, repo_url: str, package_version: Optional[str] = None,
force: bool = False) -> Optional[Dict[str, dict]]:
"""
获取Github所有最新插件列表
:param repo_url: Github仓库地址
:param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本
:param force: 是否强制刷新,忽略缓存
"""
# 如果强制刷新,直接调用不带缓存的版本
if force:
return self._request_plugins(repo_url, package_version)
else:
return self._request_plugins_cached(repo_url, package_version)
@cached(maxsize=128, ttl=1800) @cached(maxsize=128, ttl=1800)
def _request_plugins_cached(self, repo_url: str, def get_plugins(self, repo_url: str,
package_version: Optional[str] = None) -> Optional[Dict[str, dict]]:
"""
获取Github所有最新插件列表(使用缓存)
:param repo_url: Github仓库地址
:param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本
"""
return self._request_plugins(repo_url, package_version)
def _request_plugins(self, repo_url: str,
package_version: Optional[str] = None) -> Optional[Dict[str, dict]]: package_version: Optional[str] = None) -> Optional[Dict[str, dict]]:
""" """
获取Github所有最新插件列表(不使用缓存) 获取Github所有最新插件列表
:param repo_url: Github仓库地址 :param repo_url: Github仓库地址
:param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本 :param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本
""" """
@@ -932,33 +909,11 @@ class PluginHelper(metaclass=WeakSingleton):
logger.error(f"[GitHub] 所有策略均请求失败,URL: {url},请检查网络连接或 GitHub 配置") logger.error(f"[GitHub] 所有策略均请求失败,URL: {url},请检查网络连接或 GitHub 配置")
return None return None
async def async_get_plugins(self, repo_url: str, package_version: Optional[str] = None,
force: bool = False) -> Optional[Dict[str, dict]]:
"""
异步获取Github所有最新插件列表
:param repo_url: Github仓库地址
:param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本
:param force: 是否强制刷新,忽略缓存
"""
if force:
return await self._async_request_plugins(repo_url, package_version)
else:
return await self._async_request_plugins_cached(repo_url, package_version)
@cached(maxsize=128, ttl=1800) @cached(maxsize=128, ttl=1800)
async def _async_request_plugins_cached(self, repo_url: str, async def async_get_plugins(self, repo_url: str,
package_version: Optional[str] = None) -> Optional[Dict[str, dict]]:
"""
获取Github所有最新插件列表(使用缓存)
:param repo_url: Github仓库地址
:param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本
"""
return await self._async_request_plugins(repo_url, package_version)
async def _async_request_plugins(self, repo_url: str,
package_version: Optional[str] = None) -> Optional[Dict[str, dict]]: package_version: Optional[str] = None) -> Optional[Dict[str, dict]]:
""" """
异步获取Github所有最新插件列表(不使用缓存) 异步获取Github所有最新插件列表
:param repo_url: Github仓库地址 :param repo_url: Github仓库地址
:param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本 :param package_version: 首选插件版本 (如 "v2", "v3"),如果不指定则获取 v1 版本
""" """
+14 -41
View File
@@ -8,7 +8,7 @@ from datetime import datetime
import requests import requests
import requests.exceptions import requests.exceptions
from app.core.cache import cached from app.core.cache import cached, fresh, async_fresh
from app.core.config import settings from app.core.config import settings
from app.utils.http import RequestUtils, AsyncRequestUtils from app.utils.http import RequestUtils, AsyncRequestUtils
from .exceptions import TMDbException from .exceptions import TMDbException
@@ -24,7 +24,6 @@ class TMDb(object):
self._session_id = None self._session_id = None
self._session = session self._session = session
self._wait_on_rate_limit = True self._wait_on_rate_limit = True
self._debug_enabled = False
self._proxies = settings.PROXY self._proxies = settings.PROXY
self._domain = settings.TMDB_API_DOMAIN self._domain = settings.TMDB_API_DOMAIN
self._page = None self._page = None
@@ -109,28 +108,8 @@ class TMDb(object):
def wait_on_rate_limit(self, wait_on_rate_limit): def wait_on_rate_limit(self, wait_on_rate_limit):
self._wait_on_rate_limit = bool(wait_on_rate_limit) self._wait_on_rate_limit = bool(wait_on_rate_limit)
@property
def debug(self):
return self._debug_enabled
@debug.setter
def debug(self, debug):
self._debug_enabled = bool(debug)
@cached(maxsize=settings.CONF.tmdb, ttl=settings.CONF.meta, skip_none=True) @cached(maxsize=settings.CONF.tmdb, ttl=settings.CONF.meta, skip_none=True)
def cached_request(self, method, url, data, json, def request(self, method, url, data, json, **kwargs):
_ts=datetime.strftime(datetime.now(), '%Y%m%d')):
return self.request(method, url, data, json)
@cached(maxsize=settings.CONF.tmdb, ttl=settings.CONF.meta, skip_none=True)
async def async_cached_request(self, method, url, data, json,
_ts=datetime.strftime(datetime.now(), '%Y%m%d')):
if self.__clear_async_cache__:
self.__clear_async_cache__ = False
await self.async_cached_request.cache_clear()
return await self.async_request(method, url, data, json)
def request(self, method, url, data, json):
if method == "GET": if method == "GET":
req = self._req.get_res(url, params=data, json=json) req = self._req.get_res(url, params=data, json=json)
else: else:
@@ -139,7 +118,8 @@ class TMDb(object):
raise TMDbException("无法连接TheMovieDb,请检查网络连接!") raise TMDbException("无法连接TheMovieDb,请检查网络连接!")
return req return req
async def async_request(self, method, url, data, json): @cached(maxsize=settings.CONF.tmdb, ttl=settings.CONF.meta, skip_none=True)
async def async_request(self, method, url, data, json, **kwargs):
if method == "GET": if method == "GET":
req = await self._async_req.get_res(url, params=data, json=json) req = await self._async_req.get_res(url, params=data, json=json)
else: else:
@@ -150,7 +130,7 @@ class TMDb(object):
def cache_clear(self): def cache_clear(self):
self.__clear_async_cache__ = True self.__clear_async_cache__ = True
return self.cached_request.cache_clear() return self.request.cache_clear()
def _validate_api_key(self): def _validate_api_key(self):
if self.api_key is None or self.api_key == "": if self.api_key is None or self.api_key == "":
@@ -194,13 +174,6 @@ class TMDb(object):
if "total_pages" in json_data: if "total_pages" in json_data:
self._total_pages = json_data["total_pages"] self._total_pages = json_data["total_pages"]
if self.debug:
logger.info(json_data)
if is_async:
logger.info(self.async_cached_request.cache_info())
else:
logger.info(self.cached_request.cache_info())
@staticmethod @staticmethod
def _handle_errors(json_data): def _handle_errors(json_data):
if "errors" in json_data: if "errors" in json_data:
@@ -214,11 +187,9 @@ class TMDb(object):
self._validate_api_key() self._validate_api_key()
url = self._build_url(action, params) url = self._build_url(action, params)
if call_cached and method != "POST": with fresh(not call_cached or method == "POST"):
req = self.cached_request(method, url, data, json, req = self.request(method, url, data, json,
_ts=datetime.strftime(datetime.now(), '%Y%m%d')) _ts=datetime.strftime(datetime.now(), '%Y%m%d'))
else:
req = self.request(method, url, data, json)
if req is None: if req is None:
return None return None
@@ -244,11 +215,13 @@ class TMDb(object):
self._validate_api_key() self._validate_api_key()
url = self._build_url(action, params) url = self._build_url(action, params)
if call_cached and method != "POST": if self.__clear_async_cache__:
req = await self.async_cached_request(method, url, data, json, self.__clear_async_cache__ = False
_ts=datetime.strftime(datetime.now(), '%Y%m%d')) await self.async_request.cache_clear()
else:
req = await self.async_request(method, url, data, json) async with async_fresh(not call_cached or method == "POST"):
req = await self.async_request(method, url, data, json,
_ts=datetime.strftime(datetime.now(), '%Y%m%d'))
if req is None: if req is None:
return None return None