mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-08 17:08:35 +08:00
feat:增加插件和日历的自动缓存
This commit is contained in:
@@ -1184,6 +1184,33 @@ class SubscribeChain(ChainBase):
|
|||||||
logger.error(f'follow用户分享订阅 {title} 添加失败:{message}')
|
logger.error(f'follow用户分享订阅 {title} 添加失败:{message}')
|
||||||
logger.info(f'follow用户分享订阅刷新完成,共添加 {success_count} 个订阅')
|
logger.info(f'follow用户分享订阅刷新完成,共添加 {success_count} 个订阅')
|
||||||
|
|
||||||
|
async def cache_calendar(self):
|
||||||
|
"""
|
||||||
|
预缓存订阅日历,实际上就是查询一遍所有订阅的媒体信息
|
||||||
|
前端请示是异常的,所以需要使用异步缓存方法
|
||||||
|
"""
|
||||||
|
logger.info(f'开始预缓存订阅日历 ...')
|
||||||
|
for subscribe in await SubscribeOper().async_list():
|
||||||
|
if global_vars.is_system_stopped:
|
||||||
|
break
|
||||||
|
try:
|
||||||
|
mtype = MediaType(subscribe.type)
|
||||||
|
except ValueError:
|
||||||
|
logger.error(f'订阅 {subscribe.name} 类型错误:{subscribe.type}')
|
||||||
|
continue
|
||||||
|
# 识别媒体信息
|
||||||
|
mediainfo: MediaInfo = await self.async_recognize_media(mtype=mtype,
|
||||||
|
tmdbid=subscribe.tmdbid,
|
||||||
|
doubanid=subscribe.doubanid,
|
||||||
|
bangumiid=subscribe.bangumiid,
|
||||||
|
episode_group=subscribe.episode_group,
|
||||||
|
cache=False)
|
||||||
|
if not mediainfo:
|
||||||
|
logger.warn(
|
||||||
|
f'未识别到媒体信息,标题:{subscribe.name},tmdbid:{subscribe.tmdbid},doubanid:{subscribe.doubanid}')
|
||||||
|
continue
|
||||||
|
logger.info(f'订阅日历预缓存完成')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __update_subscribe_note(subscribe: Subscribe, downloads: Optional[List[Context]]):
|
def __update_subscribe_note(subscribe: Subscribe, downloads: Optional[List[Context]]):
|
||||||
"""
|
"""
|
||||||
|
|||||||
+2
-2
@@ -1393,7 +1393,7 @@ class TTLCache(CacheProxy):
|
|||||||
def __init__(self,
|
def __init__(self,
|
||||||
region: Optional[str] = DEFAULT_CACHE_REGION,
|
region: Optional[str] = DEFAULT_CACHE_REGION,
|
||||||
maxsize: Optional[int] = DEFAULT_CACHE_SIZE,
|
maxsize: Optional[int] = DEFAULT_CACHE_SIZE,
|
||||||
ttl: Optional[int]= DEFAULT_CACHE_TTL):
|
ttl: Optional[int] = DEFAULT_CACHE_TTL):
|
||||||
"""
|
"""
|
||||||
初始化 TTL 缓存
|
初始化 TTL 缓存
|
||||||
|
|
||||||
@@ -1412,7 +1412,7 @@ class LRUCache(CacheProxy):
|
|||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
region: Optional[str] = DEFAULT_CACHE_REGION,
|
region: Optional[str] = DEFAULT_CACHE_REGION,
|
||||||
maxsize: Optional[int]= DEFAULT_CACHE_SIZE
|
maxsize: Optional[int] = DEFAULT_CACHE_SIZE
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
初始化 LRU 缓存
|
初始化 LRU 缓存
|
||||||
|
|||||||
@@ -1189,6 +1189,7 @@ class PluginManager(metaclass=Singleton):
|
|||||||
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: 是否强制刷新(忽略缓存)
|
||||||
"""
|
"""
|
||||||
if not settings.PLUGIN_MARKET:
|
if not settings.PLUGIN_MARKET:
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -119,6 +119,14 @@ class SubscribeOper(DbOper):
|
|||||||
return Subscribe.get_by_state(self._db, state)
|
return Subscribe.get_by_state(self._db, state)
|
||||||
return Subscribe.list(self._db)
|
return Subscribe.list(self._db)
|
||||||
|
|
||||||
|
async def async_list(self, state: Optional[str] = None) -> List[Subscribe]:
|
||||||
|
"""
|
||||||
|
异步获取订阅列表
|
||||||
|
"""
|
||||||
|
if state:
|
||||||
|
return await Subscribe.async_get_by_state(self._db, state)
|
||||||
|
return await Subscribe.async_list(self._db)
|
||||||
|
|
||||||
def delete(self, sid: int):
|
def delete(self, sid: int):
|
||||||
"""
|
"""
|
||||||
删除订阅
|
删除订阅
|
||||||
|
|||||||
@@ -911,10 +911,10 @@ class PluginHelper(metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
# 异步版本直接调用不带缓存的版本(缓存在异步环境下可能有并发问题)
|
# 异步版本直接调用不带缓存的版本(缓存在异步环境下可能有并发问题)
|
||||||
if force:
|
if force:
|
||||||
return await self._async_get_plugins_uncached(repo_url, package_version)
|
await self._async_get_plugins_cached.cache_clear()
|
||||||
return await self._async_get_plugins_cached(repo_url, package_version)
|
return await self._async_get_plugins_cached(repo_url, package_version)
|
||||||
|
|
||||||
@cached(maxsize=64, ttl=1800)
|
@cached(maxsize=128, ttl=1800)
|
||||||
async def _async_get_plugins_cached(self, repo_url: str,
|
async def _async_get_plugins_cached(self, repo_url: str,
|
||||||
package_version: Optional[str] = None) -> Optional[Dict[str, dict]]:
|
package_version: Optional[str] = None) -> Optional[Dict[str, dict]]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
+51
-5
@@ -1,3 +1,4 @@
|
|||||||
|
import inspect
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
@@ -27,6 +28,7 @@ from app.helper.wallpaper import WallpaperHelper
|
|||||||
from app.log import logger
|
from app.log import logger
|
||||||
from app.schemas import Notification, NotificationType, Workflow, ConfigChangeEventData
|
from app.schemas import Notification, NotificationType, Workflow, ConfigChangeEventData
|
||||||
from app.schemas.types import EventType, SystemConfigKey
|
from app.schemas.types import EventType, SystemConfigKey
|
||||||
|
from app.utils.asyncio import AsyncUtils
|
||||||
from app.utils.singleton import Singleton
|
from app.utils.singleton import Singleton
|
||||||
from app.utils.timer import TimerUtils
|
from app.utils.timer import TimerUtils
|
||||||
|
|
||||||
@@ -162,6 +164,19 @@ class Scheduler(metaclass=Singleton):
|
|||||||
"name": "推荐缓存",
|
"name": "推荐缓存",
|
||||||
"func": RecommendChain().refresh_recommend,
|
"func": RecommendChain().refresh_recommend,
|
||||||
"running": False,
|
"running": False,
|
||||||
|
},
|
||||||
|
"plugin_market_refresh": {
|
||||||
|
"name": "插件市场缓存",
|
||||||
|
"func": PluginManager().async_get_online_plugins,
|
||||||
|
"running": False,
|
||||||
|
"kwargs": {
|
||||||
|
"force": True
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"subscribe_calendar_cache": {
|
||||||
|
"name": "订阅日历缓存",
|
||||||
|
"func": SubscribeChain().cache_calendar,
|
||||||
|
"running": False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +195,7 @@ class Scheduler(metaclass=Singleton):
|
|||||||
id="cookiecloud",
|
id="cookiecloud",
|
||||||
name="同步CookieCloud站点",
|
name="同步CookieCloud站点",
|
||||||
minutes=int(settings.COOKIECLOUD_INTERVAL),
|
minutes=int(settings.COOKIECLOUD_INTERVAL),
|
||||||
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(minutes=1),
|
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(minutes=5),
|
||||||
kwargs={
|
kwargs={
|
||||||
'job_id': 'cookiecloud'
|
'job_id': 'cookiecloud'
|
||||||
}
|
}
|
||||||
@@ -195,7 +210,7 @@ class Scheduler(metaclass=Singleton):
|
|||||||
id="mediaserver_sync",
|
id="mediaserver_sync",
|
||||||
name="同步媒体服务器",
|
name="同步媒体服务器",
|
||||||
hours=int(settings.MEDIASERVER_SYNC_INTERVAL),
|
hours=int(settings.MEDIASERVER_SYNC_INTERVAL),
|
||||||
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(minutes=5),
|
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(minutes=10),
|
||||||
kwargs={
|
kwargs={
|
||||||
'job_id': 'mediaserver_sync'
|
'job_id': 'mediaserver_sync'
|
||||||
}
|
}
|
||||||
@@ -301,7 +316,7 @@ class Scheduler(metaclass=Singleton):
|
|||||||
id="random_wallpager",
|
id="random_wallpager",
|
||||||
name="壁纸缓存",
|
name="壁纸缓存",
|
||||||
minutes=30,
|
minutes=30,
|
||||||
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(seconds=3),
|
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(seconds=1),
|
||||||
kwargs={
|
kwargs={
|
||||||
'job_id': 'random_wallpager'
|
'job_id': 'random_wallpager'
|
||||||
}
|
}
|
||||||
@@ -363,12 +378,37 @@ class Scheduler(metaclass=Singleton):
|
|||||||
id="recommend_refresh",
|
id="recommend_refresh",
|
||||||
name="推荐缓存",
|
name="推荐缓存",
|
||||||
hours=24,
|
hours=24,
|
||||||
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(seconds=3),
|
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(seconds=5),
|
||||||
kwargs={
|
kwargs={
|
||||||
'job_id': 'recommend_refresh'
|
'job_id': 'recommend_refresh'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 插件市场缓存
|
||||||
|
self._scheduler.add_job(
|
||||||
|
self.start,
|
||||||
|
"interval",
|
||||||
|
id="plugin_market_refresh",
|
||||||
|
name="插件市场缓存",
|
||||||
|
minutes=30,
|
||||||
|
kwargs={
|
||||||
|
'job_id': 'plugin_market_refresh'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# 订阅日历缓存
|
||||||
|
self._scheduler.add_job(
|
||||||
|
self.start,
|
||||||
|
"interval",
|
||||||
|
id="subscribe_calendar_cache",
|
||||||
|
name="订阅日历缓存",
|
||||||
|
hours=6,
|
||||||
|
next_run_time=datetime.now(pytz.timezone(settings.TZ)) + timedelta(minutes=2),
|
||||||
|
kwargs={
|
||||||
|
'job_id': 'subscribe_calendar_cache'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# 初始化工作流服务
|
# 初始化工作流服务
|
||||||
self.init_workflow_jobs()
|
self.init_workflow_jobs()
|
||||||
|
|
||||||
@@ -417,7 +457,13 @@ class Scheduler(metaclass=Singleton):
|
|||||||
try:
|
try:
|
||||||
if not kwargs:
|
if not kwargs:
|
||||||
kwargs = job.get("kwargs") or {}
|
kwargs = job.get("kwargs") or {}
|
||||||
job["func"](*args, **kwargs)
|
func = job.get("func")
|
||||||
|
if not func:
|
||||||
|
return
|
||||||
|
if inspect.iscoroutinefunction(func):
|
||||||
|
AsyncUtils.run_async_in_executor(func(*args, **kwargs))
|
||||||
|
else:
|
||||||
|
job["func"](*args, **kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"定时任务 {job.get('name')} 执行失败:{str(e)} - {traceback.format_exc()}")
|
logger.error(f"定时任务 {job.get('name')} 执行失败:{str(e)} - {traceback.format_exc()}")
|
||||||
MessageHelper().put(title=f"{job.get('name')} 执行失败",
|
MessageHelper().put(title=f"{job.get('name')} 执行失败",
|
||||||
|
|||||||
Reference in New Issue
Block a user