From 1c82ade9bca569f95b39327dae5a9906338d654a Mon Sep 17 00:00:00 2001 From: bdhimes Date: Wed, 8 Oct 2025 15:56:21 +0200 Subject: [PATCH 1/2] Allows AsyncSubstrateInterface's Websocket connection to not automatically shut down For niche use-cases such as long-running processes which should never die. --- async_substrate_interface/async_substrate.py | 32 +++++++++++--------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/async_substrate_interface/async_substrate.py b/async_substrate_interface/async_substrate.py index 6416f66..283d438 100644 --- a/async_substrate_interface/async_substrate.py +++ b/async_substrate_interface/async_substrate.py @@ -526,9 +526,9 @@ class Websocket: def __init__( self, ws_url: str, - max_subscriptions=1024, - max_connections=100, - shutdown_timer=5, + max_subscriptions: int = 1024, + max_connections: int = 100, + shutdown_timer: Optional[float] = 5.0, options: Optional[dict] = None, _log_raw_websockets: bool = False, retry_timeout: float = 60.0, @@ -542,7 +542,9 @@ def __init__( ws_url: Websocket URL to connect to max_subscriptions: Maximum number of subscriptions per websocket connection max_connections: Maximum number of connections total - shutdown_timer: Number of seconds to shut down websocket connection after last use + shutdown_timer: Number of seconds to shut down websocket connection after last use. If set to `None`, the + connection will never be automatically shut down. Use this for very long-running processes, where you + will manually shut down the connection if ever you intend to close it. options: Options to pass to the websocket connection _log_raw_websockets: Whether to log raw websockets in the "raw_websocket" logger retry_timeout: Timeout in seconds to retry websocket connection @@ -661,15 +663,16 @@ async def _handler(self, ws: ClientConnection) -> Union[None, Exception]: return e async def __aexit__(self, exc_type, exc_val, exc_tb): - if not self.state != State.CONNECTING: - if self._exit_task is not None: - self._exit_task.cancel() - try: - await self._exit_task - except asyncio.CancelledError: - pass - if self.ws is not None: - self._exit_task = asyncio.create_task(self._exit_with_timer()) + if self.shutdown_timer is not None: + if not self.state != State.CONNECTING: + if self._exit_task is not None: + self._exit_task.cancel() + try: + await self._exit_task + except asyncio.CancelledError: + pass + if self.ws is not None: + self._exit_task = asyncio.create_task(self._exit_with_timer()) async def _exit_with_timer(self): """ @@ -677,7 +680,8 @@ async def _exit_with_timer(self): for reuse of the websocket connection. """ try: - await asyncio.sleep(self.shutdown_timer) + if self.shutdown_timer is not None: + await asyncio.sleep(self.shutdown_timer) await self.shutdown() except asyncio.CancelledError: pass From d47af8807833853854551b44a0621dcc60756e5b Mon Sep 17 00:00:00 2001 From: bdhimes Date: Wed, 8 Oct 2025 16:02:50 +0200 Subject: [PATCH 2/2] Return path --- async_substrate_interface/async_substrate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/async_substrate_interface/async_substrate.py b/async_substrate_interface/async_substrate.py index 283d438..e004ac7 100644 --- a/async_substrate_interface/async_substrate.py +++ b/async_substrate_interface/async_substrate.py @@ -661,6 +661,7 @@ async def _handler(self, ws: ClientConnection) -> Union[None, Exception]: return e elif isinstance(e := send_task.result(), Exception): return e + return None async def __aexit__(self, exc_type, exc_val, exc_tb): if self.shutdown_timer is not None: