Skip to content

Commit ff1efe2

Browse files
committed
new service decorator to timeout get_contract_code
1 parent d381117 commit ff1efe2

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

p2p/cancel_token.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ async def wait_first(self,
105105
*awaitables: Awaitable[_TReturn],
106106
token: CancelToken = None,
107107
timeout: float = None) -> _TReturn:
108-
"""Wait for the first awaitable to complete, unless we timeout or the token chain is triggered.
108+
"""
109+
Wait for the first awaitable to complete, unless we timeout or the token chain is triggered.
109110
110111
The given token is chained with this service's token, so triggering either will cancel
111112
this.

p2p/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
# us.
4141
CHAIN_SPLIT_CHECK_TIMEOUT = 5 * REPLY_TIMEOUT
4242

43+
# Default timeout before giving up on a caller-initiated interaction
44+
COMPLETION_TIMEOUT = 5
45+
4346
# Types of LES Announce messages
4447
LES_ANNOUNCE_SIMPLE = 1
4548
LES_ANNOUNCE_SIGNED = 2

p2p/lightchain.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@
3838
)
3939
from p2p.cancel_token import CancelToken
4040
from p2p import protocol
41-
from p2p.constants import REPLY_TIMEOUT
41+
from p2p.constants import (
42+
COMPLETION_TIMEOUT,
43+
REPLY_TIMEOUT,
44+
)
45+
from p2p.p2p_proto import (
46+
DisconnectReason,
47+
)
4248
from p2p.peer import (
4349
LESPeer,
4450
PeerPool,
@@ -47,6 +53,7 @@
4753
from p2p.rlp import BlockBody
4854
from p2p.service import (
4955
BaseService,
56+
service_timeout,
5057
)
5158
from p2p.utils import gen_request_id
5259

@@ -144,6 +151,7 @@ async def get_account(self, block_hash: Hash32, address: Address) -> Account:
144151
return rlp.decode(rlp_account, sedes=Account)
145152

146153
@alru_cache(maxsize=1024, cache_exceptions=False)
154+
@service_timeout(COMPLETION_TIMEOUT)
147155
async def get_contract_code(self, block_hash: Hash32, address: Address) -> bytes:
148156
"""
149157
:param block_hash: find code as of the block with block_hash

p2p/service.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
from abc import ABC, abstractmethod
22
import asyncio
3+
import functools
34
import logging
4-
from typing import ( # noqa: #401
5+
from typing import (
56
Any,
67
Awaitable,
78
Callable,
8-
cast,
9+
Dict,
910
List,
1011
Optional,
11-
TypeVar,
12+
Tuple,
13+
TypeVar
14+
cast,
1215
)
1316

1417
from evm.utils.logging import TraceLogger
@@ -129,6 +132,25 @@ async def _cleanup(self) -> None:
129132
raise NotImplementedError()
130133

131134

135+
def service_timeout(timeout):
136+
"""
137+
Decorator to time out a method call.
138+
139+
:param timeout: seconds to wait before raising a timeout exception
140+
141+
:raise asyncio.futures.TimeoutError: if the call is not complete before timeout seconds
142+
"""
143+
def decorator(func):
144+
@functools.wraps(func)
145+
async def wrapped(service: BaseService, *args: Tuple, **kwargs: Dict) -> Any:
146+
return await service.wait(
147+
func(service, *args, **kwargs),
148+
timeout=timeout,
149+
)
150+
return wrapped
151+
return decorator
152+
153+
132154
class EmptyService(BaseService):
133155
async def _run(self) -> None:
134156
pass

0 commit comments

Comments
 (0)