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 p2pReadyFuture = nodeMustBeStartedFuture(
executorService,
effectiveP2PAddress,
config.corda.baseDirectory / "net.corda.node.Corda.${identifier}.stdout.log",
process
) {
NodeListenProcessDeathException(

View File

@ -11,6 +11,7 @@ import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.div
import net.corda.core.internal.readText
import net.corda.core.internal.times
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.services.AttachmentFixup
@ -41,8 +42,10 @@ import rx.subjects.AsyncSubject
import java.io.InputStream
import java.net.Socket
import java.net.SocketException
import java.nio.file.Path
import java.sql.DriverManager
import java.time.Duration
import java.time.Instant
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit
import java.util.jar.JarOutputStream
@ -79,6 +82,8 @@ val FINANCE_CORDAPPS: Set<TestCordappImpl> = setOf(FINANCE_CONTRACTS_CORDAPP, FI
@JvmField
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(packageNames: Iterable<String>): Set<CustomCordapp> {
@ -172,20 +177,28 @@ fun addressMustBeBoundFuture(executorService: ScheduledExecutorService, hostAndP
}
fun nodeMustBeStartedFuture(
executorService: ScheduledExecutorService,
hostAndPort: NetworkHostAndPort,
listenProcess: Process? = null,
exception: () -> NodeListenProcessDeathException
executorService: ScheduledExecutorService,
logFile: Path,
listenProcess: Process,
exception: () -> NodeListenProcessDeathException
): CordaFuture<Unit> {
return poll(executorService, "address $hostAndPort to bind") {
if (listenProcess != null && !listenProcess.isAlive) {
val stopPolling = Instant.now().plusSeconds(SECONDS_TO_WAIT_FOR_P2P)
return poll(executorService, "process $listenProcess is running") {
if (!listenProcess.isAlive) {
throw exception()
}
try {
Socket(hostAndPort.host, hostAndPort.port).close()
Unit
} catch (_exception: SocketException) {
null
when {
logFile.readText().contains("Running P2PMessaging loop") -> {
Unit
}
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
}
}
}
}