Skip to content

Commit

Permalink
Make EthereumClient timeouts configurable via envvars
Browse files Browse the repository at this point in the history
  • Loading branch information
Uxio0 committed Mar 16, 2022
1 parent f51fc5e commit 2ad38b0
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 16 deletions.
5 changes: 5 additions & 0 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ If you want to use the underlying `web3.py <https://github.com/ethereum/web3.py>
eip1559_tx = ethereum_client.set_eip1559_fees(legacy_tx, tx_speed=TxSpeed.NORMAL)
You can modify timeouts (in seconds) for the RPC endpoints by setting
`ETHEREUM_RPC_TIMEOUT` and `ETHEREUM_RPC_SLOW_TIMEOUT` as environment variables.

By default every RPC request will be retried `3` times. You can modify that by setting `ETHEREUM_RPC_RETRY_COUNT`.


gnosis.eth.constants
~~~~~~~~~~~~~~~~~~~~
Expand Down
46 changes: 31 additions & 15 deletions gnosis/eth/ethereum_client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from enum import Enum
from functools import wraps
from logging import getLogger
Expand Down Expand Up @@ -186,7 +187,14 @@ def __new__(cls):
if not hasattr(cls, "instance"):
from django.conf import settings

cls.instance = EthereumClient(settings.ETHEREUM_NODE_URL)
cls.instance = EthereumClient(
settings.ETHEREUM_NODE_URL,
provider_timeout=int(os.environ.get("ETHEREUM_RPC_TIMEOUT", 10)),
slow_provider_timeout=int(
os.environ.get("ETHEREUM_RPC_SLOW_TIMEOUT", 60)
),
retry_count=int(os.environ.get("ETHEREUM_RPC_RETRY_COUNT", 60)),
)
return cls.instance


Expand All @@ -197,7 +205,7 @@ def __init__(self, ethereum_client: "EthereumClient"):
self.w3 = ethereum_client.w3
self.slow_w3 = ethereum_client.slow_w3
self.http_session = ethereum_client.http_session
self.timeout = ethereum_client.timeout
self.slow_timeout = ethereum_client.timeout


class BatchCallManager(EthereumClientManager):
Expand Down Expand Up @@ -247,7 +255,7 @@ def batch_call_custom(
)

response = self.http_session.post(
self.ethereum_node_url, json=queries, timeout=self.timeout
self.ethereum_node_url, json=queries, timeout=self.slow_timeout
)
if not response.ok:
raise ConnectionError(
Expand Down Expand Up @@ -545,7 +553,9 @@ def get_info(self, erc20_address: str) -> Erc20Info:
for i, data in enumerate(datas)
]
response = self.http_session.post(
self.ethereum_client.ethereum_node_url, json=payload, timeout=self.timeout
self.ethereum_client.ethereum_node_url,
json=payload,
timeout=self.slow_timeout,
)
if not response.ok:
raise InvalidERC20Info(response.content)
Expand Down Expand Up @@ -1068,7 +1078,7 @@ def trace_blocks(
for i, block_identifier in enumerate(block_identifiers)
]
response = self.http_session.post(
self.ethereum_node_url, json=payload, timeout=self.timeout
self.ethereum_node_url, json=payload, timeout=self.slow_timeout
)
if not response.ok:
message = (
Expand Down Expand Up @@ -1126,7 +1136,7 @@ def trace_transactions(
for i, tx_hash in enumerate(tx_hashes)
]
response = self.http_session.post(
self.ethereum_node_url, json=payload, timeout=self.timeout
self.ethereum_node_url, json=payload, timeout=self.slow_timeout
)
if not response.ok:
message = (
Expand Down Expand Up @@ -1267,17 +1277,23 @@ class EthereumClient:
def __init__(
self,
ethereum_node_url: URI = URI("http://localhost:8545"),
provider_timeout: int = 15,
slow_provider_timeout: int = 60,
retry_count: int = 3,
):
"""
:param ethereum_node_url: Ethereum RPC uri
:param slow_provider_timeout: Timeout for slow and custom queries
:param slow_provider_timeout: Timeout for regular RPC queries
:param slow_provider_timeout: Timeout for slow (tracing, logs...) and custom RPC queries
"""
self.http_session = self._prepare_http_session()
self.http_session = self._prepare_http_session(retry_count)
self.ethereum_node_url: str = ethereum_node_url
self.timeout = slow_provider_timeout
self.timeout = provider_timeout
self.slow_timeout = slow_provider_timeout
self.w3_provider = HTTPProvider(
self.ethereum_node_url, session=self.http_session
self.ethereum_node_url,
request_kwargs={"timeout": provider_timeout},
session=self.http_session,
)
self.w3_slow_provider = HTTPProvider(
self.ethereum_node_url,
Expand All @@ -1300,7 +1316,7 @@ def __init__(
def __str__(self):
return f"EthereumClient for url={self.ethereum_node_url}"

def _prepare_http_session(self) -> requests.Session:
def _prepare_http_session(self, retry_count: int) -> requests.Session:
"""
Prepare http session with custom pooling. See:
https://urllib3.readthedocs.io/en/stable/advanced-usage.html
Expand All @@ -1311,7 +1327,7 @@ def _prepare_http_session(self) -> requests.Session:
adapter = requests.adapters.HTTPAdapter(
pool_connections=1, # Doing all the connections to the same url
pool_maxsize=100, # Number of concurrent connections
max_retries=3, # Nodes are not very responsive some times
max_retries=retry_count, # Nodes are not very responsive some times
pool_block=False,
)
session.mount("http://", adapter)
Expand Down Expand Up @@ -1618,7 +1634,7 @@ def get_transactions(self, tx_hashes: List[EthereumHash]) -> List[Optional[TxDat
for i, tx_hash in enumerate(tx_hashes)
]
results = self.http_session.post(
self.ethereum_node_url, json=payload, timeout=self.timeout
self.ethereum_node_url, json=payload, timeout=self.slow_timeout
).json()
txs = []
for result in sorted(results, key=lambda x: x["id"]):
Expand Down Expand Up @@ -1667,7 +1683,7 @@ def get_transaction_receipts(
for i, tx_hash in enumerate(tx_hashes)
]
results = self.http_session.post(
self.ethereum_node_url, json=payload, timeout=self.timeout
self.ethereum_node_url, json=payload, timeout=self.slow_timeout
).json()
receipts = []
for result in sorted(results, key=lambda x: x["id"]):
Expand Down Expand Up @@ -1719,7 +1735,7 @@ def get_blocks(
for i, block_identifier in enumerate(block_identifiers)
]
results = self.http_session.post(
self.ethereum_node_url, json=payload, timeout=self.timeout
self.ethereum_node_url, json=payload, timeout=self.slow_timeout
).json()
blocks = []
for result in sorted(results, key=lambda x: x["id"]):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

setup(
name="gnosis-py",
version="3.8.2",
version="3.8.3",
packages=find_packages(),
package_data={"gnosis": ["py.typed"]},
install_requires=requirements,
Expand Down

0 comments on commit 2ad38b0

Please sign in to comment.