2025-12-02 22:05:54 +08:00
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
|
from loguru import logger
|
2025-12-02 22:36:52 +08:00
|
|
|
|
from typing import List, Dict, Any, Set
|
2025-12-02 22:05:54 +08:00
|
|
|
|
import json
|
2025-12-02 22:36:52 +08:00
|
|
|
|
import re
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
|
|
|
|
|
from utils.redis_client import RedisClient
|
|
|
|
|
|
from utils.database_manager import DatabaseManager
|
2025-12-02 22:36:52 +08:00
|
|
|
|
from config.settings import COMPUTER_NAMES, COMPUTER_NAME_PATTERN
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
|
|
|
|
|
class BaseSync(ABC):
|
|
|
|
|
|
"""同步基类"""
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
self.redis_client = RedisClient()
|
|
|
|
|
|
self.db_manager = DatabaseManager()
|
2025-12-02 22:36:52 +08:00
|
|
|
|
self.computer_names = self._get_computer_names()
|
|
|
|
|
|
self.computer_name_pattern = re.compile(COMPUTER_NAME_PATTERN)
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
2025-12-02 22:36:52 +08:00
|
|
|
|
def _get_computer_names(self) -> List[str]:
|
|
|
|
|
|
"""获取计算机名列表"""
|
|
|
|
|
|
if ',' in COMPUTER_NAMES:
|
|
|
|
|
|
return [name.strip() for name in COMPUTER_NAMES.split(',')]
|
|
|
|
|
|
return [COMPUTER_NAMES.strip()]
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
|
|
|
|
|
def get_accounts_from_redis(self) -> Dict[str, Dict]:
|
2025-12-02 22:36:52 +08:00
|
|
|
|
"""从Redis获取所有计算机名的账号配置"""
|
2025-12-02 22:05:54 +08:00
|
|
|
|
try:
|
2025-12-02 22:36:52 +08:00
|
|
|
|
accounts_dict = {}
|
|
|
|
|
|
|
|
|
|
|
|
# 方法1:使用配置的计算机名列表
|
|
|
|
|
|
for computer_name in self.computer_names:
|
|
|
|
|
|
accounts = self._get_accounts_by_computer_name(computer_name)
|
|
|
|
|
|
accounts_dict.update(accounts)
|
|
|
|
|
|
|
|
|
|
|
|
# 方法2:自动发现所有匹配的key(备用方案)
|
|
|
|
|
|
if not accounts_dict:
|
|
|
|
|
|
accounts_dict = self._discover_all_accounts()
|
|
|
|
|
|
|
|
|
|
|
|
logger.info(f"从 {len(self.computer_names)} 个计算机名获取到 {len(accounts_dict)} 个账号")
|
|
|
|
|
|
return accounts_dict
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"获取账户信息失败: {e}")
|
|
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
def _get_accounts_by_computer_name(self, computer_name: str) -> Dict[str, Dict]:
|
|
|
|
|
|
"""获取指定计算机名的账号"""
|
|
|
|
|
|
accounts_dict = {}
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 构建key
|
|
|
|
|
|
redis_key = f"{computer_name}_strategy_api"
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
|
|
|
|
|
# 从Redis获取数据
|
2025-12-02 22:36:52 +08:00
|
|
|
|
result = self.redis_client.client.hgetall(redis_key)
|
2025-12-02 22:05:54 +08:00
|
|
|
|
if not result:
|
2025-12-02 22:36:52 +08:00
|
|
|
|
logger.debug(f"未找到 {redis_key} 的策略API配置")
|
2025-12-02 22:05:54 +08:00
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
for exchange_name, accounts_json in result.items():
|
|
|
|
|
|
try:
|
|
|
|
|
|
accounts = json.loads(accounts_json)
|
|
|
|
|
|
if not accounts:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
# 格式化交易所ID
|
|
|
|
|
|
exchange_id = self.format_exchange_id(exchange_name)
|
|
|
|
|
|
|
|
|
|
|
|
for account_id, account_info in accounts.items():
|
|
|
|
|
|
parsed_account = self.parse_account(exchange_id, account_id, account_info)
|
|
|
|
|
|
if parsed_account:
|
2025-12-02 22:36:52 +08:00
|
|
|
|
# 添加计算机名标记
|
|
|
|
|
|
parsed_account['computer_name'] = computer_name
|
2025-12-02 22:05:54 +08:00
|
|
|
|
accounts_dict[account_id] = parsed_account
|
|
|
|
|
|
|
|
|
|
|
|
except json.JSONDecodeError as e:
|
|
|
|
|
|
logger.error(f"解析交易所 {exchange_name} 的JSON数据失败: {e}")
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
2025-12-02 22:36:52 +08:00
|
|
|
|
logger.info(f"从 {redis_key} 获取到 {len(accounts_dict)} 个账号")
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
2025-12-02 22:36:52 +08:00
|
|
|
|
logger.error(f"获取计算机名 {computer_name} 的账号失败: {e}")
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
2025-12-02 22:36:52 +08:00
|
|
|
|
return accounts_dict
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
2025-12-02 22:36:52 +08:00
|
|
|
|
def _discover_all_accounts(self) -> Dict[str, Dict]:
|
|
|
|
|
|
"""自动发现所有匹配的账号key"""
|
|
|
|
|
|
accounts_dict = {}
|
|
|
|
|
|
|
2025-12-02 22:05:54 +08:00
|
|
|
|
try:
|
2025-12-02 22:36:52 +08:00
|
|
|
|
# 获取所有匹配模式的key
|
|
|
|
|
|
pattern = f"*_strategy_api"
|
|
|
|
|
|
cursor = 0
|
2025-12-02 22:05:54 +08:00
|
|
|
|
|
2025-12-02 22:36:52 +08:00
|
|
|
|
while True:
|
|
|
|
|
|
cursor, keys = self.redis_client.client.scan(cursor, match=pattern, count=100)
|
|
|
|
|
|
|
|
|
|
|
|
for key in keys:
|
|
|
|
|
|
key_str = key.decode('utf-8') if isinstance(key, bytes) else key
|
|
|
|
|
|
|
|
|
|
|
|
# 提取计算机名
|
|
|
|
|
|
computer_name = key_str.replace('_strategy_api', '')
|
|
|
|
|
|
|
|
|
|
|
|
# 验证计算机名格式
|
|
|
|
|
|
if self.computer_name_pattern.match(computer_name):
|
|
|
|
|
|
accounts = self._get_accounts_by_computer_name(computer_name)
|
|
|
|
|
|
accounts_dict.update(accounts)
|
|
|
|
|
|
|
|
|
|
|
|
if cursor == 0:
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
logger.info(f"自动发现 {len(accounts_dict)} 个账号")
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"自动发现账号失败: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
return accounts_dict
|
|
|
|
|
|
|
|
|
|
|
|
# 其他方法保持不变...
|