Retry creation of ActorSystem in remoting tests #23481 (#23769)

* Retry creation of ActorSystem in remoting tests #23481

Remoting multi-jvm test rely on setting port = 0 which selects an open
port. This has a race where two of the JVMs open/close the same port
then configure their ActorSystem with it so one of them fails to start
due to the port being in use. This adds a simple retry so another port
is selected.
This commit is contained in:
Christopher Batey 2017-10-24 07:22:25 -05:00 committed by Patrik Nordwall
parent da0cfa577b
commit 70ad537af5
7 changed files with 82 additions and 34 deletions

View file

@ -8,12 +8,12 @@ import java.net.{ InetAddress, InetSocketAddress }
import com.typesafe.config.{ Config, ConfigFactory, ConfigObject }
import scala.concurrent.{ Await, Awaitable, Future }
import scala.concurrent.{ Await, Awaitable }
import scala.util.control.NonFatal
import scala.collection.immutable
import akka.actor._
import akka.util.Timeout
import akka.remote.testconductor.{ RoleName, TestConductor, TestConductorExt }
import akka.remote.testconductor.{ TestConductor, TestConductorExt }
import akka.testkit._
import akka.testkit.TestKit
import akka.testkit.TestEvent._
@ -22,6 +22,8 @@ import scala.concurrent.duration._
import akka.remote.testconductor.RoleName
import akka.actor.RootActorPath
import akka.event.{ Logging, LoggingAdapter }
import akka.remote.RemoteTransportException
import org.jboss.netty.channel.ChannelException
/**
* Configure the role names and participants of the test, including configuration settings.
@ -267,7 +269,18 @@ abstract class MultiNodeSpec(val myself: RoleName, _system: ActorSystem, _roles:
this(config.myself, actorSystemCreator(ConfigFactory.load(config.config)), config.roles, config.deployments)
def this(config: MultiNodeConfig) =
this(config, config ActorSystem(MultiNodeSpec.getCallerName(classOf[MultiNodeSpec]), config))
this(config, {
val name = MultiNodeSpec.getCallerName(classOf[MultiNodeSpec])
config
try {
ActorSystem(name, config)
} catch {
// Retry creating the system once as when using port = 0 two systems may try and use the same one.
// RTE is for aeron, CE for netty
case _: RemoteTransportException ActorSystem(name, config)
case _: ChannelException ActorSystem(name, config)
}
})
val log: LoggingAdapter = Logging(system, this.getClass)
@ -275,7 +288,7 @@ abstract class MultiNodeSpec(val myself: RoleName, _system: ActorSystem, _roles:
* Enrich `.await()` onto all Awaitables, using remaining duration from the innermost
* enclosing `within` block or QueryTimeout.
*/
implicit def awaitHelper[T](w: Awaitable[T]) = new AwaitHelper(w)
implicit def awaitHelper[T](w: Awaitable[T]): AwaitHelper[T] = new AwaitHelper(w)
class AwaitHelper[T](w: Awaitable[T]) {
def await: T = Await.result(w, remainingOr(testConductor.Settings.QueryTimeout.duration))
}