From 160094cd74c1048bf593a9cc1d7d4d566d00913b Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 22 Aug 2026 20:02:32 +0800 Subject: [PATCH] refactor: migrate image configuration to runtime snapshot --- app/application/configuration.py | 5 +++ app/application/image.py | 41 +++++++++++-------- app/startup/configuration.py | 5 +++ .../backend-architecture-next-stage.md | 5 +++ .../configuration-debt-baseline.json | 3 +- .../architecture/dependency-baseline.json | 4 +- 6 files changed, 41 insertions(+), 22 deletions(-) diff --git a/app/application/configuration.py b/app/application/configuration.py index 0b6d34cc9..cbf8ba9e6 100644 --- a/app/application/configuration.py +++ b/app/application/configuration.py @@ -192,6 +192,11 @@ class ChainRuntimeConfig: television_rename_format: str = "" music_rename_format: str = "" tmdb_image_domain: str = "image.tmdb.org" + wallpaper: str = "bing" + customize_wallpaper_api_url: Optional[str] = None + security_image_suffixes: tuple[str, ...] = () + cache_path: Path = Path(".") + global_image_cache_days: int = 7 def rename_format(self, media_type: MediaType) -> str: """从快照返回指定媒体类型的稳定重命名格式。""" diff --git a/app/application/image.py b/app/application/image.py index 04c05f08c..17e83652e 100644 --- a/app/application/image.py +++ b/app/application/image.py @@ -5,7 +5,7 @@ from typing import Callable, Optional, List from PIL import Image from app.runtime.cache import cached, FileCache, AsyncFileCache -from app.runtime.config import settings +from app.application.configuration import get_chain_runtime_config_snapshot from app.runtime.log import logger from app.adapters.network.http import RequestUtils, AsyncRequestUtils from app.adapters.network.ip import IpUtils @@ -64,13 +64,14 @@ class WallpaperHelper(metaclass=Singleton): """ 获取登录页面壁纸 """ - if settings.WALLPAPER == "bing": + wallpaper = get_chain_runtime_config_snapshot().wallpaper + if wallpaper == "bing": return self.get_bing_wallpaper() - elif settings.WALLPAPER == "mediaserver": + elif wallpaper == "mediaserver": return self.get_mediaserver_wallpaper() - elif settings.WALLPAPER == "customize": + elif wallpaper == "customize": return self.get_customize_wallpaper() - elif settings.WALLPAPER == "tmdb": + elif wallpaper == "tmdb": return self.get_tmdb_wallpaper() return '' @@ -78,13 +79,14 @@ class WallpaperHelper(metaclass=Singleton): """ 获取登录页面壁纸列表 """ - if settings.WALLPAPER == "bing": + wallpaper = get_chain_runtime_config_snapshot().wallpaper + if wallpaper == "bing": return self.get_bing_wallpapers(num) - elif settings.WALLPAPER == "mediaserver": + elif wallpaper == "mediaserver": return self.get_mediaserver_wallpapers(num) - elif settings.WALLPAPER == "customize": + elif wallpaper == "customize": return self.get_customize_wallpapers() - elif settings.WALLPAPER == "tmdb": + elif wallpaper == "tmdb": return self.get_tmdb_wallpapers(num) return [] @@ -190,19 +192,20 @@ class WallpaperHelper(metaclass=Singleton): return _result # 判断是否存在自定义壁纸api - if settings.CUSTOMIZE_WALLPAPER_API_URL: + config = get_chain_runtime_config_snapshot() + if config.customize_wallpaper_api_url: wallpaper_list = [] - resp = RequestUtils(timeout=15).get_res(settings.CUSTOMIZE_WALLPAPER_API_URL) + resp = RequestUtils(timeout=15).get_res(config.customize_wallpaper_api_url) if resp and resp.status_code == 200: # 如果返回的是图片格式 content_type = resp.headers.get('Content-Type') if content_type and content_type.lower().startswith('image/'): - wallpaper_list.append(settings.CUSTOMIZE_WALLPAPER_API_URL) + wallpaper_list.append(config.customize_wallpaper_api_url) else: try: result = resp.json() if isinstance(result, list) or isinstance(result, dict) or isinstance(result, str): - wallpaper_list = find_files_with_suffixes(result, settings.SECURITY_IMAGE_SUFFIXES) + wallpaper_list = find_files_with_suffixes(result, config.security_image_suffixes) except Exception as err: print(str(err)) return wallpaper_list @@ -215,8 +218,9 @@ class ImageHelper(metaclass=Singleton): def __init__(self): """按全局图片缓存天数初始化文件缓存。""" - _base_path = settings.CACHE_PATH - _ttl = settings.GLOBAL_IMAGE_CACHE_DAYS * 24 * 3600 + config = get_chain_runtime_config_snapshot() + _base_path = config.cache_path + _ttl = config.global_image_cache_days * 24 * 3600 self.file_cache = FileCache(base=_base_path, ttl=_ttl) self.async_file_cache = AsyncFileCache(base=_base_path, ttl=_ttl) @@ -260,12 +264,13 @@ class ImageHelper(metaclass=Singleton): def _get_request_params(url: str, proxy: Optional[bool], cookies: Optional[str | dict]) -> dict: """获取参数""" referer = "https://movie.douban.com/" if "doubanio.com" in url else None + config = get_chain_runtime_config_snapshot() if proxy is None: - proxies = settings.PROXY if not (referer or IpUtils.is_internal(url)) else None + proxies = config.proxy if not (referer or IpUtils.is_internal(url)) else None else: - proxies = settings.PROXY if proxy else None + proxies = config.proxy if proxy else None return { - "ua": settings.NORMAL_USER_AGENT, + "ua": config.normal_user_agent, "proxies": proxies, "referer": referer, "cookies": cookies, diff --git a/app/startup/configuration.py b/app/startup/configuration.py index 59ac0f08f..ad0af9d29 100644 --- a/app/startup/configuration.py +++ b/app/startup/configuration.py @@ -141,4 +141,9 @@ def build_chain_runtime_config(settings: Settings) -> ChainRuntimeConfig: television_rename_format=settings.RENAME_FORMAT(MediaType.TV), music_rename_format=settings.RENAME_FORMAT(MediaType.MUSIC), tmdb_image_domain=settings.TMDB_IMAGE_DOMAIN, + wallpaper=settings.WALLPAPER, + customize_wallpaper_api_url=settings.CUSTOMIZE_WALLPAPER_API_URL, + security_image_suffixes=tuple(settings.SECURITY_IMAGE_SUFFIXES), + cache_path=settings.CACHE_PATH, + global_image_cache_days=settings.GLOBAL_IMAGE_CACHE_DAYS, ) diff --git a/docs/refactor/backend-architecture-next-stage.md b/docs/refactor/backend-architecture-next-stage.md index c6f3750e5..b64db5844 100644 --- a/docs/refactor/backend-architecture-next-stage.md +++ b/docs/refactor/backend-architecture-next-stage.md @@ -969,6 +969,11 @@ Outbox adapter、DB 装饰器、Base 与 UoW,strict 清单扩大到 37 个源 - 单元测试覆盖删除/缩短放行和增长/新增拒绝,当前仓库 baseline check 通过。 - 2026-08-22 将 MCP JSON-RPC 分派、无媒体信息下载识别、缺集结果合并拆成具有独立输入/输出的私有阶段; 对应 `mcp_jsonrpc`、`download.add`、`DownloadChain.get_no_exists_info` 退出超限清单,总债务从 28 降到 25。 +- 2026-08-22 将 `SiteChain.sync_cookies` 拆为单域名处理、黑名单判断、索引器地址解析和连接重试阶段,入口降至预算内; + 保留已有站点健康、黑名单、失败重试时的事件与进度回调语义,站点专项测试通过。 + +配置债务继续按模块族收敛:`app/application/image.py` 的壁纸模式、图片缓存、代理和安全后缀读取已接入 +`ChainRuntimeConfig`,canonical `settings` 直接读取文件数从 137 降至 136;配置/依赖基线已更新,壁纸与图片专项测试通过。 #### ARCH-272:异步阻塞检测 diff --git a/tests/fixtures/architecture/configuration-debt-baseline.json b/tests/fixtures/architecture/configuration-debt-baseline.json index f0062b28b..c3b8f9d2e 100644 --- a/tests/fixtures/architecture/configuration-debt-baseline.json +++ b/tests/fixtures/architecture/configuration-debt-baseline.json @@ -9,7 +9,7 @@ "root": "app" }, "settings_imports": { - "count": 137, + "count": 136, "files": [ "app/adapters/cache/backends.py", "app/adapters/cache/redis.py", @@ -48,7 +48,6 @@ "app/agent/tools/impl/update_agent_task.py", "app/agent/tools/impl/update_system_settings.py", "app/application/formatting.py", - "app/application/image.py", "app/application/maintenance.py", "app/application/rss.py", "app/application/security/auth.py", diff --git a/tests/fixtures/architecture/dependency-baseline.json b/tests/fixtures/architecture/dependency-baseline.json index c654fe435..aa37d2b01 100644 --- a/tests/fixtures/architecture/dependency-baseline.json +++ b/tests/fixtures/architecture/dependency-baseline.json @@ -14,7 +14,7 @@ "workflow_to_db": [] }, "edge_count": 6393, - "edge_sha256": "fe5804c22c536d640583046cb78ba29a7ba4de577a3205cc6eacaf030491c3d3", + "edge_sha256": "ea375f19071a37a9c72bd01ce9fa4a070e64ad7f14a87d2e5013b5c7440680cd", "edges": [ "app -> app.runtime", "app -> app.runtime.compat", @@ -2527,13 +2527,13 @@ "app.application.image -> app.adapters.network.http", "app.application.image -> app.adapters.network.ip", "app.application.image -> app.application", + "app.application.image -> app.application.configuration", "app.application.image -> app.application.security", "app.application.image -> app.application.security.url", "app.application.image -> app.foundation", "app.application.image -> app.foundation.singleton", "app.application.image -> app.runtime", "app.application.image -> app.runtime.cache", - "app.application.image -> app.runtime.config", "app.application.image -> app.runtime.log", "app.application.maintenance -> app.runtime", "app.application.maintenance -> app.runtime.config",