mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-06-09 09:40:06 +08:00
feat(cache): 同步/异步函数可共享缓存
- 缓存键支持自定义命名,使异步与同步函数可共享缓存结果 - 内存缓存改为类变量,实现多个cache装饰器共享同一缓存空间 - 重构AsyncMemoryBackend,减少重复代码 - 补齐部分模块的缓存清理功能
This commit is contained in:
@@ -290,3 +290,11 @@ class BangumiModule(_ModuleBase):
|
||||
if infos:
|
||||
return [MediaInfo(bangumi_info=info) for info in infos]
|
||||
return []
|
||||
|
||||
def clear_cache(self):
|
||||
"""
|
||||
清除缓存
|
||||
"""
|
||||
logger.info(f"开始清除{self.get_name()}缓存 ...")
|
||||
self.bangumiapi.clear_cache()
|
||||
logger.info(f"{self.get_name()}缓存清除完成")
|
||||
|
||||
@@ -31,7 +31,7 @@ class BangumiApi(object):
|
||||
self._req = RequestUtils(ua=settings.NORMAL_USER_AGENT, session=self._session)
|
||||
self._async_req = AsyncRequestUtils(ua=settings.NORMAL_USER_AGENT)
|
||||
|
||||
@cached(maxsize=settings.CONF.bangumi, ttl=settings.CONF.meta)
|
||||
@cached(maxsize=settings.CONF.bangumi, ttl=settings.CONF.meta, shared_key="get")
|
||||
def __invoke(self, url, key: Optional[str] = None, **kwargs):
|
||||
req_url = self._base_url + url
|
||||
params = {}
|
||||
@@ -47,7 +47,7 @@ class BangumiApi(object):
|
||||
print(e)
|
||||
return None
|
||||
|
||||
@cached(maxsize=settings.CONF.bangumi, ttl=settings.CONF.meta)
|
||||
@cached(maxsize=settings.CONF.bangumi, ttl=settings.CONF.meta, shared_key="get")
|
||||
async def __async_invoke(self, url, key: Optional[str] = None, **kwargs):
|
||||
req_url = self._base_url + url
|
||||
params = {}
|
||||
@@ -300,6 +300,12 @@ class BangumiApi(object):
|
||||
key="data",
|
||||
_ts=datetime.strftime(datetime.now(), '%Y%m%d'), **kwargs)
|
||||
|
||||
def clear_cache(self):
|
||||
"""
|
||||
清除缓存
|
||||
"""
|
||||
self.__invoke.cache_clear()
|
||||
|
||||
def close(self):
|
||||
if self._session:
|
||||
self._session.close()
|
||||
|
||||
@@ -154,7 +154,6 @@ class DoubanApi(metaclass=WeakSingleton):
|
||||
_api_url = "https://api.douban.com/v2"
|
||||
|
||||
def __init__(self):
|
||||
self.__clear_async_cache__ = False
|
||||
self._session = requests.Session()
|
||||
|
||||
@classmethod
|
||||
@@ -225,7 +224,7 @@ class DoubanApi(metaclass=WeakSingleton):
|
||||
"""
|
||||
return resp.json() if resp is not None else None
|
||||
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True)
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True, shared_key="get")
|
||||
def __invoke(self, url: str, **kwargs) -> dict:
|
||||
"""
|
||||
GET请求
|
||||
@@ -237,14 +236,11 @@ class DoubanApi(metaclass=WeakSingleton):
|
||||
).get_res(url=req_url, params=params)
|
||||
return self._handle_response(resp)
|
||||
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True)
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True, shared_key="get")
|
||||
async def __async_invoke(self, url: str, **kwargs) -> dict:
|
||||
"""
|
||||
GET请求(异步版本)
|
||||
"""
|
||||
if self.__clear_async_cache__:
|
||||
self.__clear_async_cache__ = False
|
||||
await self.__async_invoke.cache_clear()
|
||||
req_url, params = self._prepare_get_request(url, **kwargs)
|
||||
resp = await AsyncRequestUtils(
|
||||
ua=choice(self._user_agents)
|
||||
@@ -263,7 +259,7 @@ class DoubanApi(metaclass=WeakSingleton):
|
||||
params.pop('_ts')
|
||||
return req_url, params
|
||||
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True)
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True, shared_key="post")
|
||||
def __post(self, url: str, **kwargs) -> dict:
|
||||
"""
|
||||
POST请求
|
||||
@@ -285,7 +281,7 @@ class DoubanApi(metaclass=WeakSingleton):
|
||||
).post_res(url=req_url, data=params)
|
||||
return self._handle_response(resp)
|
||||
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True)
|
||||
@cached(maxsize=settings.CONF.douban, ttl=settings.CONF.meta, skip_none=True, shared_key="post")
|
||||
async def __async_post(self, url: str, **kwargs) -> dict:
|
||||
"""
|
||||
POST请求(异步版本)
|
||||
@@ -865,7 +861,7 @@ class DoubanApi(metaclass=WeakSingleton):
|
||||
清空LRU缓存
|
||||
"""
|
||||
self.__invoke.cache_clear()
|
||||
self.__clear_async_cache__ = True
|
||||
self.__post.cache_clear()
|
||||
|
||||
def close(self):
|
||||
if self._session:
|
||||
|
||||
@@ -440,7 +440,7 @@ class FanartModule(_ModuleBase):
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
@cached(maxsize=settings.CONF.fanart, ttl=settings.CONF.meta)
|
||||
@cached(maxsize=settings.CONF.fanart, ttl=settings.CONF.meta, shared_key="get")
|
||||
def __request_fanart(cls, media_type: MediaType, queryid: Union[str, int]) -> Optional[dict]:
|
||||
if media_type == MediaType.MOVIE:
|
||||
image_url = cls._movie_url % queryid
|
||||
@@ -456,3 +456,11 @@ class FanartModule(_ModuleBase):
|
||||
except Exception as err:
|
||||
logger.error(f"获取{queryid}的Fanart图片失败:{str(err)}")
|
||||
return None
|
||||
|
||||
def clear_cache(self):
|
||||
"""
|
||||
清除缓存
|
||||
"""
|
||||
logger.info(f"开始清除{self.get_name()}缓存 ...")
|
||||
self.__request_fanart.cache_clear()
|
||||
logger.info(f"{self.get_name()}缓存清除完成")
|
||||
|
||||
@@ -29,7 +29,7 @@ class TNodeSpider(metaclass=SingletonClass):
|
||||
self._ua = indexer.get('ua')
|
||||
self._timeout = indexer.get('timeout') or 15
|
||||
|
||||
@cached(region="indexer_spider", maxsize=1, ttl=60 * 60 * 24, skip_empty=True)
|
||||
@cached(region="indexer_spider", maxsize=1, ttl=60 * 60 * 24, skip_empty=True, shared_key="get_token")
|
||||
def __get_token(self) -> Optional[str]:
|
||||
if not self._domain:
|
||||
return
|
||||
@@ -43,7 +43,7 @@ class TNodeSpider(metaclass=SingletonClass):
|
||||
return csrf_token.group(1)
|
||||
return None
|
||||
|
||||
@cached(region="indexer_spider", maxsize=1, ttl=60 * 60 * 24, skip_empty=True)
|
||||
@cached(region="indexer_spider", maxsize=1, ttl=60 * 60 * 24, skip_empty=True, shared_key="get_token")
|
||||
async def __async_get_token(self) -> Optional[str]:
|
||||
if not self._domain:
|
||||
return
|
||||
|
||||
@@ -1625,6 +1625,9 @@ class TmdbApi:
|
||||
"""
|
||||
清除缓存
|
||||
"""
|
||||
self.match_web.cache_clear()
|
||||
self.discover.discover_movies.cache_clear()
|
||||
self.discover.discover_tv_shows.cache_clear()
|
||||
self.tmdb.cache_clear()
|
||||
|
||||
# 私有异步方法
|
||||
|
||||
@@ -40,8 +40,6 @@ class TMDb(object):
|
||||
self._reset = None
|
||||
self._timeout = 15
|
||||
|
||||
self.__clear_async_cache__ = False
|
||||
|
||||
@property
|
||||
def page(self):
|
||||
return self._page
|
||||
@@ -129,7 +127,6 @@ class TMDb(object):
|
||||
return req
|
||||
|
||||
def cache_clear(self):
|
||||
self.__clear_async_cache__ = True
|
||||
return self.request.cache_clear()
|
||||
|
||||
def _validate_api_key(self):
|
||||
@@ -200,7 +197,7 @@ class TMDb(object):
|
||||
if rate_limit_result:
|
||||
logger.warning("达到请求频率限制,将在 %d 秒后重试..." % rate_limit_result)
|
||||
time.sleep(rate_limit_result)
|
||||
return self._request_obj(action, params, call_cached, method, data, json, key)
|
||||
return self._request_obj(action, params, False, method, data, json, key)
|
||||
|
||||
json_data = req.json()
|
||||
self._process_json_response(json_data, is_async=False)
|
||||
@@ -215,10 +212,6 @@ class TMDb(object):
|
||||
self._validate_api_key()
|
||||
url = self._build_url(action, params)
|
||||
|
||||
if self.__clear_async_cache__:
|
||||
self.__clear_async_cache__ = False
|
||||
await self.async_request.cache_clear()
|
||||
|
||||
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'))
|
||||
@@ -232,7 +225,7 @@ class TMDb(object):
|
||||
if rate_limit_result:
|
||||
logger.warning("达到请求频率限制,将在 %d 秒后重试..." % rate_limit_result)
|
||||
await asyncio.sleep(rate_limit_result)
|
||||
return await self._async_request_obj(action, params, call_cached, method, data, json, key)
|
||||
return await self._async_request_obj(action, params, False, method, data, json, key)
|
||||
|
||||
json_data = req.json()
|
||||
self._process_json_response(json_data, is_async=True)
|
||||
|
||||
@@ -162,3 +162,12 @@ class TheTvDbModule(_ModuleBase):
|
||||
except Exception as err:
|
||||
logger.error(f"用标题搜索TVDB剧集失败 ({title}): {str(err)}")
|
||||
return []
|
||||
|
||||
def clear_cache(self):
|
||||
"""
|
||||
清除缓存
|
||||
"""
|
||||
logger.info(f"开始清除{self.get_name()}缓存 ...")
|
||||
if tvdb := self.tvdb:
|
||||
tvdb.clear_cache()
|
||||
logger.info(f"{self.get_name()}缓存清除完成")
|
||||
|
||||
@@ -618,3 +618,9 @@ class TVDB:
|
||||
"""
|
||||
url = self.url.construct('user/favorites')
|
||||
return self.request.make_request(url)
|
||||
|
||||
def clear_cache(self):
|
||||
"""
|
||||
清除缓存
|
||||
"""
|
||||
self.request.make_request.cache_clear()
|
||||
|
||||
Reference in New Issue
Block a user