Skip to content

Commit d7aac66

Browse files
committed
Allow setting the request information cache size:
- This was a feature that had been requested while the WebsocketProviderV2 was being developed, in beta. We did not forward-port this to the WebSocketProvider in ``v7``. relevant ``v6`` PR: #3226
1 parent 6279d99 commit d7aac66

File tree

6 files changed

+55
-7
lines changed

6 files changed

+55
-7
lines changed

docs/providers.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ Persistent Connection Base Class
233233
.. py:class:: web3.providers.persistent.PersistentConnectionProvider(\
234234
request_timeout: float = 50.0, \
235235
subscription_response_queue_size: int = 500, \
236-
silence_listener_task_exceptions: bool = False\
236+
silence_listener_task_exceptions: bool = False \
237+
max_connection_retries: int = 5, \
238+
request_information_cache_size: int = 500, \
237239
)
238240
239241
This is a base provider class, inherited by the following providers:
@@ -262,6 +264,13 @@ Persistent Connection Base Class
262264
exceptions raised by the listener task are silenced. Defaults to ``False``,
263265
raising any exceptions that occur in the listener task.
264266

267+
* ``max_connection_retries`` is the maximum number of times to retry a connection
268+
to the provider when initializing the provider. Defaults to ``5``.
269+
270+
* ``request_information_cache_size`` specifies the size of the transient cache for
271+
storing request details, enabling the provider to process responses based on the
272+
original request information. Defaults to ``500``.
273+
265274
AsyncIPCProvider
266275
++++++++++++++++
267276

newsfragments/3662.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow setting the ``request_information_cache_size`` for ``PersistentConnectionProvider`` implementations.

tests/core/providers/test_websocket_provider.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,3 +510,27 @@ async def test_websocket_provider_raises_errors_from_cache_not_tied_to_a_request
510510
with pytest.raises(Web3RPCError, match="Request shutdown"):
511511
await asyncio.sleep(0.1)
512512
await async_w3.eth.block_number
513+
514+
515+
@pytest.mark.asyncio
516+
async def test_req_info_cache_size_can_be_set_and_warns_when_full(caplog):
517+
with patch(
518+
"web3.providers.persistent.websocket.connect",
519+
new=lambda *_1, **_2: _mocked_ws_conn(),
520+
):
521+
async_w3 = await AsyncWeb3(
522+
WebSocketProvider("ws://mocked", request_information_cache_size=1)
523+
)
524+
async_w3.provider._request_processor.cache_request_information(
525+
RPCEndpoint("eth_getBlockByNumber"),
526+
["latest"],
527+
tuple(),
528+
tuple(),
529+
)
530+
531+
assert len(async_w3.provider._request_processor._request_information_cache) == 1
532+
assert (
533+
"Request information cache is full. This may result in unexpected "
534+
"behavior. Consider increasing the ``request_information_cache_size`` "
535+
"on the provider."
536+
) in caplog.text

web3/providers/persistent/persistent.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,14 @@ def __init__(
8787
subscription_response_queue_size: int = 500,
8888
silence_listener_task_exceptions: bool = False,
8989
max_connection_retries: int = 5,
90+
request_information_cache_size: int = 500,
9091
**kwargs: Any,
9192
) -> None:
9293
super().__init__(**kwargs)
9394
self._request_processor = RequestProcessor(
9495
self,
9596
subscription_response_queue_size=subscription_response_queue_size,
97+
request_information_cache_size=request_information_cache_size,
9698
)
9799
self._message_listener_task: Optional["asyncio.Task[None]"] = None
98100
self._batch_request_counter: Optional[int] = None

web3/providers/persistent/request_processor.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,12 @@ def __init__(
8585
self,
8686
provider: "PersistentConnectionProvider",
8787
subscription_response_queue_size: int = 500,
88+
request_information_cache_size: int = 500,
8889
) -> None:
8990
self._provider = provider
90-
self._request_information_cache: SimpleCache = SimpleCache(500)
91+
self._request_information_cache: SimpleCache = SimpleCache(
92+
request_information_cache_size
93+
)
9194
self._request_response_cache: SimpleCache = SimpleCache(500)
9295
self._subscription_response_queue: TaskReliantQueue[
9396
Union[RPCResponse, TaskNotRunning]
@@ -152,6 +155,12 @@ def cache_request_information(
152155
cache_key,
153156
request_info,
154157
)
158+
if self._request_information_cache.is_full():
159+
self._provider.logger.warning(
160+
"Request information cache is full. This may result in unexpected "
161+
"behavior. Consider increasing the ``request_information_cache_size`` "
162+
"on the provider."
163+
)
155164
return cache_key
156165

157166
def pop_cached_request_information(

web3/utils/caching.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ def __init__(self, size: int = 100):
2525
self._size = size
2626
self._data: OrderedDict[str, Any] = OrderedDict()
2727

28+
def __contains__(self, key: str) -> bool:
29+
return key in self._data
30+
31+
def __len__(self) -> int:
32+
return len(self._data)
33+
2834
def cache(self, key: str, value: Any) -> Tuple[Any, Dict[str, Any]]:
2935
evicted_items = {}
3036
# If the key is already in the OrderedDict just update it
@@ -59,11 +65,8 @@ def pop(self, key: str) -> Optional[Any]:
5965
def popitem(self, last: bool = True) -> Tuple[str, Any]:
6066
return self._data.popitem(last=last)
6167

62-
def __contains__(self, key: str) -> bool:
63-
return key in self._data
64-
65-
def __len__(self) -> int:
66-
return len(self._data)
68+
def is_full(self) -> bool:
69+
return len(self._data) >= self._size
6770

6871
# -- async utility methods -- #
6972

0 commit comments

Comments
 (0)