diff --git a/akka-cluster-sharding/src/main/scala/akka/cluster/sharding/ShardCoordinator.scala b/akka-cluster-sharding/src/main/scala/akka/cluster/sharding/ShardCoordinator.scala index 455b8dc2c3..21bdaf9dd6 100644 --- a/akka-cluster-sharding/src/main/scala/akka/cluster/sharding/ShardCoordinator.scala +++ b/akka-cluster-sharding/src/main/scala/akka/cluster/sharding/ShardCoordinator.scala @@ -10,7 +10,6 @@ import scala.collection.immutable import scala.concurrent.Future import scala.concurrent.duration._ import scala.util.Success - import akka.actor._ import akka.actor.DeadLetterSuppression import akka.cluster.Cluster @@ -953,7 +952,7 @@ class DDataShardCoordinator(typeName: String, settings: ClusterShardingSettings, case GetFailure(CoordinatorStateKey, _) ⇒ log.error( - "The ShardCoordinator was unable to get an initial state within 'waiting-for-state-timeout': {} millis (retrying)", + "The ShardCoordinator was unable to get an initial state within 'waiting-for-state-timeout': {} millis (retrying). Has ClusterSharding been started on all nodes?", readMajority.timeout.toMillis) // repeat until GetSuccess getCoordinatorState() diff --git a/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingIncorrectSetupSpec.scala b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingIncorrectSetupSpec.scala new file mode 100644 index 0000000000..76cb74bd47 --- /dev/null +++ b/akka-cluster-sharding/src/multi-jvm/scala/akka/cluster/sharding/ClusterShardingIncorrectSetupSpec.scala @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2017-2018 Lightbend Inc. + */ + +package akka.cluster.sharding + +import akka.cluster.MultiNodeClusterSpec +import akka.remote.testkit.{ MultiNodeConfig, MultiNodeSpec } +import akka.testkit._ +import com.typesafe.config.ConfigFactory + +object ClusterShardingIncorrectSetupSpecConfig extends MultiNodeConfig { + val first = role("first") + val second = role("second") + + val commonConfig = ConfigFactory.parseString( + """ + akka.loglevel = INFO + akka.cluster.sharding { + waiting-for-state-timeout = 100ms + } + """.stripMargin) + + commonConfig(commonConfig.withFallback(MultiNodeClusterSpec.clusterConfig)) +} + +class ClusterShardingIncorrectSetupMultiJvmNode1 extends ClusterShardingIncorrectSetupSpec +class ClusterShardingIncorrectSetupMultiJvmNode2 extends ClusterShardingIncorrectSetupSpec + +object ClusterShardingIncorrectSetupSpec { + val extractEntityId: ShardRegion.ExtractEntityId = { + case id: Int ⇒ (id.toString, id) + } + + val extractShardId: ShardRegion.ExtractShardId = { + case id: Int ⇒ id.toString + } +} + +abstract class ClusterShardingIncorrectSetupSpec extends MultiNodeSpec(ClusterShardingIncorrectSetupSpecConfig) with MultiNodeClusterSpec with ImplicitSender { + + import ClusterShardingIncorrectSetupSpec._ + import ClusterShardingIncorrectSetupSpecConfig._ + + "Cluster sharding" must { + "log useful error message if sharding not started" in { + awaitClusterUp(roles: _*) + enterBarrier("cluster-up") + runOn(first) { + EventFilter.error(pattern = """Has ClusterSharding been started on all nodes?""").intercept { + ClusterSharding(system).start( + typeName = "Entity", + entityProps = TestActors.echoActorProps, + settings = ClusterShardingSettings(system), + extractEntityId = extractEntityId, + extractShardId = extractShardId) + } + enterBarrier("helpful error message logged") + } + } + } +} +