1+ import logging
2+
13from eth_typing import BlockNumber
24from gql import Client , gql
35from gql .client import AsyncClientSession
46from gql .transport .aiohttp import AIOHTTPTransport
57from graphql import DocumentNode
8+ from tenacity import RetryCallState
69
710from sw_utils .graph .decorators import retry_gql_errors
811
12+ logger = logging .getLogger (__name__ )
13+
914
1015class GraphClient :
1116 # pylint: disable=too-many-arguments,too-many-positional-arguments
@@ -28,15 +33,30 @@ def __init__(
2833 self .session : AsyncClientSession | None = None
2934
3035 async def setup (self ) -> None :
31- self .session = await self .gql_client .connect_async ()
36+ self .session = await self .gql_client .connect_async (reconnecting = True , retry_execute = False )
3237
3338 async def disconnect (self ) -> None :
3439 await self .gql_client .close_async ()
3540
3641 async def run_query (self , query : DocumentNode , params : dict | None = None ) -> dict :
3742 if not self .session :
3843 raise RuntimeError ("GraphClient session is not initialized. Call 'setup' first." )
39- retry_decorator = retry_gql_errors (delay = self .retry_timeout )
44+
45+ def log_before (retry_state : 'RetryCallState' ) -> None :
46+ if retry_state .attempt_number <= 1 :
47+ return
48+ msg = 'Retrying %s graph query, attempt %s'
49+ query_name = 'Unknown'
50+ if (
51+ query .definitions
52+ and hasattr (query .definitions [0 ], 'name' )
53+ and query .definitions [0 ].name
54+ ):
55+ query_name = query .definitions [0 ].name .value
56+ args = (query_name , retry_state .attempt_number )
57+ logger .log (logging .INFO , msg , * args )
58+
59+ retry_decorator = retry_gql_errors (delay = self .retry_timeout , before = log_before )
4060 result = await retry_decorator (self .session .execute )(query , variable_values = params )
4161 return result
4262
0 commit comments