mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 10:46:42 +01:00
RpcRetryException (#274)
* Created RpcRetryException for better error messages on RpcUtil timeouts * De-duplicated RpcUtil * Ran scalafmt * Fixed an import and a version
This commit is contained in:
parent
1301336231
commit
cc04732e41
7 changed files with 81 additions and 29 deletions
|
@ -1,13 +1,14 @@
|
|||
package org.bitcoins.rpc
|
||||
package org.bitcoins.rpc.util
|
||||
|
||||
import java.io.PrintStream
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import org.bitcoins.core.util.BitcoinSLogger
|
||||
import org.bitcoins.rpc.client.BitcoindRpcClient
|
||||
|
||||
import scala.concurrent.duration.{DurationInt, FiniteDuration}
|
||||
import scala.concurrent.{Await, Future, Promise}
|
||||
|
||||
trait RpcUtil extends BitcoinSLogger {
|
||||
trait AsyncUtil extends BitcoinSLogger {
|
||||
|
||||
private def retryRunnable(
|
||||
condition: => Boolean,
|
||||
|
@ -38,10 +39,37 @@ trait RpcUtil extends BitcoinSLogger {
|
|||
conditionF: () => Future[Boolean],
|
||||
duration: FiniteDuration = 100.millis,
|
||||
maxTries: Int = 50)(implicit system: ActorSystem): Future[Unit] = {
|
||||
val stackTrace: Array[StackTraceElement] =
|
||||
Thread.currentThread().getStackTrace
|
||||
|
||||
retryUntilSatisfiedWithCounter(conditionF = conditionF,
|
||||
duration = duration,
|
||||
maxTries = maxTries)
|
||||
maxTries = maxTries,
|
||||
stackTrace = stackTrace)
|
||||
}
|
||||
|
||||
case class RpcRetryException(
|
||||
message: String,
|
||||
caller: Array[StackTraceElement])
|
||||
extends Exception(message) {
|
||||
override def printStackTrace(s: PrintStream): Unit = {
|
||||
super.printStackTrace(s)
|
||||
|
||||
val indexOfLastBitcoinSOpt = caller.reverse.zipWithIndex
|
||||
.find {
|
||||
case (element, _) =>
|
||||
element.getClassName.contains("bitcoins")
|
||||
}
|
||||
|
||||
val indexOfLastRelevantElement =
|
||||
indexOfLastBitcoinSOpt.map(_._2).getOrElse(0)
|
||||
|
||||
val relevantStackTrace =
|
||||
caller.dropRight(indexOfLastRelevantElement).drop(1)
|
||||
|
||||
s.println("Called from:")
|
||||
relevantStackTrace.foreach(element => s.println(s"\t$element"))
|
||||
}
|
||||
}
|
||||
|
||||
// Has a different name so that default values are permitted
|
||||
|
@ -49,7 +77,9 @@ trait RpcUtil extends BitcoinSLogger {
|
|||
conditionF: () => Future[Boolean],
|
||||
duration: FiniteDuration,
|
||||
counter: Int = 0,
|
||||
maxTries: Int)(implicit system: ActorSystem): Future[Unit] = {
|
||||
maxTries: Int,
|
||||
stackTrace: Array[StackTraceElement])(
|
||||
implicit system: ActorSystem): Future[Unit] = {
|
||||
|
||||
implicit val ec = system.dispatcher
|
||||
|
||||
|
@ -57,7 +87,7 @@ trait RpcUtil extends BitcoinSLogger {
|
|||
if (condition) {
|
||||
Future.successful(())
|
||||
} else if (counter == maxTries) {
|
||||
Future.failed(new RuntimeException("Condition timed out"))
|
||||
Future.failed(RpcRetryException("Condition timed out", stackTrace))
|
||||
} else {
|
||||
val p = Promise[Boolean]()
|
||||
val runnable = retryRunnable(condition, p)
|
||||
|
@ -70,7 +100,8 @@ trait RpcUtil extends BitcoinSLogger {
|
|||
retryUntilSatisfiedWithCounter(conditionF,
|
||||
duration,
|
||||
counter + 1,
|
||||
maxTries)
|
||||
maxTries,
|
||||
stackTrace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,22 +147,6 @@ trait RpcUtil extends BitcoinSLogger {
|
|||
|
||||
Await.result(f, overallTimeout)
|
||||
}
|
||||
|
||||
def awaitServer(
|
||||
server: BitcoindRpcClient,
|
||||
duration: FiniteDuration = 1.seconds,
|
||||
maxTries: Int = 50)(implicit system: ActorSystem): Unit = {
|
||||
val f = () => server.isStarted
|
||||
awaitCondition(f, duration, maxTries)
|
||||
}
|
||||
|
||||
def awaitServerShutdown(
|
||||
server: BitcoindRpcClient,
|
||||
duration: FiniteDuration = 300.milliseconds,
|
||||
maxTries: Int = 50)(implicit system: ActorSystem): Unit = {
|
||||
val f = () => !server.isStarted
|
||||
awaitCondition(f, duration, maxTries)
|
||||
}
|
||||
}
|
||||
|
||||
object RpcUtil extends RpcUtil
|
||||
object AsyncUtil extends AsyncUtil
|
27
rpc/src/main/scala/org/bitcoins/rpc/util/RpcUtil.scala
Normal file
27
rpc/src/main/scala/org/bitcoins/rpc/util/RpcUtil.scala
Normal file
|
@ -0,0 +1,27 @@
|
|||
package org.bitcoins.rpc.util
|
||||
|
||||
import akka.actor.ActorSystem
|
||||
import org.bitcoins.rpc.client.BitcoindRpcClient
|
||||
|
||||
import scala.concurrent.duration.{DurationInt, FiniteDuration}
|
||||
|
||||
trait RpcUtil extends AsyncUtil {
|
||||
|
||||
def awaitServer(
|
||||
server: BitcoindRpcClient,
|
||||
duration: FiniteDuration = 1.seconds,
|
||||
maxTries: Int = 50)(implicit system: ActorSystem): Unit = {
|
||||
val f = () => server.isStarted
|
||||
awaitCondition(f, duration, maxTries)
|
||||
}
|
||||
|
||||
def awaitServerShutdown(
|
||||
server: BitcoindRpcClient,
|
||||
duration: FiniteDuration = 300.milliseconds,
|
||||
maxTries: Int = 50)(implicit system: ActorSystem): Unit = {
|
||||
val f = () => !server.isStarted
|
||||
awaitCondition(f, duration, maxTries)
|
||||
}
|
||||
}
|
||||
|
||||
object RpcUtil extends RpcUtil
|
|
@ -7,6 +7,7 @@ import akka.testkit.TestKit
|
|||
import org.bitcoins.core.currency.Bitcoins
|
||||
import org.bitcoins.rpc.client.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.config.BitcoindInstance
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
import org.scalatest.{AsyncFlatSpec, BeforeAndAfterAll}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
|
|
@ -4,7 +4,9 @@ import java.io.File
|
|||
|
||||
import akka.actor.ActorSystem
|
||||
import akka.stream.ActorMaterializer
|
||||
import org.bitcoins.rpc.util.RpcUtil.RpcRetryException
|
||||
import org.bitcoins.rpc.client.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
import org.scalatest.{AsyncFlatSpec, BeforeAndAfterAll}
|
||||
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
@ -44,7 +46,7 @@ class RpcUtilTest extends AsyncFlatSpec with BeforeAndAfterAll {
|
|||
}
|
||||
|
||||
it should "fail if condition is false" in {
|
||||
recoverToSucceededIf[RuntimeException] {
|
||||
recoverToSucceededIf[RpcRetryException] {
|
||||
RpcUtil.retryUntilSatisfiedF(conditionF = () => Future.successful(false),
|
||||
duration = 0.millis)
|
||||
}
|
||||
|
@ -59,7 +61,7 @@ class RpcUtilTest extends AsyncFlatSpec with BeforeAndAfterAll {
|
|||
|
||||
it should "fail if there is a delay and duration is zero" in {
|
||||
val boolLater = trueLater(delay = 250)
|
||||
recoverToSucceededIf[RuntimeException] {
|
||||
recoverToSucceededIf[RpcRetryException] {
|
||||
RpcUtil.retryUntilSatisfiedF(boolLaterDoneAndTrue(boolLater),
|
||||
duration = 0.millis)
|
||||
}
|
||||
|
@ -71,7 +73,7 @@ class RpcUtilTest extends AsyncFlatSpec with BeforeAndAfterAll {
|
|||
}
|
||||
|
||||
it should "timeout if condition is false" in {
|
||||
assertThrows[RuntimeException] {
|
||||
assertThrows[RpcRetryException] {
|
||||
RpcUtil.awaitCondition(condition = () => false, duration = 0.millis)
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +88,7 @@ class RpcUtilTest extends AsyncFlatSpec with BeforeAndAfterAll {
|
|||
|
||||
it should "timeout if there is a delay and duration is zero" in {
|
||||
val boolLater = trueLater(delay = 250)
|
||||
assertThrows[RuntimeException] {
|
||||
assertThrows[RpcRetryException] {
|
||||
RpcUtil.awaitConditionF(boolLaterDoneAndTrue(boolLater),
|
||||
duration = 0.millis)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ import org.bitcoins.eclair.rpc.client.EclairRpcClient
|
|||
import org.bitcoins.eclair.rpc.config.EclairInstance
|
||||
import org.bitcoins.rpc.client.BitcoindRpcClient
|
||||
import org.bitcoins.rpc.config.{BitcoindInstance, ZmqConfig}
|
||||
import org.bitcoins.rpc.{BitcoindRpcTestUtil, RpcUtil}
|
||||
import org.bitcoins.rpc.BitcoindRpcTestUtil
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.concurrent.duration.DurationInt
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.bitcoins.rpc.config.{
|
|||
BitcoindInstance,
|
||||
ZmqConfig
|
||||
}
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
|
||||
import scala.collection.immutable.Map
|
||||
import scala.collection.JavaConverters.{asScalaSet, mapAsJavaMap}
|
||||
|
|
5
testkit/src/main/scala/org/bitcoins/util/AsyncUtil.scala
Normal file
5
testkit/src/main/scala/org/bitcoins/util/AsyncUtil.scala
Normal file
|
@ -0,0 +1,5 @@
|
|||
package org.bitcoins.util
|
||||
|
||||
trait AsyncUtil extends org.bitcoins.rpc.util.AsyncUtil
|
||||
|
||||
object AsyncUtil extends AsyncUtil
|
Loading…
Add table
Reference in a new issue