Implement sharing of actor systems across the GUI and backend app server (#3220)

* Implement sharing of actor systems across the GUI and backend app server

* Add timestamp to system names

* Fix test case
This commit is contained in:
Chris Stewart 2021-06-07 11:38:33 -05:00 committed by GitHub
parent fc5bb956dc
commit a61c11acfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 118 additions and 78 deletions

View file

@ -1,5 +1,6 @@
package org.bitcoins.bundle.gui package org.bitcoins.bundle.gui
import akka.actor.ActorSystem
import org.bitcoins.gui._ import org.bitcoins.gui._
import org.bitcoins.node.NodeType import org.bitcoins.node.NodeType
import org.bitcoins.server.BitcoinSAppConfig import org.bitcoins.server.BitcoinSAppConfig
@ -12,7 +13,7 @@ import scalafx.scene.text._
import scala.concurrent.ExecutionContext.global import scala.concurrent.ExecutionContext.global
import scala.util.Try import scala.util.Try
class LandingPane(glassPane: VBox) { class LandingPane(glassPane: VBox)(implicit system: ActorSystem) {
val appConfig: BitcoinSAppConfig = val appConfig: BitcoinSAppConfig =
BitcoinSAppConfig.fromDefaultDatadir()(global) BitcoinSAppConfig.fromDefaultDatadir()(global)

View file

@ -1,5 +1,6 @@
package org.bitcoins.bundle.gui package org.bitcoins.bundle.gui
import akka.actor.ActorSystem
import com.typesafe.config._ import com.typesafe.config._
import org.bitcoins.bundle.gui.BundleGUI._ import org.bitcoins.bundle.gui.BundleGUI._
import org.bitcoins.gui._ import org.bitcoins.gui._
@ -14,7 +15,7 @@ import scala.concurrent.duration.DurationInt
import scala.concurrent.{Await, Promise} import scala.concurrent.{Await, Promise}
import scala.jdk.CollectionConverters._ import scala.jdk.CollectionConverters._
class LandingPaneModel() { class LandingPaneModel()(implicit system: ActorSystem) {
var taskRunner: TaskRunner = _ var taskRunner: TaskRunner = _
// Sadly, it is a Java "pattern" to pass null into // Sadly, it is a Java "pattern" to pass null into
@ -48,7 +49,9 @@ class LandingPaneModel() {
changeToWalletGUIScene() changeToWalletGUIScene()
promise.success(()) promise.success(())
}(global) }(global)
BitcoinSServerMain.main(args.toArray)
//use class base constructor to share the actor system
new BitcoinSServerMain(args.toArray).run()
Await.result(promise.future, 60.seconds) Await.result(promise.future, 60.seconds)
} }

View file

@ -1,15 +1,16 @@
package org.bitcoins.oracle.server package org.bitcoins.oracle.server
import akka.actor.ActorSystem
import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig
import org.bitcoins.server.routes.{BitcoinSRunner, Server} import org.bitcoins.server.routes.{BitcoinSRunner, Server}
import org.bitcoins.server.util.BitcoinSApp
import scala.concurrent.Future import scala.concurrent.Future
class OracleServerMain(override val args: Array[String]) class OracleServerMain(override val args: Array[String])(implicit
override val system: ActorSystem)
extends BitcoinSRunner { extends BitcoinSRunner {
override val actorSystemName = "bitcoin-s-oracle"
implicit val conf: DLCOracleAppConfig = implicit val conf: DLCOracleAppConfig =
DLCOracleAppConfig(datadir, baseConfig) DLCOracleAppConfig(datadir, baseConfig)
@ -58,6 +59,9 @@ class OracleServerMain(override val args: Array[String])
} }
} }
object OracleServerMain extends App { object OracleServerMain extends BitcoinSApp {
override val actorSystemName =
s"bitcoin-s-oracle-${System.currentTimeMillis()}"
new OracleServerMain(args).run(Some("oracle")) new OracleServerMain(args).run(Some("oracle"))
} }

View file

