You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.4 KiB

"""
实时数据路由
"""
from fastapi import APIRouter, Depends, Query, WebSocket, WebSocketDisconnect
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.schemas.base import ResponseModel
from app.services.realtime_service import RealtimeService
from app.core.security import get_current_user
from app.models.user import User
router = APIRouter()
@router.get("/snapshot", response_model=ResponseModel)
async def get_realtime_snapshot(
codes: str = Query(..., description="代码列表,多个用逗号分隔"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取最新快照数据"""
service = RealtimeService(db)
code_list = [c.strip() for c in codes.split(",")]
data = service.get_latest_snapshot(code_list)
return ResponseModel(data=data)
@router.post("/subscribe", response_model=ResponseModel)
async def subscribe_realtime(
codes: str = Query(..., description="代码列表,多个用逗号分隔"),
types: str = Query("snapshot", description="订阅类型: snapshot, kline"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""开始实时数据订阅"""
code_list = [c.strip() for c in codes.split(",")]
return ResponseModel(data={
"message": "订阅成功",
"codes": code_list,
"types": types.split(",")
})
@router.delete("/subscribe", response_model=ResponseModel)
async def unsubscribe_realtime(
codes: str = Query(None, description="代码列表,多个用逗号分隔,为空则取消所有"),
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""停止实时数据订阅"""
code_list = [c.strip() for c in codes.split(",")] if codes else None
return ResponseModel(data={
"message": "取消订阅成功",
"codes": code_list
})
@router.get("/subscribe/status", response_model=ResponseModel)
async def get_subscribe_status(
current_user: User = Depends(get_current_user)
):
"""获取订阅状态"""
return ResponseModel(data={
"subscribed_codes": [],
"subscribed_types": []
})
@router.websocket("/stream")
async def realtime_websocket(websocket: WebSocket):
"""WebSocket实时数据流"""
# 获取查询参数
query_params = websocket.query_params
codes_str = query_params.get("codes", "")
types_str = query_params.get("types", "snapshot")
codes = [c.strip() for c in codes_str.split(",") if c.strip()]
if not codes:
await websocket.close(code=4000, reason="Missing codes parameter")
return
# 创建数据库会话
from app.db.session import SessionLocal
db = SessionLocal()
try:
service = RealtimeService(db)
await service.subscribe_websocket(websocket, codes)
# 保持连接
while True:
try:
# 接收客户端消息(心跳检测)
data = await websocket.receive_text()
# 回复心跳
await websocket.send_json({"type": "heartbeat", "timestamp": datetime.utcnow().isoformat()})
except WebSocketDisconnect:
break
except Exception as e:
break
finally:
await service.unsubscribe_websocket(websocket, codes)
db.close()
from datetime import datetime