This commit is contained in:
薇薇安 2026-01-18 21:16:01 +08:00
parent 31486b5026
commit 596b2ec788

View File

@ -5,6 +5,7 @@
import sys
import os
import json
import re
from pathlib import Path
from typing import Optional, Any
@ -152,12 +153,8 @@ class ConfigManager:
try:
# 使用Hash存储所有配置键为 trading_config:{key}
value = self._redis_client.hget('trading_config', key)
if value:
# 尝试解析JSON如果是复杂类型
try:
return json.loads(value)
except (json.JSONDecodeError, TypeError):
return value
if value is not None and value != '':
return self._coerce_redis_value(value)
except Exception as e:
logger.debug(f"从Redis获取配置失败 {key}: {e}")
# 连接失败时,尝试重新连接
@ -169,6 +166,56 @@ class ConfigManager:
return None
@staticmethod
def _coerce_redis_value(value_str: Any) -> Any:
"""
Redis Hash 中的字符串值尽量还原为正确类型
兼容历史写法
- 之前 bool 会被写成 "True"/"False" JSON导致读取后变成字符串进而在逻辑判断里永远为 True
- 现在会优先把 bool/int/float/dict/list JSON 序列化写入 _set_to_redis
"""
if value_str is None:
return None
# redis-py decode_responses=True 时是 str否则可能是 bytes
if isinstance(value_str, bytes):
try:
value_str = value_str.decode('utf-8', errors='ignore')
except Exception:
value_str = str(value_str)
s = str(value_str).strip()
if s == '':
return ''
# 1) JSON 优先dict/list/bool/number 都能覆盖)
try:
return json.loads(s)
except Exception:
pass
sl = s.lower()
# 2) bool 兼容(历史 "True"/"False"
if sl in ('true', 'false', '1', '0', 'yes', 'no', 'on', 'off'):
return sl in ('true', '1', 'yes', 'on')
# 3) number 兼容(避免把 "1h" 之类误判)
# int: -?\d+
if re.fullmatch(r'-?\d+', s):
try:
return int(s)
except Exception:
return s
# float: -?\d+\.\d+
if re.fullmatch(r'-?\d+\.\d+', s):
try:
return float(s)
except Exception:
return s
return s
def _set_to_redis(self, key: str, value: Any):
"""设置配置到Redis"""
if not self._redis_connected or not self._redis_client:
@ -176,9 +223,9 @@ class ConfigManager:
try:
# 使用Hash存储所有配置键为 trading_config:{key}
# 将值序列化为JSON如果是复杂类型
if isinstance(value, (dict, list)):
value_str = json.dumps(value)
# 将值序列化:复杂类型/基础类型使用 JSON避免 bool 被写成 "False" 字符串后逻辑误判
if isinstance(value, (dict, list, bool, int, float)):
value_str = json.dumps(value, ensure_ascii=False)
else:
value_str = str(value)
@ -193,8 +240,8 @@ class ConfigManager:
self._redis_client.ping()
self._redis_connected = True
# 重试一次
if isinstance(value, (dict, list)):
value_str = json.dumps(value)
if isinstance(value, (dict, list, bool, int, float)):
value_str = json.dumps(value, ensure_ascii=False)
else:
value_str = str(value)
self._redis_client.hset('trading_config', key, value_str)
@ -213,8 +260,8 @@ class ConfigManager:
# 批量设置所有配置到Redis
pipe = self._redis_client.pipeline()
for key, value in self._cache.items():
if isinstance(value, (dict, list)):
value_str = json.dumps(value)
if isinstance(value, (dict, list, bool, int, float)):
value_str = json.dumps(value, ensure_ascii=False)
else:
value_str = str(value)
pipe.hset('trading_config', key, value_str)
@ -241,13 +288,7 @@ class ConfigManager:
if redis_configs and len(redis_configs) > 0:
# 解析Redis中的配置
for key, value_str in redis_configs.items():
try:
# 尝试解析JSON
value = json.loads(value_str)
except (json.JSONDecodeError, TypeError):
# 如果不是JSON尝试转换类型
value = value_str
self._cache[key] = value
self._cache[key] = self._coerce_redis_value(value_str)
logger.info(f"从Redis加载了 {len(self._cache)} 个配置项")
return
else:
@ -350,11 +391,7 @@ class ConfigManager:
if redis_configs and len(redis_configs) > 0:
self._cache = {} # 清空缓存
for key, value_str in redis_configs.items():
try:
value = json.loads(value_str)
except (json.JSONDecodeError, TypeError):
value = value_str
self._cache[key] = value
self._cache[key] = self._coerce_redis_value(value_str)
logger.debug(f"从Redis重新加载了 {len(self._cache)} 个配置项")
else:
# Redis中没有配置但不回退到数据库避免频繁从数据库加载