@ -1,12 +1,14 @@
package org.bitcoins.scripts package org.bitcoins.scripts
import akka.NotUsed import akka.NotUsed
import akka.actor.ActorSystem
import akka.stream.scaladsl.{Keep, Sink, Source} import akka.stream.scaladsl.{Keep, Sink, Source}
import org.bitcoins.core.protocol.blockchain.Block import org.bitcoins.core.protocol.blockchain.Block
import org.bitcoins.core.protocol.transaction.WitnessTransaction import org.bitcoins.core.protocol.transaction.WitnessTransaction
import org.bitcoins.rpc.client.common.BitcoindRpcClient import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.server.BitcoindRpcAppConfig import org.bitcoins.server.BitcoindRpcAppConfig
import org.bitcoins.server.routes.BitcoinSRunner import org.bitcoins.server.routes.BitcoinSRunner
import org.bitcoins.server.util.BitcoinSApp
import scala.concurrent.Future import scala.concurrent.Future
@ -15,8 +17,9 @@ import scala.concurrent.Future
* between bitcoin-s and bitcoind inside of bitcoin-s.conf * between bitcoin-s and bitcoind inside of bitcoin-s.conf
* @see https://bitcoin-s.org/docs/config/configuration#example-configuration-file * @see https://bitcoin-s.org/docs/config/configuration#example-configuration-file
*/ */
class ScanBitcoind(override val args: Array[String]) extends BitcoinSRunner { class ScanBitcoind(override val args: Array[String])(implicit
override val actorSystemName = "scan-bitcoind" override val system: ActorSystem)
extends BitcoinSRunner {
implicit val rpcAppConfig: BitcoindRpcAppConfig = implicit val rpcAppConfig: BitcoindRpcAppConfig =
BitcoindRpcAppConfig(datadir, baseConfig) BitcoindRpcAppConfig(datadir, baseConfig)
@ -93,6 +96,9 @@ class ScanBitcoind(override val args: Array[String]) extends BitcoinSRunner {
} }
} }
object ScanBitcoind extends App { object ScanBitcoind extends BitcoinSApp {
override val actorSystemName: String =
s"scan-bitcoind-${System.currentTimeMillis()}"
new ScanBitcoind(args).run() new ScanBitcoind(args).run()
} }

View file

@ -1,15 +1,17 @@
package org.bitcoins.scripts package org.bitcoins.scripts
import akka.actor.ActorSystem
import org.bitcoins.server.BitcoinSAppConfig import org.bitcoins.server.BitcoinSAppConfig
import org.bitcoins.server.routes.BitcoinSRunner import org.bitcoins.server.routes.BitcoinSRunner
import org.bitcoins.server.util.BitcoinSApp
import java.nio.file.Paths import java.nio.file.Paths
import scala.concurrent.Future import scala.concurrent.Future
/** This script zips your $HOME/.bitcoin-s/ directory to a specified path, excluding chaindb.sqlite */ /** This script zips your $HOME/.bitcoin-s/ directory to a specified path, excluding chaindb.sqlite */
class ZipDatadir(override val args: Array[String]) extends BitcoinSRunner { class ZipDatadir(override val args: Array[String])(implicit
override val system: ActorSystem)
override def actorSystemName: String = "Zip-datadir" extends BitcoinSRunner {
implicit lazy val conf: BitcoinSAppConfig = implicit lazy val conf: BitcoinSAppConfig =
BitcoinSAppConfig(datadir, baseConfig) BitcoinSAppConfig(datadir, baseConfig)
@ -28,6 +30,9 @@ class ZipDatadir(override val args: Array[String]) extends BitcoinSRunner {
override def stop(): Future[Unit] = Future.unit override def stop(): Future[Unit] = Future.unit
} }
object Zip extends App { object Zip extends BitcoinSApp {
override val actorSystemName: String =
s"zip-datadir-${System.currentTimeMillis()}"
new ZipDatadir(args).run() new ZipDatadir(args).run()
} }

View file

@ -16,13 +16,8 @@ trait BitcoinSRunner extends StartStopAsync[Unit] with Logging {
protected def args: Array[String] protected def args: Array[String]
def actorSystemName: String implicit def system: ActorSystem
implicit lazy val system: ActorSystem = {
val system = ActorSystem(actorSystemName, baseConfig)
system.log.info("Akka started")
system
}
implicit lazy val ec: ExecutionContext = system.dispatcher implicit lazy val ec: ExecutionContext = system.dispatcher
lazy val argsWithIndex: Vector[(String, Int)] = args.toVector.zipWithIndex lazy val argsWithIndex: Vector[(String, Int)] = args.toVector.zipWithIndex

View file

@ -0,0 +1,9 @@
package org.bitcoins.server.util
import akka.actor.ActorSystem
trait BitcoinSApp extends App {
def actorSystemName: String
implicit lazy val system: ActorSystem = ActorSystem(actorSystemName)
}

View file

@ -0,0 +1,67 @@
package org.bitcoins.server
import org.bitcoins.rpc.client.common.BitcoindVersion
import org.bitcoins.rpc.util.RpcUtil
import org.bitcoins.testkit.BitcoinSTestAppConfig
import org.bitcoins.testkit.fixtures.BitcoinSFixture
import org.bitcoins.testkit.util.{AkkaUtil, BitcoinSAsyncTest}
import scala.concurrent.duration.DurationInt
import java.nio.file.Files
import scala.reflect.io.Directory
class LogLocationTest extends BitcoinSAsyncTest {
behavior of "LogLocationTest"
it must "start up and log to the correct location" in {
val datadir = BitcoinSTestAppConfig.tmpDir()
val directory = new Directory(datadir.toFile)
val confFile = datadir.resolve("bitcoin-s.conf")
for {
bitcoind <-
BitcoinSFixture.createBitcoindWithFunds(Some(BitcoindVersion.V21))
// Make it so we connect to the correct bitcoind
port = bitcoind.instance.uri.getPort
confStr = s"""bitcoin-s.node.peers = ["localhost:$port"]"""
_ = Files.write(confFile, confStr.getBytes)
// Add config options
randPort = RpcUtil.randomPort
args = Array("--datadir",
datadir.toAbsolutePath.toString,
"--rpcport",
randPort.toString)
main = new BitcoinSServerMain(args)
// Start the server in a separate thread
runnable = new Runnable {
override def run(): Unit = {
main.run()
}
}
thread = new Thread(runnable)
_ = thread.start()
// Wait for the server to have successfully started up
_ <- AkkaUtil.nonBlockingSleep(1.second)
binding <- BitcoinSServer.startedF
// Stop the server
_ <- bitcoind.stop()
_ <- binding.terminate(5.seconds)
_ = thread.interrupt()
_ <- main.stop()
} yield {
// Cleanup
directory.deleteRecursively()
val expectedDir = datadir.resolve("regtest")
// Check the log location was correctly set
assert(
System.getProperty("bitcoins.log.location") == expectedDir.toString)
}
}
}

View file

@ -1,13 +1,10 @@
package org.bitcoins.server package org.bitcoins.server
import org.bitcoins.rpc.client.common.BitcoindVersion
import org.bitcoins.rpc.util.RpcUtil import org.bitcoins.rpc.util.RpcUtil
import org.bitcoins.testkit.BitcoinSTestAppConfig import org.bitcoins.testkit.BitcoinSTestAppConfig
import org.bitcoins.testkit.fixtures.BitcoinSFixture
import org.bitcoins.testkit.util.{AkkaUtil, BitcoinSAsyncTest} import org.bitcoins.testkit.util.{AkkaUtil, BitcoinSAsyncTest}
import org.scalatest.Assertion import org.scalatest.Assertion
import java.nio.file._
import scala.concurrent.Future import scala.concurrent.Future
import scala.concurrent.duration.DurationInt import scala.concurrent.duration.DurationInt
import scala.reflect.io.Directory import scala.reflect.io.Directory
@ -54,55 +51,4 @@ class ServerRunTest extends BitcoinSAsyncTest {
} yield succeed } yield succeed
} }
it must "start up and log to the correct location" in {
val datadir = BitcoinSTestAppConfig.tmpDir()
val directory = new Directory(datadir.toFile)
val confFile = datadir.resolve("bitcoin-s.conf")
for {
bitcoind <-
BitcoinSFixture.createBitcoindWithFunds(Some(BitcoindVersion.V21))
// Make it so we connect to the correct bitcoind
port = bitcoind.instance.uri.getPort
confStr = s"""bitcoin-s.node.peers = ["localhost:$port"]"""
_ = Files.write(confFile, confStr.getBytes)
// Add config options
randPort = RpcUtil.randomPort
args = Array("--datadir",
datadir.toAbsolutePath.toString,
"--rpcport",
randPort.toString)
main = new BitcoinSServerMain(args)
// Start the server in a separate thread
runnable = new Runnable {
override def run(): Unit = {
main.run()
}
}
thread = new Thread(runnable)
_ = thread.start()
// Wait for the server to have successfully started up
_ <- AkkaUtil.nonBlockingSleep(1.second)
binding <- BitcoinSServer.startedF
// Stop the server
_ <- bitcoind.stop()
_ <- binding.terminate(5.seconds)
_ = thread.interrupt()
_ <- main.stop()
} yield {
// Cleanup
directory.deleteRecursively()
val expectedDir = datadir.resolve("regtest")
// Check the log location was correctly set
assert(
System.getProperty("bitcoins.log.location") == expectedDir.toString)
}
}
} }

