INFRA-429: Wait for log file to indicate that the process is running (#6433)

Wait for log file to indicate that a driver node process is running, instead of trying to open a socket on the port the node is attempting to binding on. This means the driver is more responsive to the node being ready, as well as removing a race condition where the binding test could block the node from starting.

As sometimes nodes do not log this information, after 20 seconds we presume the node is up.
This commit is contained in:
Yiftach Kaplan 2020-07-13 11:42:30 +01:00 committed by GitHub
parent e684cfd1e6
commit 79b75ff1ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 12 deletions

View File

@ -729,7 +729,7 @@ class DriverDSLImpl(
val effectiveP2PAddress = config.corda.messagingServerAddress ?: config.corda.p2pAddress val effectiveP2PAddress = config.corda.messagingServerAddress ?: config.corda.p2pAddress
val p2pReadyFuture = nodeMustBeStartedFuture( val p2pReadyFuture = nodeMustBeStartedFuture(
executorService, executorService,
effectiveP2PAddress, config.corda.baseDirectory / "net.corda.node.Corda.${identifier}.stdout.log",
process process
) { ) {
NodeListenProcessDeathException( NodeListenProcessDeathException(

View File

@ -11,6 +11,7 @@ import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.VisibleForTesting import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.concurrent.openFuture import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.readText
import net.corda.core.internal.times import net.corda.core.internal.times
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.services.AttachmentFixup import net.corda.core.node.services.AttachmentFixup
@ -41,8 +42,10 @@ import rx.subjects.AsyncSubject
import java.io.InputStream import java.io.InputStream
import java.net.Socket import java.net.Socket
import java.net.SocketException import java.net.SocketException
import java.nio.file.Path
import java.sql.DriverManager import java.sql.DriverManager
import java.time.Duration import java.time.Duration
import java.time.Instant
import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
@ -79,6 +82,8 @@ val FINANCE_CORDAPPS: Set<TestCordappImpl> = setOf(FINANCE_CONTRACTS_CORDAPP, FI
@JvmField @JvmField
val DUMMY_CONTRACTS_CORDAPP: CustomCordapp = cordappWithPackages("net.corda.testing.contracts") val DUMMY_CONTRACTS_CORDAPP: CustomCordapp = cordappWithPackages("net.corda.testing.contracts")
private const val SECONDS_TO_WAIT_FOR_P2P: Long = 20
fun cordappsForPackages(vararg packageNames: String): Set<CustomCordapp> = cordappsForPackages(packageNames.asList()) fun cordappsForPackages(vararg packageNames: String): Set<CustomCordapp> = cordappsForPackages(packageNames.asList())
fun cordappsForPackages(packageNames: Iterable<String>): Set<CustomCordapp> { fun cordappsForPackages(packageNames: Iterable<String>): Set<CustomCordapp> {
@ -173,21 +178,29 @@ fun addressMustBeBoundFuture(executorService: ScheduledExecutorService, hostAndP
fun nodeMustBeStartedFuture( fun nodeMustBeStartedFuture(
executorService: ScheduledExecutorService, executorService: ScheduledExecutorService,
hostAndPort: NetworkHostAndPort, logFile: Path,
listenProcess: Process? = null, listenProcess: Process,
exception: () -> NodeListenProcessDeathException exception: () -> NodeListenProcessDeathException
): CordaFuture<Unit> { ): CordaFuture<Unit> {
return poll(executorService, "address $hostAndPort to bind") { val stopPolling = Instant.now().plusSeconds(SECONDS_TO_WAIT_FOR_P2P)
if (listenProcess != null && !listenProcess.isAlive) { return poll(executorService, "process $listenProcess is running") {
if (!listenProcess.isAlive) {
throw exception() throw exception()
} }
try { when {
Socket(hostAndPort.host, hostAndPort.port).close() logFile.readText().contains("Running P2PMessaging loop") -> {
Unit Unit
} catch (_exception: SocketException) { }
Instant.now().isAfter(stopPolling) -> {
// Waited for 20 seconds and the log file did not indicate that the PWP loop is running.
// This could be because the log is disabled, so lets try to create a client anyway.
Unit
}
else -> {
null null
} }
} }
}
} }
/* /*