Skip to content

Commit f75348c

Browse files
committed
ETCM-168: Add timeout for waiting on deferreds. More debug logs in lookup.
1 parent feef9b2 commit f75348c

File tree

1 file changed

+44
-30
lines changed

1 file changed

+44
-30
lines changed

scalanet/discovery/src/io/iohk/scalanet/discovery/ethereum/v4/DiscoveryService.scala

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ object DiscoveryService {
407407
case false =>
408408
initBond(peer).flatMap {
409409
case Some(result) =>
410-
result.pongReceived.get
410+
result.pongReceived.get.timeoutTo(config.requestTimeout, Task.pure(false))
411411

412412
case None =>
413413
Task(logger.debug(s"Trying to bond with $peer...")) >>
@@ -433,6 +433,7 @@ object DiscoveryService {
433433
_ <- completePong(peer, responded = false)
434434
} yield false
435435
}
436+
.guarantee(stateRef.update(_.clearBondingResults(peer)))
436437
}
437438
}
438439

@@ -563,7 +564,7 @@ object DiscoveryService {
563564

564565
waitOrFetch.flatMap {
565566
case Left(wait) =>
566-
wait.get
567+
wait.get.timeoutTo(config.requestTimeout, Task.pure(None))
567568

568569
case Right(fetch) =>
569570
val maybeEnr = bond(peer).flatMap {
@@ -729,39 +730,49 @@ object DiscoveryService {
729730
case true =>
730731
rpc
731732
.findNode(peer)(target)
732-
.map(_.map(_.toList).getOrElse(Nil))
733+
.flatMap {
734+
case None =>
735+
Task(logger.debug(s"Received no response for neighbors for $target from ${peer.address}")).as(Nil)
736+
case Some(neighbors) =>
737+
Task(logger.debug(s"Received ${neighbors.size} neighbors for $target from ${peer.address}"))
738+
.as(neighbors.toList)
739+
}
733740
.flatMap { neighbors =>
734741
neighbors.filterA { neighbor =>
735742
if (neighbor.address.checkRelay(peer))
736743
Task.pure(true)
737744
else
738-
Task(logger.debug(s"Ignoring neighbor $neighbor from $peer because of invalid relay IP.")).as(false)
745+
Task(logger.debug(s"Ignoring neighbor $neighbor from ${peer.address} because of invalid relay IP."))
746+
.as(false)
739747
}
740748
}
741749
.recoverWith {
742750
case NonFatal(ex) =>
743-
Task(logger.debug(s"Failed to fetch neighbors of $target from $from: $ex")).as(Nil)
751+
Task(logger.debug(s"Failed to fetch neighbors of $target from ${peer.address}: $ex")).as(Nil)
744752
}
745753
case false =>
746-
Task(logger.debug(s"Could not bond with $from to fetch neighbors of $target")).as(Nil)
754+
Task(logger.debug(s"Could not bond with ${peer.address} to fetch neighbors of $target")).as(Nil)
747755
}
748756
}
749757

750758
// Make sure these new nodes can be bonded with before we consider them,
751759
// otherwise they might appear to be be closer to the target but actually
752760
// be fakes with unreachable addresses that could knock out legit nodes.
753-
def bondNeighbors(neighbors: Seq[Node]): Task[Seq[Node]] = {
754-
Task
755-
.parTraverseUnordered(neighbors) { neighbor =>
756-
bond(toPeer(neighbor)).flatMap {
757-
case true =>
758-
Task.pure(Some(neighbor))
759-
case false =>
760-
Task(logger.debug(s"Could not bond with neighbor candidate $neighbor")).as(None)
761+
def bondNeighbors(neighbors: Seq[Node]): Task[Seq[Node]] =
762+
for {
763+
_ <- Task(logger.debug(s"Bonding with ${neighbors.size} neighbors..."))
764+
bonded <- Task
765+
.parTraverseN(config.kademliaAlpha)(neighbors) { neighbor =>
766+
bond(toPeer(neighbor)).flatMap {
767+
case true =>
768+
Task.pure(Some(neighbor))
769+
case false =>
770+
Task(logger.debug(s"Could not bond with neighbor candidate $neighbor")).as(None)
771+
}
761772
}
762-
}
763-
.map(_.flatten)
764-
}
773+
.map(_.flatten)
774+
_ <- Task(logger.debug(s"Bonded with ${bonded.size} neighbors out of ${neighbors.size}."))
775+
} yield bonded
765776

766777
def loop(
767778
local: Node,
@@ -775,18 +786,19 @@ object DiscoveryService {
775786
.take(config.kademliaAlpha)
776787
.toList
777788

778-
if (contacts.isEmpty)
779-
Task.pure(closest)
780-
else {
781-
Task
782-
.parTraverseUnordered(contacts)(fetchNeighbors)
783-
.map(_.flatten.distinct)
784-
.flatMap(bondNeighbors)
785-
.flatMap { newNeighbors =>
786-
val newClosest = (closest ++ newNeighbors).take(config.kademliaBucketSize)
787-
val newAsked = asked ++ contacts
788-
loop(local, newClosest, newAsked)
789-
}
789+
if (contacts.isEmpty) {
790+
Task(logger.debug(s"Lookup finished for $target after asking ${asked.size} nodes.")).as(closest)
791+
} else {
792+
Task(logger.debug(s"Lookup for $target contacting ${contacts.size} nodes.")) >>
793+
Task
794+
.parTraverseUnordered(contacts)(fetchNeighbors)
795+
.map(_.flatten.distinct)
796+
.flatMap(bondNeighbors)
797+
.flatMap { newNeighbors =>
798+
val newClosest = (closest ++ newNeighbors).take(config.kademliaBucketSize)
799+
val newAsked = asked ++ contacts
800+
loop(local, newClosest, newAsked)
801+
}
790802
}
791803
}
792804

@@ -825,7 +837,9 @@ object DiscoveryService {
825837
_ <- Task(
826838
logger.info(s"Successfully enrolled with $enrolled bootstrap nodes. Performing initial lookup...")
827839
)
828-
_ <- lookup(nodeId)
840+
_ <- lookup(nodeId).doOnFinish {
841+
_.fold(Task.unit)(ex => Task(logger.error(s"Error during initial lookup", ex)))
842+
}
829843
nodeCount <- stateRef.get.map(_.nodeMap.size)
830844
_ <- Task(logger.info(s"Discovered $nodeCount nodes by the end of the lookup."))
831845
} yield ()

0 commit comments

Comments
 (0)