initial candle request limit, better error reporting, split up _handle_producer_connection
This commit is contained in:
@@ -26,6 +26,8 @@ async def _process_consumer_request(
|
||||
):
|
||||
type, data = request.get('type'), request.get('data')
|
||||
|
||||
logger.debug(f"Request of type {type} from {channel}")
|
||||
|
||||
# If we have a request of type SUBSCRIBE, set the topics in this channel
|
||||
if type == RPCRequestType.SUBSCRIBE:
|
||||
# If the request is empty, do nothing
|
||||
@@ -49,8 +51,16 @@ async def _process_consumer_request(
|
||||
await channel.send({"type": RPCMessageType.WHITELIST, "data": whitelist})
|
||||
|
||||
elif type == RPCRequestType.ANALYZED_DF:
|
||||
limit = None
|
||||
|
||||
if data:
|
||||
# Limit the amount of candles per dataframe to 'limit' or 1500
|
||||
limit = max(data.get('limit', 500), 1500)
|
||||
|
||||
# They requested the full historical analyzed dataframes
|
||||
analyzed_df = rpc._ws_request_analyzed_df()
|
||||
analyzed_df = rpc._ws_request_analyzed_df(limit)
|
||||
|
||||
logger.debug(f"ANALYZED_DF RESULT: {analyzed_df}")
|
||||
|
||||
# For every dataframe, send as a separate message
|
||||
for _, message in analyzed_df.items():
|
||||
@@ -65,32 +75,33 @@ async def message_endpoint(
|
||||
):
|
||||
try:
|
||||
if is_websocket_alive(ws):
|
||||
logger.info(f"Consumer connected - {ws.client}")
|
||||
|
||||
# TODO:
|
||||
# Return a channel ID, pass that instead of ws to the rest of the methods
|
||||
channel = await channel_manager.on_connect(ws)
|
||||
|
||||
logger.info(f"Consumer connected - {channel}")
|
||||
|
||||
# Keep connection open until explicitly closed, and process requests
|
||||
try:
|
||||
while not channel.is_closed():
|
||||
request = await channel.recv()
|
||||
|
||||
# Process the request here. Should this be a method of RPC?
|
||||
logger.info(f"Request: {request}")
|
||||
# Process the request here
|
||||
await _process_consumer_request(request, channel, rpc)
|
||||
|
||||
except WebSocketDisconnect:
|
||||
# Handle client disconnects
|
||||
logger.info(f"Consumer disconnected - {ws.client}")
|
||||
logger.info(f"Consumer disconnected - {channel}")
|
||||
await channel_manager.on_disconnect(ws)
|
||||
except Exception as e:
|
||||
logger.info(f"Consumer connection failed - {ws.client}")
|
||||
logger.info(f"Consumer connection failed - {channel}")
|
||||
logger.exception(e)
|
||||
# Handle cases like -
|
||||
# RuntimeError('Cannot call "send" once a closed message has been sent')
|
||||
await channel_manager.on_disconnect(ws)
|
||||
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to serve - {ws.client}")
|
||||
# Log tracebacks to keep track of what errors are happening
|
||||
logger.exception(e)
|
||||
await channel_manager.on_disconnect(ws)
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import logging
|
||||
from threading import RLock
|
||||
from typing import List, Type
|
||||
from typing import List, Optional, Type
|
||||
from uuid import uuid4
|
||||
|
||||
from freqtrade.rpc.api_server.ws.proxy import WebSocketProxy
|
||||
from freqtrade.rpc.api_server.ws.serializer import (HybridJSONWebSocketSerializer,
|
||||
@@ -19,8 +20,12 @@ class WebSocketChannel:
|
||||
def __init__(
|
||||
self,
|
||||
websocket: WebSocketType,
|
||||
channel_id: Optional[str] = None,
|
||||
serializer_cls: Type[WebSocketSerializer] = HybridJSONWebSocketSerializer
|
||||
):
|
||||
|
||||
self.channel_id = channel_id if channel_id else uuid4().hex[:8]
|
||||
|
||||
# The WebSocket object
|
||||
self._websocket = WebSocketProxy(websocket)
|
||||
# The Serializing class for the WebSocket object
|
||||
@@ -34,6 +39,13 @@ class WebSocketChannel:
|
||||
# Wrap the WebSocket in the Serializing class
|
||||
self._wrapped_ws = self._serializer_cls(self._websocket)
|
||||
|
||||
def __repr__(self):
|
||||
return f"WebSocketChannel({self.channel_id}, {self.remote_addr})"
|
||||
|
||||
@property
|
||||
def remote_addr(self):
|
||||
return self._websocket.remote_addr
|
||||
|
||||
async def send(self, data):
|
||||
"""
|
||||
Send data on the wrapped websocket
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from typing import Union
|
||||
from typing import Any, Tuple, Union
|
||||
|
||||
from fastapi import WebSocket as FastAPIWebSocket
|
||||
from websockets import WebSocketClientProtocol as WebSocket
|
||||
@@ -15,6 +15,14 @@ class WebSocketProxy:
|
||||
def __init__(self, websocket: WebSocketType):
|
||||
self._websocket: Union[FastAPIWebSocket, WebSocket] = websocket
|
||||
|
||||
@property
|
||||
def remote_addr(self) -> Tuple[Any, ...]:
|
||||
if hasattr(self._websocket, "remote_address"):
|
||||
return self._websocket.remote_address
|
||||
elif hasattr(self._websocket, "client"):
|
||||
return tuple(self._websocket.client)
|
||||
return ("unknown", 0)
|
||||
|
||||
async def send(self, data):
|
||||
"""
|
||||
Send data on the wrapped websocket
|
||||
|
Reference in New Issue
Block a user