Enforce node death on failure to register with network map (#905)

* Give up polling when result future cancelled
This commit is contained in:
Andrzej Cichocki
2017-06-28 12:07:53 +01:00
committed by GitHub
parent 83fdf678ab
commit e5395fe1b7
9 changed files with 208 additions and 56 deletions

View File

@ -6,11 +6,15 @@ import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.core.getOrThrow
import net.corda.core.messaging.startFlow
import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.ServiceType
import net.corda.core.utilities.ALICE
import net.corda.testing.driver.driver
import net.corda.node.internal.NodeStartup
import net.corda.node.services.startFlowPermission
import net.corda.nodeapi.User
import net.corda.testing.driver.ListenProcessDeathException
import net.corda.testing.driver.NetworkMapStartStrategy
import net.corda.testing.ProjectStructure.projectRootDir
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
@ -18,6 +22,7 @@ import org.junit.Test
import java.io.*
import java.nio.file.Files
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class BootTests {
@ -48,6 +53,15 @@ class BootTests {
assertEquals(1, numberOfNodesThatLogged)
}
}
@Test
fun `node quits on failure to register with network map`() {
val tooManyAdvertisedServices = (1..100).map { ServiceInfo(ServiceType.regulator.getSubType("$it")) }.toSet()
driver(networkMapStartStrategy = NetworkMapStartStrategy.Nominated(ALICE.name)) {
val future = startNode(ALICE.name, advertisedServices = tooManyAdvertisedServices)
assertFailsWith(ListenProcessDeathException::class) { future.getOrThrow() }
}
}
}
@StartableByRPC

View File

@ -118,9 +118,6 @@ open class NodeStartup(val args: Array<String>) {
logger.error("Shell failed to start", e)
}
}
} failure {
logger.error("Error during network map registration", it)
exitProcess(1)
}
node.run()
}

View File

@ -2,7 +2,7 @@ package net.corda.node.services.messaging
import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.ThreadBox
import net.corda.core.*
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.RPCOps
@ -10,9 +10,7 @@ import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.VersionInfo
import net.corda.core.node.services.PartyInfo
import net.corda.core.node.services.TransactionVerifierService
import net.corda.core.random63BitValue
import net.corda.core.serialization.opaque
import net.corda.core.success
import net.corda.core.transactions.LedgerTransaction
import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.trace
@ -236,7 +234,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
}
}
private var shutdownLatch = CountDownLatch(1)
private val shutdownLatch = CountDownLatch(1)
private fun processMessage(consumer: ClientConsumer): Boolean {
// Two possibilities here:
@ -286,6 +284,9 @@ class NodeMessagingClient(override val config: NodeConfiguration,
while (!networkMapRegistrationFuture.isDone && processMessage(consumer)) {
}
with(networkMapRegistrationFuture) {
if (isDone) getOrThrow() else andForget(log) // Trigger node shutdown here to avoid deadlock in shutdown hooks.
}
}
private fun runPostNetworkMap() {
@ -306,11 +307,14 @@ class NodeMessagingClient(override val config: NodeConfiguration,
* consume all messages via a new consumer without a filter applied.
*/
fun run(serverControl: ActiveMQServerControl) {
// Build the network map.
runPreNetworkMap(serverControl)
// Process everything else once we have the network map.
runPostNetworkMap()
shutdownLatch.countDown()
try {
// Build the network map.
runPreNetworkMap(serverControl)
// Process everything else once we have the network map.
runPostNetworkMap()
} finally {
shutdownLatch.countDown()
}
}
private fun artemisToCordaMessage(message: ClientMessage): ReceivedMessage? {