Skip to content

Commit 76ceac0

Browse files
author
Nicolás Tallar
authored
[FIX] Handle timeouts on BlockFetcher (#805)
1 parent 65c23ba commit 76ceac0

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

src/main/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcher.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class BlockFetcher(
4444
import BlockFetcher._
4545

4646
implicit val ec: ExecutionContext = context.dispatcher
47-
implicit val timeout: Timeout = syncConfig.peerResponseTimeout + 1.second // some margin for actor communication
47+
implicit val timeout: Timeout = syncConfig.peerResponseTimeout + 2.second // some margin for actor communication
4848

4949
override def receive: Receive = idle()
5050

@@ -130,7 +130,7 @@ class BlockFetcher(
130130

131131
fetchBlocks(newState)
132132
case RetryHeadersRequest if state.isFetchingHeaders =>
133-
log.debug("Time-out occurred while waiting for headers")
133+
log.debug("Something failed on a headers request, cancelling the request and re-fetching")
134134

135135
val newState = state.withHeaderFetchReceived
136136
fetchBlocks(newState)
@@ -149,7 +149,7 @@ class BlockFetcher(
149149

150150
fetchBlocks(newState)
151151
case RetryBodiesRequest if state.isFetchingBodies =>
152-
log.debug("Time-out occurred while waiting for bodies")
152+
log.debug("Something failed on a bodies request, cancelling the request and re-fetching")
153153

154154
val newState = state.withBodiesFetchReceived
155155
fetchBlocks(newState)
@@ -315,19 +315,23 @@ class BlockFetcher(
315315
private def makeRequest(request: Request[_], responseFallback: FetchMsg): Future[Any] =
316316
(peersClient ? request)
317317
.tap(blacklistPeerOnFailedRequest)
318-
.flatMap(failureTo(responseFallback))
318+
.flatMap(handleRequestResult(responseFallback))
319+
.recover { case error =>
320+
log.error(error, "Unexpected error while doing a request")
321+
responseFallback
322+
}
319323

320324
private def blacklistPeerOnFailedRequest(msg: Any): Unit = msg match {
321325
case RequestFailed(peer, reason) => peersClient ! BlacklistPeer(peer.id, reason)
322326
case _ => ()
323327
}
324328

325-
private def failureTo(fallback: FetchMsg)(msg: Any): Future[Any] = msg match {
329+
private def handleRequestResult(fallback: FetchMsg)(msg: Any): Future[Any] = msg match {
326330
case failed: RequestFailed =>
327-
log.debug("Failed request {}", failed)
331+
log.debug("Request failed due to {}", failed)
328332
Future.successful(fallback)
329333
case Failure(cause) =>
330-
log.debug("Failed request due to {}", cause)
334+
log.error(cause, "Unexpected error on the request result")
331335
Future.successful(fallback)
332336
case NoSuitablePeer =>
333337
Future.successful(fallback).delayedBy(syncConfig.syncRetryInterval)

src/test/scala/io/iohk/ethereum/blockchain/sync/regular/BlockFetcherSpec.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,24 @@ class BlockFetcherSpec extends TestKit(ActorSystem("BlockFetcherSpec_System")) w
195195
assert(HeadersSeq.areChain(headers))
196196
}
197197
}
198+
199+
"should properly handle a request timeout" in new TestSetup {
200+
override lazy val syncConfig = defaultSyncConfig.copy(
201+
// Small timeout on ask pattern for testing it here
202+
peerResponseTimeout = 1.seconds
203+
)
204+
205+
startFetcher()
206+
207+
val firstGetBlockHeadersRequest =
208+
GetBlockHeaders(Left(1), syncConfig.blockHeadersPerRequest, skip = 0, reverse = false)
209+
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == firstGetBlockHeadersRequest => () }
210+
211+
// Request should timeout without any response from the peer
212+
Thread.sleep((syncConfig.peerResponseTimeout + 2.seconds).toMillis)
213+
214+
peersClient.expectMsgPF() { case PeersClient.Request(msg, _, _) if msg == firstGetBlockHeadersRequest => () }
215+
}
198216
}
199217

200218
trait TestSetup extends TestSyncConfig {

0 commit comments

Comments
 (0)