import copy import threading from typing import Any, Optional, Union from app.db.base import DbOper from app.db.models.systemconfig import SystemConfig from app.schemas.types import SystemConfigKey from app.foundation.singleton import Singleton class SystemConfigOper(DbOper, metaclass=Singleton): """ 系统配置管理 """ def __init__(self): """初始化空快照,数据库加载由启动组合根显式执行。""" super().__init__() self.__SYSTEMCONF = {} self._snapshot_lock = threading.RLock() self._write_lock = threading.RLock() self._loaded = False def load_snapshot(self) -> None: """从数据库加载完整配置,并一次性发布新的内存快照。""" with self._write_lock: snapshot = { item.key: copy.deepcopy(item.value) for item in SystemConfig.list(self._db) } with self._snapshot_lock: self.__SYSTEMCONF = snapshot self._loaded = True def _require_loaded(self) -> None: """阻止消费者读取尚未完成启动加载的半成品快照。""" if not self._loaded: raise RuntimeError("系统配置快照尚未加载") def _publish_value(self, key: str, value: Any) -> None: """在事务成功后短暂持锁发布单项配置。""" with self._snapshot_lock: self.__SYSTEMCONF[key] = copy.deepcopy(value) def _publish_delete(self, key: str) -> None: """在事务成功后短暂持锁移除单项配置。""" with self._snapshot_lock: self.__SYSTEMCONF.pop(key, None) 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 self._require_loaded() with self._write_lock: def write(db): """在当前事务中创建或更新配置记录。""" conf = SystemConfig.get_by_key(db, key) if conf: if conf.value == value: return None # 假值同样是有效配置;删除记录会使读取端错误回落默认值。 conf.value = copy.deepcopy(value) else: db.add(SystemConfig(key=key, value=copy.deepcopy(value))) return True result = self._execute_sync_write(write) # 数据库操作返回时事务已经提交,读取方不会看到尚未持久化的配置。 self._publish_value(key, value) return result def get(self, key: Optional[Union[str, SystemConfigKey]] = None) -> Any: """ 获取系统设置 """ if isinstance(key, SystemConfigKey): key = key.value if not key: return self.all() with self._snapshot_lock: self._require_loaded() # 避免将__SYSTEMCONF内的值引用出去,会导致set时误判没有变动 return copy.deepcopy(self.__SYSTEMCONF.get(key)) def increment(self, key: SystemConfigKey, step: int = 1) -> int: """ 原子递增整数系统设置 :param key: 配置键 :param step: 递增步长 :return: 递增后的整数值 """ self._require_loaded() with self._write_lock: value = int(self.get(key) or 0) + step self.set(key, value) return value def all(self): """ 获取所有系统设置 """ with self._snapshot_lock: self._require_loaded() # 避免将__SYSTEMCONF内的值引用出去,会导致set时误判没有变动 return copy.deepcopy(self.__SYSTEMCONF) def delete(self, key: Union[str, SystemConfigKey]) -> bool: """ 删除系统设置 """ if isinstance(key, SystemConfigKey): key = key.value self._require_loaded() with self._write_lock: def delete(db): """在当前事务中删除配置记录。""" conf = SystemConfig.get_by_key(db, key) if conf: db.delete(conf) self._execute_sync_write(delete) self._publish_delete(key) return True