|
|
|
|
|
"""
|
|
|
|
|
|
SDK连接管理器 - 保持SDK登录状态,避免重复登录
|
|
|
|
|
|
"""
|
|
|
|
|
|
import threading
|
|
|
|
|
|
import time
|
|
|
|
|
|
from typing import Optional, Dict, Any
|
|
|
|
|
|
from app.services.amazing_data_adapter import AmazingDataAdapter
|
|
|
|
|
|
from app.models.config import SDKConfig
|
|
|
|
|
|
from app.db.session import SessionLocal
|
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SDKConnectionManager:
|
|
|
|
|
|
"""
|
|
|
|
|
|
SDK连接管理器
|
|
|
|
|
|
|
|
|
|
|
|
- 保持SDK登录状态,避免重复登录
|
|
|
|
|
|
- 登录成功后,在释放前所有请求都不用重复登录
|
|
|
|
|
|
- 支持多配置管理
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
_instance = None
|
|
|
|
|
|
_lock = threading.Lock()
|
|
|
|
|
|
|
|
|
|
|
|
def __new__(cls):
|
|
|
|
|
|
if cls._instance is None:
|
|
|
|
|
|
with cls._lock:
|
|
|
|
|
|
if cls._instance is None:
|
|
|
|
|
|
cls._instance = super().__new__(cls)
|
|
|
|
|
|
cls._instance._connections: Dict[int, AmazingDataAdapter] = {}
|
|
|
|
|
|
cls._instance._connection_locks: Dict[int, threading.Lock] = {}
|
|
|
|
|
|
cls._instance._last_activity: Dict[int, float] = {}
|
|
|
|
|
|
return cls._instance
|
|
|
|
|
|
|
|
|
|
|
|
def get_connection(self, config_id: int) -> Optional[AmazingDataAdapter]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
获取SDK连接
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
config_id: 配置ID
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
AmazingDataAdapter实例,如果连接失败返回None
|
|
|
|
|
|
"""
|
|
|
|
|
|
if config_id not in self._connection_locks:
|
|
|
|
|
|
self._connection_locks[config_id] = threading.Lock()
|
|
|
|
|
|
|
|
|
|
|
|
with self._connection_locks[config_id]:
|
|
|
|
|
|
if config_id in self._connections:
|
|
|
|
|
|
adapter = self._connections[config_id]
|
|
|
|
|
|
if adapter.is_connected():
|
|
|
|
|
|
self._last_activity[config_id] = time.time()
|
|
|
|
|
|
return adapter
|
|
|
|
|
|
else:
|
|
|
|
|
|
del self._connections[config_id]
|
|
|
|
|
|
|
|
|
|
|
|
db = SessionLocal()
|
|
|
|
|
|
try:
|
|
|
|
|
|
config = db.query(SDKConfig).filter(SDKConfig.id == config_id).first()
|
|
|
|
|
|
if not config:
|
|
|
|
|
|
logger.warning(f"SDK配置不存在: {config_id}")
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
adapter = AmazingDataAdapter({
|
|
|
|
|
|
"username": config.username,
|
|
|
|
|
|
"password": config.password,
|
|
|
|
|
|
"host": config.host,
|
|
|
|
|
|
"port": config.port,
|
|
|
|
|
|
"local_path": config.local_path or "./amazing_data_cache/"
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
if adapter.connect():
|
|
|
|
|
|
self._connections[config_id] = adapter
|
|
|
|
|
|
self._last_activity[config_id] = time.time()
|
|
|
|
|
|
logger.info(f"SDK连接成功: config_id={config_id}")
|
|
|
|
|
|
return adapter
|
|
|
|
|
|
else:
|
|
|
|
|
|
logger.warning(f"SDK连接失败: config_id={config_id}")
|
|
|
|
|
|
return None
|
|
|
|
|
|
finally:
|
|
|
|
|
|
db.close()
|
|
|
|
|
|
|
|
|
|
|
|
def release_connection(self, config_id: int):
|
|
|
|
|
|
"""
|
|
|
|
|
|
释放SDK连接
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
config_id: 配置ID
|
|
|
|
|
|
"""
|
|
|
|
|
|
if config_id not in self._connection_locks:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
with self._connection_locks[config_id]:
|
|
|
|
|
|
if config_id in self._connections:
|
|
|
|
|
|
adapter = self._connections[config_id]
|
|
|
|
|
|
try:
|
|
|
|
|
|
adapter.disconnect()
|
|
|
|
|
|
logger.info(f"SDK连接已释放: config_id={config_id}")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.warning(f"释放SDK连接时出错: {e}")
|
|
|
|
|
|
del self._connections[config_id]
|
|
|
|
|
|
if config_id in self._last_activity:
|
|
|
|
|
|
del self._last_activity[config_id]
|
|
|
|
|
|
|
|
|
|
|
|
def get_default_connection(self) -> Optional[AmazingDataAdapter]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
获取默认SDK连接
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
AmazingDataAdapter实例
|
|
|
|
|
|
"""
|
|
|
|
|
|
db = SessionLocal()
|
|
|
|
|
|
try:
|
|
|
|
|
|
config = db.query(SDKConfig).filter(SDKConfig.is_default == True).first()
|
|
|
|
|
|
if not config:
|
|
|
|
|
|
config = db.query(SDKConfig).first()
|
|
|
|
|
|
if config:
|
|
|
|
|
|
return self.get_connection(config.id)
|
|
|
|
|
|
return None
|
|
|
|
|
|
finally:
|
|
|
|
|
|
db.close()
|
|
|
|
|
|
|
|
|
|
|
|
def release_all(self):
|
|
|
|
|
|
"""释放所有SDK连接"""
|
|
|
|
|
|
for config_id in list(self._connections.keys()):
|
|
|
|
|
|
self.release_connection(config_id)
|
|
|
|
|
|
|
|
|
|
|
|
def get_status(self, config_id: int) -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
获取连接状态
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
config_id: 配置ID
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
状态信息
|
|
|
|
|
|
"""
|
|
|
|
|
|
if config_id in self._connections:
|
|
|
|
|
|
adapter = self._connections[config_id]
|
|
|
|
|
|
return {
|
|
|
|
|
|
"connected": adapter.is_connected(),
|
|
|
|
|
|
"last_activity": self._last_activity.get(config_id, 0),
|
|
|
|
|
|
"config_id": config_id
|
|
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
"connected": False,
|
|
|
|
|
|
"last_activity": 0,
|
|
|
|
|
|
"config_id": config_id
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sdk_manager = SDKConnectionManager()
|