mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-05-02 14:42:22 +08:00
fix Config reload
This commit is contained in:
@@ -32,11 +32,13 @@ from app.helper.subscribe import SubscribeHelper
|
||||
from app.helper.system import SystemHelper
|
||||
from app.log import logger
|
||||
from app.scheduler import Scheduler
|
||||
from app.schemas.types import SystemConfigKey
|
||||
from app.schemas import ConfigChangeEventData
|
||||
from app.schemas.types import SystemConfigKey, EventType
|
||||
from app.utils.crypto import HashUtils
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.security import SecurityUtils
|
||||
from app.utils.url import UrlUtils
|
||||
from core.event import eventmanager
|
||||
from version import APP_VERSION
|
||||
|
||||
router = APIRouter()
|
||||
@@ -218,7 +220,7 @@ def set_env_setting(env: dict,
|
||||
result = settings.update_settings(env=env)
|
||||
# 统计成功和失败的结果
|
||||
success_updates = {k: v for k, v in result.items() if v[0]}
|
||||
failed_updates = {k: v for k, v in result.items() if not v[0]}
|
||||
failed_updates = {k: v for k, v in result.items() if v[0] is False}
|
||||
|
||||
if failed_updates:
|
||||
return schemas.Response(
|
||||
@@ -230,6 +232,15 @@ def set_env_setting(env: dict,
|
||||
}
|
||||
)
|
||||
|
||||
if success_updates:
|
||||
for key in success_updates.keys():
|
||||
# 发送配置变更事件
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
value=getattr(settings, key, None),
|
||||
change_type="update"
|
||||
))
|
||||
|
||||
return schemas.Response(
|
||||
success=True,
|
||||
message="所有配置项更新成功",
|
||||
@@ -283,12 +294,26 @@ def set_setting(key: str, value: Union[list, dict, bool, int, str] = None,
|
||||
"""
|
||||
if hasattr(settings, key):
|
||||
success, message = settings.update_setting(key=key, value=value)
|
||||
if success:
|
||||
# 发送配置变更事件
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
value=value,
|
||||
change_type="update"
|
||||
))
|
||||
return schemas.Response(success=success, message=message)
|
||||
elif key in {item.value for item in SystemConfigKey}:
|
||||
if isinstance(value, list):
|
||||
value = list(filter(None, value))
|
||||
value = value if value else None
|
||||
SystemConfigOper().set(key, value)
|
||||
success = SystemConfigOper().set(key, value)
|
||||
if success:
|
||||
# 发送配置变更事件
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
value=value,
|
||||
change_type="update"
|
||||
))
|
||||
return schemas.Response(success=True)
|
||||
else:
|
||||
return schemas.Response(success=False, message=f"配置项 '{key}' 不存在")
|
||||
|
||||
@@ -13,8 +13,6 @@ from pydantic import BaseModel, BaseSettings, validator, Field
|
||||
from app.log import logger, log_settings, LogConfigModel
|
||||
from app.utils.system import SystemUtils
|
||||
from app.utils.url import UrlUtils
|
||||
from app.schemas.types import EventType
|
||||
from app.schemas import ConfigChangeEventData
|
||||
|
||||
|
||||
class ConfigModel(BaseModel):
|
||||
@@ -391,8 +389,6 @@ class Settings(BaseSettings, ConfigModel, LogConfigModel):
|
||||
f"配置项 '{field_name}' 的值 '{value}' 无法转换成正确的类型,使用默认值 '{default}',错误信息: {e}")
|
||||
return default, True
|
||||
|
||||
# TODO[pydantic]: We couldn't refactor the `validator`, please replace it by `field_validator` manually.
|
||||
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-validators for more information.
|
||||
@validator('*', pre=True, always=True)
|
||||
def generic_type_validator(cls, value: Any, field): # noqa
|
||||
"""
|
||||
@@ -435,9 +431,12 @@ class Settings(BaseSettings, ConfigModel, LogConfigModel):
|
||||
logger.info(f"配置项 '{field.name}' 已自动修正并写入到 'app.env' 文件")
|
||||
return True, message
|
||||
|
||||
def update_setting(self, key: str, value: Any) -> Tuple[bool, str]:
|
||||
def update_setting(self, key: str, value: Any) -> Tuple[Optional[bool], str]:
|
||||
"""
|
||||
更新单个配置项
|
||||
:param key: 配置项的名称
|
||||
:param value: 配置项的新值
|
||||
:return: (是否成功 True 成功/False 失败/None 无需更新, 错误信息)
|
||||
"""
|
||||
if not hasattr(self, key):
|
||||
return False, f"配置项 '{key}' 不存在"
|
||||
@@ -448,32 +447,25 @@ class Settings(BaseSettings, ConfigModel, LogConfigModel):
|
||||
if field.name == "API_TOKEN":
|
||||
converted_value, needs_update = self.validate_api_token(value, original_value)
|
||||
else:
|
||||
converted_value, needs_update = self.generic_type_converter(value, original_value, field.type_,
|
||||
field.default, key)
|
||||
converted_value, needs_update = self.generic_type_converter(value,
|
||||
original_value,
|
||||
field.type_,
|
||||
field.default,
|
||||
key)
|
||||
# 如果没有抛出异常,则统一使用 converted_value 进行更新
|
||||
if needs_update or str(value) != str(converted_value):
|
||||
success, message = self.update_env_config(field, value, converted_value)
|
||||
# 仅成功更新配置时,才更新内存
|
||||
if success:
|
||||
old_value = getattr(self, key)
|
||||
setattr(self, key, converted_value)
|
||||
if hasattr(log_settings, key):
|
||||
setattr(log_settings, key, converted_value)
|
||||
# 发送配置变更通知
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=converted_value,
|
||||
change_type="update"
|
||||
))
|
||||
|
||||
return success, message
|
||||
return True, ""
|
||||
return None, ""
|
||||
except Exception as e:
|
||||
return False, str(e)
|
||||
|
||||
def update_settings(self, env: Dict[str, Any]) -> Dict[str, Tuple[bool, str]]:
|
||||
def update_settings(self, env: Dict[str, Any]) -> Dict[str, Tuple[Optional[bool], str]]:
|
||||
"""
|
||||
更新多个配置项
|
||||
"""
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from typing import Any, Union
|
||||
from typing import Any, Union, Optional
|
||||
|
||||
from app.db import DbOper
|
||||
from app.db.models.systemconfig import SystemConfig
|
||||
from app.schemas.types import SystemConfigKey, EventType
|
||||
from app.schemas.types import SystemConfigKey
|
||||
from app.utils.singleton import Singleton
|
||||
from app.schemas import ConfigChangeEventData
|
||||
|
||||
|
||||
class SystemConfigOper(DbOper, metaclass=Singleton):
|
||||
@@ -19,9 +18,12 @@ class SystemConfigOper(DbOper, metaclass=Singleton):
|
||||
for item in SystemConfig.list(self._db):
|
||||
self.__SYSTEMCONF[item.key] = item.value
|
||||
|
||||
def set(self, key: Union[str, SystemConfigKey], value: Any):
|
||||
def set(self, key: Union[str, SystemConfigKey], value: Any) -> Optional[bool]:
|
||||
"""
|
||||
设置系统设置
|
||||
:param key: 配置键
|
||||
:param value: 配置值
|
||||
:return: 是否设置成功(True 成功/False 失败/None 无需更新)
|
||||
"""
|
||||
if isinstance(key, SystemConfigKey):
|
||||
key = key.value
|
||||
@@ -31,38 +33,17 @@ class SystemConfigOper(DbOper, metaclass=Singleton):
|
||||
self.__SYSTEMCONF[key] = value
|
||||
conf = SystemConfig.get_by_key(self._db, key)
|
||||
if conf:
|
||||
if value:
|
||||
conf.update(self._db, {"value": value})
|
||||
# 发送配置变更通知
|
||||
if old_value != value:
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=value,
|
||||
change_type="update"
|
||||
))
|
||||
else:
|
||||
conf.delete(self._db, conf.id)
|
||||
# 发送配置删除通知
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=value,
|
||||
change_type="delete"
|
||||
))
|
||||
if old_value != value:
|
||||
if value:
|
||||
conf.update(self._db, {"value": value})
|
||||
else:
|
||||
conf.delete(self._db, conf.id)
|
||||
return True
|
||||
return None
|
||||
else:
|
||||
conf = SystemConfig(key=key, value=value)
|
||||
conf.create(self._db)
|
||||
# 发送配置变更通知
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=value,
|
||||
change_type="add"
|
||||
))
|
||||
return True
|
||||
|
||||
def get(self, key: Union[str, SystemConfigKey] = None) -> Any:
|
||||
"""
|
||||
@@ -80,26 +61,18 @@ class SystemConfigOper(DbOper, metaclass=Singleton):
|
||||
"""
|
||||
return self.__SYSTEMCONF or {}
|
||||
|
||||
def delete(self, key: Union[str, SystemConfigKey]):
|
||||
def delete(self, key: Union[str, SystemConfigKey]) -> bool:
|
||||
"""
|
||||
删除系统设置
|
||||
"""
|
||||
if isinstance(key, SystemConfigKey):
|
||||
key = key.value
|
||||
# 更新内存
|
||||
old_value = self.__SYSTEMCONF.pop(key, None)
|
||||
self.__SYSTEMCONF.pop(key, None)
|
||||
# 写入数据库
|
||||
conf = SystemConfig.get_by_key(self._db, key)
|
||||
if conf:
|
||||
conf.delete(self._db, conf.id)
|
||||
# 发送配置变更通知
|
||||
from app.core.event import eventmanager
|
||||
eventmanager.send_event(etype=EventType.ConfigChanged, data=ConfigChangeEventData(
|
||||
key=key,
|
||||
old_value=old_value,
|
||||
new_value=None,
|
||||
change_type="delete"
|
||||
))
|
||||
return True
|
||||
|
||||
def __del__(self):
|
||||
|
||||
@@ -27,8 +27,7 @@ class ConfigChangeEventData(BaseEventData):
|
||||
ConfigChange 事件的数据模型
|
||||
"""
|
||||
key: str = Field(..., description="配置项的键")
|
||||
old_value: Optional[Any] = Field(default=None, description="配置项的旧值")
|
||||
new_value: Optional[Any] = Field(default=None, description="配置项的新值")
|
||||
value: Optional[Any] = Field(default=None, description="配置项的新值")
|
||||
change_type: str = Field(default="update", description="配置项的变更类型,如 'add', 'update', 'delete'")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user