mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/jxxghp/MoviePilot.git
synced 2026-09-20 08:03:34 +08:00
fix(scheduler): disable wallpaper cache without wallpaper
This commit is contained in:
@@ -183,6 +183,7 @@ class SchedulerRuntimeConfig:
|
||||
site_link: str | None
|
||||
auto_update: bool = False
|
||||
auto_update_resource: bool = True
|
||||
wallpaper: str = ""
|
||||
|
||||
@property
|
||||
def update_check_enabled(self) -> bool:
|
||||
|
||||
@@ -184,6 +184,10 @@ class WallpaperHelper(metaclass=Singleton):
|
||||
壁纸帮助类
|
||||
"""
|
||||
|
||||
def clear_cache(self) -> None:
|
||||
"""清除全部壁纸来源缓存,使壁纸配置变更即时生效。"""
|
||||
_clear_wallpaper_caches()
|
||||
|
||||
def get_wallpaper(self) -> Optional[str]:
|
||||
"""
|
||||
获取登录页面壁纸
|
||||
|
||||
@@ -62,6 +62,16 @@ def _subscription_search_job_specs(
|
||||
)
|
||||
|
||||
|
||||
def _wallpaper_job_specs(
|
||||
services: SchedulerServices,
|
||||
wallpaper: str,
|
||||
) -> tuple[JobSpec, ...]:
|
||||
"""仅在启用壁纸时返回壁纸缓存任务声明。"""
|
||||
if not wallpaper:
|
||||
return ()
|
||||
return (JobSpec("random_wallpager", "壁纸缓存", services.get_wallpapers, "image"),)
|
||||
|
||||
|
||||
class SchedulerCatalogOwner(_SchedulerOwnerBase):
|
||||
"""调度器静态任务目录与 APScheduler 投影。"""
|
||||
|
||||
@@ -196,7 +206,7 @@ class SchedulerCatalogOwner(_SchedulerOwnerBase):
|
||||
JobSpec("data_cleanup", "数据表清理", services.cleanup_data, "database"),
|
||||
JobSpec("user_auth", "用户认证检查", self.user_auth, "security"),
|
||||
JobSpec("scheduler_job", "公共定时服务", services.run_modules, "module"),
|
||||
JobSpec("random_wallpager", "壁纸缓存", services.get_wallpapers, "image"),
|
||||
*_wallpaper_job_specs(services, config.wallpaper),
|
||||
JobSpec("sitedata_refresh", "站点数据刷新", services.refresh_site_data, "site"),
|
||||
JobSpec("recommend_refresh", "推荐缓存", services.refresh_recommend, "recommend"),
|
||||
JobSpec(
|
||||
@@ -360,16 +370,17 @@ class SchedulerCatalogOwner(_SchedulerOwnerBase):
|
||||
kwargs={"job_id": "transfer"},
|
||||
)
|
||||
|
||||
# 后台刷新TMDB壁纸
|
||||
self._scheduler.add_job(
|
||||
self.start,
|
||||
"interval",
|
||||
id="random_wallpager",
|
||||
name="壁纸缓存",
|
||||
minutes=30,
|
||||
next_run_time=datetime.now(pytz.timezone(config.timezone)) + timedelta(seconds=1),
|
||||
kwargs={"job_id": "random_wallpager"},
|
||||
)
|
||||
# 仅在启用壁纸时后台刷新壁纸缓存。
|
||||
if config.wallpaper:
|
||||
self._scheduler.add_job(
|
||||
self.start,
|
||||
"interval",
|
||||
id="random_wallpager",
|
||||
name="壁纸缓存",
|
||||
minutes=30,
|
||||
next_run_time=datetime.now(pytz.timezone(config.timezone)) + timedelta(seconds=1),
|
||||
kwargs={"job_id": "random_wallpager"},
|
||||
)
|
||||
|
||||
# 公共定时服务
|
||||
self._scheduler.add_job(
|
||||
|
||||
@@ -49,6 +49,10 @@ class Scheduler(
|
||||
CONFIG_WATCH = {
|
||||
"DEV",
|
||||
"TZ",
|
||||
# 壁纸来源或地址变化时重建任务并清理来源缓存。
|
||||
"WALLPAPER",
|
||||
"WALLPAPER_IMAGE_URL",
|
||||
"CUSTOMIZE_WALLPAPER_API_URL",
|
||||
"COOKIECLOUD_INTERVAL",
|
||||
"MEDIASERVER_SYNC_INTERVAL",
|
||||
SystemConfigKey.MediaServers.value,
|
||||
|
||||
@@ -30,6 +30,10 @@ class SchedulerLifecycleOwner(_SchedulerOwnerBase):
|
||||
with self._lock:
|
||||
if self._lifecycle_state != "reloading":
|
||||
return
|
||||
services = getattr(self, "_services", None)
|
||||
clear_wallpaper_cache = getattr(services, "clear_wallpaper_cache", None)
|
||||
if callable(clear_wallpaper_cache):
|
||||
clear_wallpaper_cache()
|
||||
self.init(_already_stopped=True)
|
||||
|
||||
def init(self, *, _already_stopped: bool = False) -> None:
|
||||
|
||||
@@ -32,3 +32,4 @@ class SchedulerServices:
|
||||
process_workflow: JobCallable
|
||||
put_message: JobCallable
|
||||
post_message: Callable[[Message], Any]
|
||||
clear_wallpaper_cache: Callable[[], None] | None = None
|
||||
|
||||
@@ -197,6 +197,7 @@ def build_scheduler_runtime_config(settings: Settings) -> SchedulerRuntimeConfig
|
||||
site_link=settings.MP_DOMAIN("#/site"),
|
||||
auto_update=settings.MOVIEPILOT_AUTO_UPDATE,
|
||||
auto_update_resource=settings.AUTO_UPDATE_RESOURCE,
|
||||
wallpaper=settings.WALLPAPER,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ def configure_scheduler_services() -> None:
|
||||
cleanup_data=scheduler_chain.cleanup,
|
||||
run_modules=scheduler_chain.scheduler_job,
|
||||
get_wallpapers=WallpaperHelper().get_wallpapers,
|
||||
clear_wallpaper_cache=WallpaperHelper().clear_cache,
|
||||
refresh_site_data=site_chain.refresh_userdatas,
|
||||
refresh_recommend=recommend_chain.refresh_recommend,
|
||||
cache_subscribe_calendar=subscribe_chain.cache_calendar,
|
||||
|
||||
@@ -82,6 +82,38 @@ def test_auto_update_setting_is_hot_reloadable() -> None:
|
||||
assert "AUTO_UPDATE_RESOURCE" in Scheduler.CONFIG_WATCH
|
||||
|
||||
|
||||
def test_wallpaper_settings_are_hot_reloadable() -> None:
|
||||
"""壁纸来源或地址变化时必须重建调度器并清理缓存。"""
|
||||
assert Scheduler.CONFIG_WATCH.issuperset({
|
||||
"WALLPAPER",
|
||||
"WALLPAPER_IMAGE_URL",
|
||||
"CUSTOMIZE_WALLPAPER_API_URL",
|
||||
})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("wallpaper", ["", "tmdb"])
|
||||
def test_wallpaper_schedule_follows_wallpaper_setting(monkeypatch, wallpaper) -> None:
|
||||
"""无壁纸时不注册缓存任务,启用来源后恢复注册。"""
|
||||
scheduler = _scheduler()
|
||||
scheduler._services = Mock()
|
||||
background_scheduler = Mock()
|
||||
monkeypatch.setattr(scheduler_catalog, "BackgroundScheduler", lambda **_kwargs: background_scheduler)
|
||||
monkeypatch.setattr(scheduler_catalog, "get_plugin_manager", lambda: Mock())
|
||||
monkeypatch.setattr(scheduler_catalog, "get_mediaserver_configs", lambda **_kwargs: [])
|
||||
monkeypatch.setattr(scheduler, "init_workflow_jobs", lambda: None)
|
||||
monkeypatch.setattr(scheduler, "init_agent_task_jobs", lambda: None)
|
||||
monkeypatch.setattr(scheduler, "init_plugin_jobs", lambda: None)
|
||||
|
||||
scheduler._initialize_catalog(_config(wallpaper=wallpaper))
|
||||
|
||||
registered = wallpaper != ""
|
||||
assert ("random_wallpager" in scheduler._jobs) is registered
|
||||
assert any(
|
||||
call.kwargs.get("id") == "random_wallpager"
|
||||
for call in background_scheduler.add_job.call_args_list
|
||||
) is registered
|
||||
|
||||
|
||||
def test_disabled_database_backup_does_not_register_job() -> None:
|
||||
"""关闭备份时不注册作业。"""
|
||||
scheduler = _scheduler()
|
||||
|
||||
@@ -587,6 +587,26 @@ async def test_config_reload_does_not_restart_scheduler_during_shutdown() -> Non
|
||||
assert scheduler._lifecycle_state == "stopping"
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_config_reload_clears_wallpaper_cache_before_reinitializing() -> None:
|
||||
"""壁纸配置热重载应先清理旧缓存,再建立新任务目录。"""
|
||||
scheduler = _scheduler("reload-wallpaper", lambda: None)
|
||||
calls = []
|
||||
scheduler._services = SimpleNamespace(
|
||||
clear_wallpaper_cache=lambda: calls.append("clear"),
|
||||
)
|
||||
|
||||
def init(**_kwargs) -> None:
|
||||
calls.append("init")
|
||||
scheduler._lifecycle_state = "running"
|
||||
|
||||
scheduler.init = init
|
||||
|
||||
await scheduler.on_config_changed()
|
||||
|
||||
assert calls == ["clear", "init"]
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_concurrent_config_reload_waits_for_old_scheduler_shutdown(
|
||||
monkeypatch,
|
||||
|
||||
@@ -13,8 +13,10 @@ from app.application.image import (
|
||||
configure_image_ports,
|
||||
configure_wallpaper_providers,
|
||||
reset_image_ports,
|
||||
reset_wallpaper_providers,
|
||||
)
|
||||
from app.runtime.config import ConfigModel
|
||||
from app.runtime.config import ConfigModel, Settings
|
||||
from app.startup.composition.configuration import build_scheduler_runtime_config
|
||||
|
||||
|
||||
class _WallpaperTransport:
|
||||
@@ -119,6 +121,24 @@ def test_reconfigure_image_ports_clears_wallpaper_cache():
|
||||
reset_image_ports(*previous)
|
||||
|
||||
|
||||
def test_wallpaper_helper_clear_cache_refreshes_provider_result():
|
||||
"""壁纸配置热重载后必须丢弃旧来源缓存。"""
|
||||
helper = WallpaperHelper()
|
||||
values = iter(("old-wallpaper", "new-wallpaper"))
|
||||
configure_wallpaper_providers(
|
||||
tmdb_wallpaper=lambda: next(values),
|
||||
tmdb_wallpapers=lambda _count: [],
|
||||
mediaserver_wallpaper=lambda: None,
|
||||
mediaserver_wallpapers=lambda _count: [],
|
||||
)
|
||||
try:
|
||||
assert helper.get_tmdb_wallpaper() == "old-wallpaper"
|
||||
helper.clear_cache()
|
||||
assert helper.get_tmdb_wallpaper() == "new-wallpaper"
|
||||
finally:
|
||||
reset_wallpaper_providers()
|
||||
|
||||
|
||||
def test_static_wallpaper_returns_local_or_remote_address_directly(monkeypatch):
|
||||
"""静态模式不发起 API 请求,直接沿用用户填写的本地路径或 URL。"""
|
||||
config = SimpleNamespace(wallpaper="static", wallpaper_image_url="/local/wallpaper.jpg")
|
||||
@@ -141,6 +161,13 @@ def test_wallpaper_settings_define_backward_compatible_defaults():
|
||||
assert ConfigModel.model_fields["WALLPAPER_IMAGE_URL"].default is None
|
||||
|
||||
|
||||
def test_scheduler_runtime_config_carries_wallpaper_setting():
|
||||
"""调度器快照必须读取当前壁纸来源,供任务目录决定是否注册缓存。"""
|
||||
settings = Settings(WALLPAPER="tmdb")
|
||||
|
||||
assert build_scheduler_runtime_config(settings).wallpaper == "tmdb"
|
||||
|
||||
|
||||
def test_login_global_settings_expose_wallpaper_rotation_interval(monkeypatch):
|
||||
"""登录前全局设置必须下发轮换间隔,避免前端退回硬编码时钟。"""
|
||||
values = {
|
||||
|
||||
Reference in New Issue
Block a user