a
This commit is contained in:
parent
31486b5026
commit
596b2ec788
|
|
@ -5,6 +5,7 @@
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any
|
||||||
|
|
||||||
|
|
@ -152,12 +153,8 @@ class ConfigManager:
|
||||||
try:
|
try:
|
||||||
# 使用Hash存储所有配置,键为 trading_config:{key}
|
# 使用Hash存储所有配置,键为 trading_config:{key}
|
||||||
value = self._redis_client.hget('trading_config', key)
|
value = self._redis_client.hget('trading_config', key)
|
||||||
if value:
|
if value is not None and value != '':
|
||||||
# 尝试解析JSON(如果是复杂类型)
|
return self._coerce_redis_value(value)
|
||||||
try:
|
|
||||||
return json.loads(value)
|
|
||||||
except (json.JSONDecodeError, TypeError):
|
|
||||||
return value
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"从Redis获取配置失败 {key}: {e}")
|
logger.debug(f"从Redis获取配置失败 {key}: {e}")
|
||||||
# 连接失败时,尝试重新连接
|
# 连接失败时,尝试重新连接
|
||||||
|
|
@ -168,6 +165,56 @@ class ConfigManager:
|
||||||
self._redis_connected = False
|
self._redis_connected = False
|
||||||
|
|
||||||
return None
|
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):
|
def _set_to_redis(self, key: str, value: Any):
|
||||||
"""设置配置到Redis"""
|
"""设置配置到Redis"""
|
||||||
|
|
@ -176,9 +223,9 @@ class ConfigManager:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 使用Hash存储所有配置,键为 trading_config:{key}
|
# 使用Hash存储所有配置,键为 trading_config:{key}
|
||||||
# 将值序列化为JSON(如果是复杂类型)
|
# 将值序列化:复杂类型/基础类型使用 JSON,避免 bool 被写成 "False" 字符串后逻辑误判
|
||||||
if isinstance(value, (dict, list)):
|
if isinstance(value, (dict, list, bool, int, float)):
|
||||||
value_str = json.dumps(value)
|
value_str = json.dumps(value, ensure_ascii=False)
|
||||||
else:
|
else:
|
||||||
value_str = str(value)
|
value_str = str(value)
|
||||||
|
|
||||||
|
|
@ -193,8 +240,8 @@ class ConfigManager:
|
||||||
self._redis_client.ping()
|
self._redis_client.ping()
|
||||||
self._redis_connected = True
|
self._redis_connected = True
|
||||||
# 重试一次
|
# 重试一次
|
||||||
if isinstance(value, (dict, list)):
|
if isinstance(value, (dict, list, bool, int, float)):
|
||||||
value_str = json.dumps(value)
|
value_str = json.dumps(value, ensure_ascii=False)
|
||||||
else:
|
else:
|
||||||
value_str = str(value)
|
value_str = str(value)
|
||||||
self._redis_client.hset('trading_config', key, value_str)
|
self._redis_client.hset('trading_config', key, value_str)
|
||||||
|
|
@ -213,8 +260,8 @@ class ConfigManager:
|
||||||
# 批量设置所有配置到Redis
|
# 批量设置所有配置到Redis
|
||||||
pipe = self._redis_client.pipeline()
|
pipe = self._redis_client.pipeline()
|
||||||
for key, value in self._cache.items():
|
for key, value in self._cache.items():
|
||||||
if isinstance(value, (dict, list)):
|
if isinstance(value, (dict, list, bool, int, float)):
|
||||||
value_str = json.dumps(value)
|
value_str = json.dumps(value, ensure_ascii=False)
|
||||||
else:
|
else:
|
||||||
value_str = str(value)
|
value_str = str(value)
|
||||||
pipe.hset('trading_config', key, value_str)
|
pipe.hset('trading_config', key, value_str)
|
||||||
|
|
@ -241,13 +288,7 @@ class ConfigManager:
|
||||||
if redis_configs and len(redis_configs) > 0:
|
if redis_configs and len(redis_configs) > 0:
|
||||||
# 解析Redis中的配置
|
# 解析Redis中的配置
|
||||||
for key, value_str in redis_configs.items():
|
for key, value_str in redis_configs.items():
|
||||||
try:
|
self._cache[key] = self._coerce_redis_value(value_str)
|
||||||
# 尝试解析JSON
|
|
||||||
value = json.loads(value_str)
|
|
||||||
except (json.JSONDecodeError, TypeError):
|
|
||||||
# 如果不是JSON,尝试转换类型
|
|
||||||
value = value_str
|
|
||||||
self._cache[key] = value
|
|
||||||
logger.info(f"从Redis加载了 {len(self._cache)} 个配置项")
|
logger.info(f"从Redis加载了 {len(self._cache)} 个配置项")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
|
@ -350,11 +391,7 @@ class ConfigManager:
|
||||||
if redis_configs and len(redis_configs) > 0:
|
if redis_configs and len(redis_configs) > 0:
|
||||||
self._cache = {} # 清空缓存
|
self._cache = {} # 清空缓存
|
||||||
for key, value_str in redis_configs.items():
|
for key, value_str in redis_configs.items():
|
||||||
try:
|
self._cache[key] = self._coerce_redis_value(value_str)
|
||||||
value = json.loads(value_str)
|
|
||||||
except (json.JSONDecodeError, TypeError):
|
|
||||||
value = value_str
|
|
||||||
self._cache[key] = value
|
|
||||||
logger.debug(f"从Redis重新加载了 {len(self._cache)} 个配置项")
|
logger.debug(f"从Redis重新加载了 {len(self._cache)} 个配置项")
|
||||||
else:
|
else:
|
||||||
# Redis中没有配置,但不回退到数据库(避免频繁从数据库加载)
|
# Redis中没有配置,但不回退到数据库(避免频繁从数据库加载)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user