View file

@ -21,16 +21,16 @@ import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.models.Peer import org.bitcoins.node.models.Peer
import org.bitcoins.rpc.config.ZmqConfig import org.bitcoins.rpc.config.ZmqConfig
import org.bitcoins.server.routes.{BitcoinSRunner, Server} import org.bitcoins.server.routes.{BitcoinSRunner, Server}
import org.bitcoins.server.util.BitcoinSApp
import org.bitcoins.wallet.Wallet import org.bitcoins.wallet.Wallet
import org.bitcoins.wallet.config.WalletAppConfig import org.bitcoins.wallet.config.WalletAppConfig
import scala.concurrent.{ExecutionContext, Future, Promise} import scala.concurrent.{ExecutionContext, Future, Promise}
class BitcoinSServerMain(override val args: Array[String]) class BitcoinSServerMain(override val args: Array[String])(implicit
override val system: ActorSystem)
extends BitcoinSRunner { extends BitcoinSRunner {
override val actorSystemName = "bitcoin-s-server"
implicit lazy val conf: BitcoinSAppConfig = implicit lazy val conf: BitcoinSAppConfig =
BitcoinSAppConfig(datadir, baseConfig) BitcoinSAppConfig(datadir, baseConfig)
@ -374,7 +374,11 @@ class BitcoinSServerMain(override val args: Array[String])
} }
} }
object BitcoinSServerMain extends App { object BitcoinSServerMain extends BitcoinSApp {
override val actorSystemName =
s"bitcoin-s-server-${System.currentTimeMillis()}"
new BitcoinSServerMain(args).run() new BitcoinSServerMain(args).run()
} }