22import json
33import websockets
44from loguru import logger
5+ from tenacity import retry , retry_if_exception_type , wait_exponential
56import time
67
7- from pusher .config import Config
8+ from pusher .config import Config , STALE_TIMEOUT_SECONDS
9+ from pusher .exception import StaleConnection
810from pusher .price_state import PriceState , PriceUpdate
911
1012# This will be in config, but note here.
@@ -32,14 +34,13 @@ def get_subscribe_request(self, asset):
3234 async def subscribe_all (self ):
3335 await asyncio .gather (* (self .subscribe_single (hyperliquid_ws_url ) for hyperliquid_ws_url in self .hyperliquid_ws_urls ))
3436
37+ @retry (
38+ retry = retry_if_exception_type ((StaleConnection , websockets .ConnectionClosed )),
39+ wait = wait_exponential (multiplier = 1 , min = 1 , max = 10 ),
40+ reraise = True ,
41+ )
3542 async def subscribe_single (self , url ):
36- while True :
37- try :
38- await self .subscribe_single_inner (url )
39- except websockets .ConnectionClosed :
40- logger .error ("Connection to {} closed; retrying" , url )
41- except Exception as e :
42- logger .exception ("Error on {}: {}" , url , e )
43+ return await self .subscribe_single_inner (url )
4344
4445 async def subscribe_single_inner (self , url ):
4546 async with websockets .connect (url ) as ws :
@@ -48,8 +49,9 @@ async def subscribe_single_inner(self, url):
4849 logger .info ("Sent subscribe request to {}" , url )
4950
5051 # listen for updates
51- async for message in ws :
52+ while True :
5253 try :
54+ message = await asyncio .wait_for (ws .recv (), timeout = STALE_TIMEOUT_SECONDS )
5355 data = json .loads (message )
5456 channel = data .get ("channel" , None )
5557 if not channel :
@@ -62,8 +64,14 @@ async def subscribe_single_inner(self, url):
6264 self .parse_hyperliquid_ws_message (data )
6365 else :
6466 logger .error ("Received unknown channel: {}" , channel )
67+ except asyncio .TimeoutError :
68+ raise StaleConnection (f"No messages in { STALE_TIMEOUT_SECONDS } seconds, reconnecting..." )
69+ except websockets .ConnectionClosed :
70+ raise
6571 except json .JSONDecodeError as e :
6672 logger .error ("Failed to decode JSON message: {} error: {}" , message , e )
73+ except Exception as e :
74+ logger .error ("Unexpected exception: {}" , e )
6775
6876 def parse_hyperliquid_ws_message (self , message ):
6977 try :
0 commit comments