Better indicator of ActorRefProvider implementation selection (#27012)

This commit is contained in:
Helena Edelson 2019-05-29 12:01:02 -07:00 committed by GitHub
parent bb2b59d7c2
commit 9f19e4972b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 109 additions and 23 deletions

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2019 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.actor
import akka.actor.ActorSystem.Settings
import akka.actor.ActorSystem.findClassLoader
import akka.actor.setup.ActorSystemSetup
import akka.testkit.AbstractSpec
import com.typesafe.config.ConfigFactory
class ProviderSelectionSpec extends AbstractSpec {
import ProviderSelection.{ ClusterActorRefProvider, RemoteActorRefProvider }
"ProviderSelection" must {
val setup = ActorSystemSetup()
val localConfig = ConfigFactory.load()
val classLoader = findClassLoader()
def settingsWith(key: String): Settings = {
val c = ConfigFactory.parseString(s"""akka.actor.provider = "$key"""").withFallback(localConfig)
new Settings(classLoader, c, "test", setup)
}
"create a Local ProviderSelection and set local provider fqcn in Settings" in {
val ps = ProviderSelection.Local
ps.fqcn shouldEqual classOf[LocalActorRefProvider].getName
ps.hasCluster shouldBe false
settingsWith("local").ProviderClass shouldEqual ps.fqcn
}
"create a Remote ProviderSelection and set remote provider fqcn in Settings" in {
val ps = ProviderSelection.Remote
ps.fqcn shouldEqual RemoteActorRefProvider
ps.hasCluster shouldBe false
ProviderSelection("remote") shouldEqual ProviderSelection(RemoteActorRefProvider)
settingsWith("remote").ProviderClass shouldEqual ps.fqcn
}
"create a Cluster ProviderSelection and set cluster provider fqcn in Settings" in {
val ps = ProviderSelection.Cluster
ps.fqcn shouldEqual ClusterActorRefProvider
ps.hasCluster shouldBe true
ProviderSelection("cluster") shouldEqual ProviderSelection(ClusterActorRefProvider)
settingsWith("cluster").ProviderClass shouldEqual ps.fqcn
}
"create a Custom ProviderSelection and set custom provider fqcn in Settings" in {
val other = "other.ActorRefProvider"
val ps = ProviderSelection.Custom(other) //checked by dynamicAccess
ps.fqcn shouldEqual "other.ActorRefProvider"
ps.hasCluster shouldBe false
settingsWith(other).ProviderClass shouldEqual ps.fqcn
}
}
}

View file

@ -27,15 +27,9 @@ abstract class Receptionist extends Extension {
*/
@InternalApi private[akka] class ReceptionistImpl(system: ActorSystem[_]) extends Receptionist {
private def hasCluster: Boolean = {
// FIXME: replace with better indicator that cluster is enabled
val provider = system.settings.untypedSettings.ProviderClass
provider == "akka.cluster.ClusterActorRefProvider"
}
override val ref: ActorRef[Receptionist.Command] = {
val provider: ReceptionistBehaviorProvider =
if (hasCluster) {
if (system.settings.untypedSettings.ProviderSelectionType.hasCluster) {
system.dynamicAccess
.getObjectFor[ReceptionistBehaviorProvider]("akka.cluster.typed.internal.receptionist.ClusterReceptionist")
.recover {

View file

@ -43,6 +43,9 @@ ProblemFilters.exclude[MissingTypesProblem]("akka.dispatch.BalancingDispatcher$S
ProblemFilters.exclude[MissingTypesProblem]("akka.dispatch.MonitorableThreadFactory$AkkaForkJoinWorkerThread")
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.dispatch.MonitorableThreadFactory#AkkaForkJoinWorkerThread.this")
# Better indicator of ActorRefProvider implementation selection #27009
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.actor.ProviderSelection.this")
# Remove deprecated features since 2.5.0 https://github.com/akka/akka/issues/26492
# The ActorCell and others are due to UntypedActorContext being removed from the Cell's hierarchy
ProblemFilters.exclude[MissingClassProblem]("akka.actor.UntypedActor")

View file

@ -82,11 +82,23 @@ object BootstrapSetup {
}
abstract class ProviderSelection private (private[akka] val identifier: String)
/**
* @param identifier the simple name of the selected provider
* @param fqcn the fully-qualified class name of the selected provider
*/
abstract class ProviderSelection private (
private[akka] val identifier: String,
private[akka] val fqcn: String,
private[akka] val hasCluster: Boolean)
object ProviderSelection {
case object Local extends ProviderSelection("local")
case object Remote extends ProviderSelection("remote")
case object Cluster extends ProviderSelection("cluster")
private[akka] val RemoteActorRefProvider = "akka.remote.RemoteActorRefProvider"
private[akka] val ClusterActorRefProvider = "akka.cluster.ClusterActorRefProvider"
case object Local extends ProviderSelection("local", classOf[LocalActorRefProvider].getName, hasCluster = false)
// these two cannot be referenced by class as they may not be on the classpath
case object Remote extends ProviderSelection("remote", RemoteActorRefProvider, hasCluster = false)
case object Cluster extends ProviderSelection("cluster", ClusterActorRefProvider, hasCluster = true)
final case class Custom(override val fqcn: String) extends ProviderSelection("custom", fqcn, hasCluster = false)
/**
* JAVA API
@ -103,6 +115,15 @@ object ProviderSelection {
*/
def cluster(): ProviderSelection = Cluster
/** INTERNAL API */
@InternalApi private[akka] def apply(providerClass: String): ProviderSelection =
providerClass match {
case "local" => Local
// additional fqcn for older configs not using 'remote' or 'cluster'
case "remote" | RemoteActorRefProvider => Remote
case "cluster" | ClusterActorRefProvider => Cluster
case fqcn => Custom(fqcn)
}
}
/**
@ -331,18 +352,16 @@ object ActorSystem {
import config._
final val ConfigVersion: String = getString("akka.version")
final val ProviderClass: String =
setup
.get[BootstrapSetup]
.flatMap(_.actorRefProvider)
.map(_.identifier)
.getOrElse(getString("akka.actor.provider")) match {
case "local" => classOf[LocalActorRefProvider].getName
// these two cannot be referenced by class as they may not be on the classpath
case "remote" => "akka.remote.RemoteActorRefProvider"
case "cluster" => "akka.cluster.ClusterActorRefProvider"
case fqcn => fqcn
}
private final val providerSelectionSetup = setup
.get[BootstrapSetup]
.flatMap(_.actorRefProvider)
.map(_.identifier)
.getOrElse(getString("akka.actor.provider"))
final val ProviderSelectionType: ProviderSelection = ProviderSelection(providerSelectionSetup)
final val ProviderClass: String = ProviderSelectionType.fqcn
final val SupervisorStrategyClass: String = getString("akka.actor.guardian-supervisor-strategy")
final val CreationTimeout: Timeout = Timeout(config.getMillisDuration("akka.actor.creation-timeout"))

View file

@ -0,0 +1,12 @@
/*
* Copyright (C) 2019 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.testkit
import org.scalatest.BeforeAndAfterEach
import org.scalatest.Matchers
import org.scalatest.WordSpecLike
// we could migrate AkkaSpec to extend this
abstract class AbstractSpec extends WordSpecLike with Matchers with BeforeAndAfterEach