Files
MoviePilot/app/db/systemconfig_oper.py
景大侠 f478958943 修复 SystemConfig潜在的资源竞争问题
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-01-13 14:33:53 +08:00

126 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asyncio
import copy
import threading
from typing import Any, Optional, Union
from app.db import DbOper
from app.db.models.systemconfig import SystemConfig
from app.schemas.types import SystemConfigKey
from app.utils.singleton import Singleton
class SystemConfigOper(DbOper, metaclass=Singleton):
"""
系统配置管理
"""
def __init__(self):
"""
加载配置到内存
"""
super().__init__()
self.__SYSTEMCONF = {}
self._rlock = threading.RLock()
self._alock = asyncio.Lock()
for item in SystemConfig.list(self._db):
self.__SYSTEMCONF[item.key] = item.value
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
with self._rlock:
# 旧值
old_value = self.__SYSTEMCONF.get(key)
# 更新内存(deepcopy避免内存共享)
self.__SYSTEMCONF[key] = copy.deepcopy(value)
conf = SystemConfig.get_by_key(self._db, key)
if conf:
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)
return True
async def async_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
async with self._alock:
conf = await SystemConfig.async_get_by_key(self._db, key)
# 确定是否需要更新数据库
needs_db_update = False
if conf:
if conf.value != value:
needs_db_update = True
else: # 记录不存在,总是需要创建/更新
needs_db_update = True
if not needs_db_update:
# 即使数据库值相同,也要确保缓存同步
with self._rlock:
self.__SYSTEMCONF[key] = copy.deepcopy(value)
return None
# 执行数据库更新
if conf:
if value:
await conf.async_update(self._db, {"value": value})
else:
await conf.async_delete(self._db, conf.id)
else:
conf = SystemConfig(key=key, value=value)
await conf.async_create(self._db)
# 数据库更新成功后,再更新缓存
with self._rlock:
self.__SYSTEMCONF[key] = copy.deepcopy(value)
return True
def get(self, key: Union[str, SystemConfigKey] = None) -> Any:
"""
获取系统设置
"""
if isinstance(key, SystemConfigKey):
key = key.value
if not key:
return self.all()
with self._rlock:
# 避免将__SYSTEMCONF内的值引用出去会导致set时误判没有变动
return copy.deepcopy(self.__SYSTEMCONF.get(key))
def all(self):
"""
获取所有系统设置
"""
with self._rlock:
# 避免将__SYSTEMCONF内的值引用出去会导致set时误判没有变动
return copy.deepcopy(self.__SYSTEMCONF)
def delete(self, key: Union[str, SystemConfigKey]) -> bool:
"""
删除系统设置
"""
if isinstance(key, SystemConfigKey):
key = key.value
with self._rlock:
# 更新内存
self.__SYSTEMCONF.pop(key, None)
# 写入数据库
conf = SystemConfig.get_by_key(self._db, key)
if conf:
conf.delete(self._db, conf.id)
return True