Core¶
ConnHandler(connection_properties, max_retries=8, max_conn_retries=3, retry_wait_time=30, exponential_min_retry_wait_time=1, exponential_multiplier=1, skip_connect=False, **kwargs)
¶
Base abstract class for connection handlers. This class should not be instantiated directly.
This class should be used to handle connecting and doing queries/requests to servers. The _connect() method should be defined in subclasses as it will differ for each type of connection (SQL vs HTTP for example), or even for different types of servers (for example, in case of SQL: PostgreSQL, MySQL, MS SQL Server, etc.).
This already connects to the server unless skip_connect is set to True.
This handler implements a robust retry strategy using exponential backoff to gracefully manage connection or query failures. By default, operations are attempted up to 8 times; between failures, the wait time doubles exponentially—starting at 1 second (1s, 2s, 4s, 8s, 16s)—until it reaches a configured ceiling of 30 seconds. This approach allows for rapid recovery from momentary glitches while preventing server overload during persistent outages.
Using the default parameters the connection will fail after around 90 seconds if the server is not reachable.
Parameters:
-
(connection_properties¶ConnProperties) –Object containing connection parameters.
-
(max_retries¶int, default:8) –Number of retries that will be attempted when doing queries. Will be used in
stopparameter of tenacity.stop_after_attempt, by default 8 -
(max_conn_retries¶int, default:3) –Number of retries that will be attempted when reconnecting. Will be used in
stopparameter of tenacity.stop_after_attempt, by default 3 -
(retry_wait_time¶float, default:30) –Max time to wait between retries when reconnecting or doing queries. Will be used in
maxparameter of tenacity.wait_exponential, by default 30 -
(exponential_min_retry_wait_time¶float, default:1) –Min time to wait between retries when reconnecting or doing queries. Will be used in
minparameter of tenacity.wait_exponential, by default 1 -
(exponential_multiplier¶float, default:1) –Multiplier to use when calculating wait time between retries when reconnecting or doing queries. Will be used in
multiplierparameter of tenacity.wait_exponential, by default 1 -
(skip_connect¶bool, default:False) –If True, the connection will not be established when the object is created.
If this is set toTrue, the user will need to manually call the reconnect() method when they want to connect to the server.
By default False
-
(**kwargs¶dict, default:{}) –Just kept here for compatibility.
Source code in echo_connhandler/core.py
@validate_call
def __init__(
self,
connection_properties: ConnProperties,
max_retries: int = 8,
max_conn_retries: int = 3,
retry_wait_time: float = 30,
exponential_min_retry_wait_time: float = 1,
exponential_multiplier: float = 1,
skip_connect: bool = False,
**kwargs, # pylint: disable=unused-argument # noqa
) -> None:
"""Method that initializes the handler.
This already connects to the server unless skip_connect is set to True.
This handler implements a robust retry strategy using exponential backoff to gracefully manage connection or query failures. By default, operations are attempted up to 8 times; between failures, the wait time doubles exponentially—starting at 1 second (1s, 2s, 4s, 8s, 16s)—until it reaches a configured ceiling of 30 seconds. This approach allows for rapid recovery from momentary glitches while preventing server overload during persistent outages.
Using the default parameters the connection will fail after around 90 seconds if the server is not reachable.
Parameters
----------
connection_properties : ConnProperties
Object containing connection parameters.
max_retries : int, optional
Number of retries that will be attempted when doing queries. Will be used in `stop` parameter of tenacity.stop_after_attempt, by default 8
max_conn_retries : int, optional
Number of retries that will be attempted when reconnecting. Will be used in `stop` parameter of tenacity.stop_after_attempt, by default 3
retry_wait_time : float, optional
Max time to wait between retries when reconnecting or doing queries. Will be used in `max` parameter of tenacity.wait_exponential, by default 30
exponential_min_retry_wait_time: float, optional
Min time to wait between retries when reconnecting or doing queries. Will be used in `min` parameter of tenacity.wait_exponential, by default 1
exponential_multiplier: float, optional
Multiplier to use when calculating wait time between retries when reconnecting or doing queries. Will be used in `multiplier` parameter of tenacity.wait_exponential, by default 1
skip_connect : bool, optional
If True, the connection will not be established when the object is created.
If this is set toTrue, the user will need to manually call the reconnect() method when they want to connect to the server.
By default False
**kwargs : dict, optional
Just kept here for compatibility.
"""
# checking if the connection properties are of the correct type
if not isinstance(connection_properties, self._connprops_class):
raise TypeError(
f"connection_properties should be of type {self._connprops_class.__name__}, not {type(connection_properties).__name__}",
)
self.connection = None
self.max_retries: int = max_retries
self.max_conn_retries: int = max_conn_retries
self.retry_wait_time: float = retry_wait_time
self.exponential_min_retry_wait_time: float = exponential_min_retry_wait_time
self.exponential_multiplier: float = exponential_multiplier
self.connection_properties: ConnProperties = connection_properties
if not skip_connect:
self.reconnect()
close()
¶
Method that closes the connection.
Source code in echo_connhandler/core.py
def close(self) -> None:
"""Method that closes the connection."""
if self.connection is not None:
# try to close the connection
try:
self._close()
except Exception: # noqa
pass
finally:
# try to delete the connection
try:
del self.connection
except Exception: # noqa
pass
finally:
# set connection to None
self.connection = None
reconnect()
¶
Method to reconnect to the server.
Returns:
-
Self–ConnHandler instance now connected to the server.
Source code in echo_connhandler/core.py
def reconnect(self) -> Self:
"""Method to reconnect to the server.
Returns
-------
Self
ConnHandler instance now connected to the server.
"""
try:
self.close()
except Exception: # noqa
pass
finally:
self.connection = None
# Configure tenacity retry logic with exponential backoff
retryer = Retrying(
stop=stop_after_attempt(self.max_conn_retries + 1),
wait=wait_exponential(
multiplier=self.exponential_multiplier,
min=self.exponential_min_retry_wait_time,
max=self.retry_wait_time,
),
retry=retry_if_exception_type(Exception),
reraise=True,
before_sleep=lambda retry_state: logger.exception(
f"Attempt {retry_state.attempt_number}: Will wait {retry_state.next_action.sleep} seconds before retrying. Could not connect to server using {self.connection_properties}",
),
)
for attempt in retryer:
with attempt:
self.connection = self._connect()
return self
ConnProperties
¶
Class that holds the properties used to establish a connection to a server (SQL, HTTP, etc.).
This should be created as a dataclass holding the relevant properties for each connection. This is an abstract class so it should not be instantiated directly.