=doc #3689 Make activator templates for cluster samples
This commit is contained in:
parent
b82698a354
commit
37f8f2831b
135 changed files with 2650 additions and 1461 deletions
|
|
@ -0,0 +1,111 @@
|
|||
package sample.cluster.stats
|
||||
|
||||
import language.postfixOps
|
||||
import scala.concurrent.duration._
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import org.scalatest.WordSpecLike
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
import akka.actor.PoisonPill
|
||||
import akka.actor.Props
|
||||
import akka.actor.RootActorPath
|
||||
import akka.contrib.pattern.ClusterSingletonManager
|
||||
import akka.cluster.Cluster
|
||||
import akka.cluster.Member
|
||||
import akka.cluster.MemberStatus
|
||||
import akka.cluster.ClusterEvent.CurrentClusterState
|
||||
import akka.cluster.ClusterEvent.MemberUp
|
||||
import akka.remote.testkit.MultiNodeConfig
|
||||
import akka.remote.testkit.MultiNodeSpec
|
||||
import akka.testkit.ImplicitSender
|
||||
|
||||
object StatsSampleSingleMasterSpecConfig extends MultiNodeConfig {
|
||||
// register the named roles (nodes) of the test
|
||||
val first = role("first")
|
||||
val second = role("second")
|
||||
val third = role("third")
|
||||
|
||||
// this configuration will be used for all nodes
|
||||
// note that no fixed host names and ports are used
|
||||
commonConfig(ConfigFactory.parseString("""
|
||||
akka.loglevel = INFO
|
||||
akka.actor.provider = "akka.cluster.ClusterActorRefProvider"
|
||||
akka.remote.log-remote-lifecycle-events = off
|
||||
akka.cluster.roles = [compute]
|
||||
# don't use sigar for tests, native lib not in path
|
||||
akka.cluster.metrics.collector-class = akka.cluster.JmxMetricsCollector
|
||||
#//#router-deploy-config
|
||||
akka.actor.deployment {
|
||||
/singleton/statsService/workerRouter {
|
||||
router = consistent-hashing-pool
|
||||
nr-of-instances = 100
|
||||
cluster {
|
||||
enabled = on
|
||||
max-nr-of-instances-per-node = 3
|
||||
allow-local-routees = on
|
||||
use-role = compute
|
||||
}
|
||||
}
|
||||
}
|
||||
#//#router-deploy-config
|
||||
"""))
|
||||
|
||||
}
|
||||
|
||||
// need one concrete test class per node
|
||||
class StatsSampleSingleMasterSpecMultiJvmNode1 extends StatsSampleSingleMasterSpec
|
||||
class StatsSampleSingleMasterSpecMultiJvmNode2 extends StatsSampleSingleMasterSpec
|
||||
class StatsSampleSingleMasterSpecMultiJvmNode3 extends StatsSampleSingleMasterSpec
|
||||
|
||||
abstract class StatsSampleSingleMasterSpec extends MultiNodeSpec(StatsSampleSingleMasterSpecConfig)
|
||||
with WordSpecLike with MustMatchers with BeforeAndAfterAll with ImplicitSender {
|
||||
|
||||
import StatsSampleSingleMasterSpecConfig._
|
||||
|
||||
override def initialParticipants = roles.size
|
||||
|
||||
override def beforeAll() = multiNodeSpecBeforeAll()
|
||||
|
||||
override def afterAll() = multiNodeSpecAfterAll()
|
||||
|
||||
"The stats sample with single master" must {
|
||||
"illustrate how to startup cluster" in within(15 seconds) {
|
||||
Cluster(system).subscribe(testActor, classOf[MemberUp])
|
||||
expectMsgClass(classOf[CurrentClusterState])
|
||||
|
||||
val firstAddress = node(first).address
|
||||
val secondAddress = node(second).address
|
||||
val thirdAddress = node(third).address
|
||||
|
||||
Cluster(system) join firstAddress
|
||||
|
||||
receiveN(3).collect { case MemberUp(m) => m.address }.toSet must be(
|
||||
Set(firstAddress, secondAddress, thirdAddress))
|
||||
|
||||
Cluster(system).unsubscribe(testActor)
|
||||
|
||||
system.actorOf(ClusterSingletonManager.props(
|
||||
singletonProps = Props[StatsService], singletonName = "statsService",
|
||||
terminationMessage = PoisonPill, role = Some("compute")), name = "singleton")
|
||||
|
||||
system.actorOf(Props[StatsFacade], "statsFacade")
|
||||
|
||||
testConductor.enter("all-up")
|
||||
}
|
||||
|
||||
"show usage of the statsFacade" in within(40 seconds) {
|
||||
val facade = system.actorSelection(RootActorPath(node(third).address) / "user" / "statsFacade")
|
||||
|
||||
// eventually the service should be ok,
|
||||
// service and worker nodes might not be up yet
|
||||
awaitAssert {
|
||||
facade ! StatsJob("this is the text that will be analyzed")
|
||||
expectMsgType[StatsResult](1.second).meanWordLength must be(
|
||||
3.875 plusOrMinus 0.001)
|
||||
}
|
||||
|
||||
testConductor.enter("done")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package sample.cluster.stats
|
||||
|
||||
import language.postfixOps
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.actor.RootActorPath
|
||||
import akka.cluster.Cluster
|
||||
import akka.cluster.Member
|
||||
import akka.cluster.MemberStatus
|
||||
import akka.cluster.ClusterEvent.CurrentClusterState
|
||||
import akka.cluster.ClusterEvent.MemberUp
|
||||
|
||||
//#MultiNodeConfig
|
||||
import akka.remote.testkit.MultiNodeConfig
|
||||
import com.typesafe.config.ConfigFactory
|
||||
|
||||
object StatsSampleSpecConfig extends MultiNodeConfig {
|
||||
// register the named roles (nodes) of the test
|
||||
val first = role("first")
|
||||
val second = role("second")
|
||||
val third = role("thrid")
|
||||
|
||||
// this configuration will be used for all nodes
|
||||
// note that no fixed host names and ports are used
|
||||
commonConfig(ConfigFactory.parseString("""
|
||||
akka.actor.provider = "akka.cluster.ClusterActorRefProvider"
|
||||
akka.remote.log-remote-lifecycle-events = off
|
||||
akka.cluster.roles = [compute]
|
||||
# don't use sigar for tests, native lib not in path
|
||||
akka.cluster.metrics.collector-class = akka.cluster.JmxMetricsCollector
|
||||
#//#router-lookup-config
|
||||
akka.actor.deployment {
|
||||
/statsService/workerRouter {
|
||||
router = consistent-hashing-group
|
||||
nr-of-instances = 100
|
||||
routees.paths = ["/user/statsWorker"]
|
||||
cluster {
|
||||
enabled = on
|
||||
allow-local-routees = on
|
||||
use-role = compute
|
||||
}
|
||||
}
|
||||
}
|
||||
#//#router-lookup-config
|
||||
"""))
|
||||
|
||||
}
|
||||
//#MultiNodeConfig
|
||||
|
||||
//#concrete-tests
|
||||
// need one concrete test class per node
|
||||
class StatsSampleSpecMultiJvmNode1 extends StatsSampleSpec
|
||||
class StatsSampleSpecMultiJvmNode2 extends StatsSampleSpec
|
||||
class StatsSampleSpecMultiJvmNode3 extends StatsSampleSpec
|
||||
//#concrete-tests
|
||||
|
||||
//#abstract-test
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import org.scalatest.WordSpecLike
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
import akka.remote.testkit.MultiNodeSpec
|
||||
import akka.testkit.ImplicitSender
|
||||
|
||||
abstract class StatsSampleSpec extends MultiNodeSpec(StatsSampleSpecConfig)
|
||||
with WordSpecLike with MustMatchers with BeforeAndAfterAll
|
||||
with ImplicitSender {
|
||||
|
||||
import StatsSampleSpecConfig._
|
||||
|
||||
override def initialParticipants = roles.size
|
||||
|
||||
override def beforeAll() = multiNodeSpecBeforeAll()
|
||||
|
||||
override def afterAll() = multiNodeSpecAfterAll()
|
||||
|
||||
//#abstract-test
|
||||
|
||||
"The stats sample" must {
|
||||
|
||||
//#startup-cluster
|
||||
"illustrate how to startup cluster" in within(15 seconds) {
|
||||
Cluster(system).subscribe(testActor, classOf[MemberUp])
|
||||
expectMsgClass(classOf[CurrentClusterState])
|
||||
|
||||
//#addresses
|
||||
val firstAddress = node(first).address
|
||||
val secondAddress = node(second).address
|
||||
val thirdAddress = node(third).address
|
||||
//#addresses
|
||||
|
||||
//#join
|
||||
Cluster(system) join firstAddress
|
||||
//#join
|
||||
|
||||
system.actorOf(Props[StatsWorker], "statsWorker")
|
||||
system.actorOf(Props[StatsService], "statsService")
|
||||
|
||||
receiveN(3).collect { case MemberUp(m) => m.address }.toSet must be(
|
||||
Set(firstAddress, secondAddress, thirdAddress))
|
||||
|
||||
Cluster(system).unsubscribe(testActor)
|
||||
|
||||
testConductor.enter("all-up")
|
||||
}
|
||||
//#startup-cluster
|
||||
|
||||
//#test-statsService
|
||||
"show usage of the statsService from one node" in within(15 seconds) {
|
||||
runOn(second) {
|
||||
assertServiceOk()
|
||||
}
|
||||
|
||||
testConductor.enter("done-2")
|
||||
}
|
||||
|
||||
def assertServiceOk(): Unit = {
|
||||
val service = system.actorSelection(node(third) / "user" / "statsService")
|
||||
// eventually the service should be ok,
|
||||
// first attempts might fail because worker actors not started yet
|
||||
awaitAssert {
|
||||
service ! StatsJob("this is the text that will be analyzed")
|
||||
expectMsgType[StatsResult](1.second).meanWordLength must be(
|
||||
3.875 plusOrMinus 0.001)
|
||||
}
|
||||
|
||||
}
|
||||
//#test-statsService
|
||||
|
||||
"show usage of the statsService from all nodes" in within(15 seconds) {
|
||||
assertServiceOk()
|
||||
testConductor.enter("done-3")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package sample.cluster.transformation
|
||||
|
||||
import language.postfixOps
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
|
||||
import org.scalatest.BeforeAndAfterAll
|
||||
import org.scalatest.WordSpecLike
|
||||
import org.scalatest.matchers.MustMatchers
|
||||
|
||||
import akka.actor.Props
|
||||
import akka.cluster.Cluster
|
||||
import akka.remote.testkit.MultiNodeConfig
|
||||
import akka.remote.testkit.MultiNodeSpec
|
||||
import akka.testkit.ImplicitSender
|
||||
|
||||
object TransformationSampleSpecConfig extends MultiNodeConfig {
|
||||
// register the named roles (nodes) of the test
|
||||
val frontend1 = role("frontend1")
|
||||
val frontend2 = role("frontend2")
|
||||
val backend1 = role("backend1")
|
||||
val backend2 = role("backend2")
|
||||
val backend3 = role("backend3")
|
||||
|
||||
// this configuration will be used for all nodes
|
||||
// note that no fixed host names and ports are used
|
||||
commonConfig(ConfigFactory.parseString("""
|
||||
akka.actor.provider = "akka.cluster.ClusterActorRefProvider"
|
||||
akka.remote.log-remote-lifecycle-events = off
|
||||
# don't use sigar for tests, native lib not in path
|
||||
akka.cluster.metrics.collector-class = akka.cluster.JmxMetricsCollector
|
||||
"""))
|
||||
|
||||
nodeConfig(frontend1, frontend2)(
|
||||
ConfigFactory.parseString("akka.cluster.roles =[frontend]"))
|
||||
|
||||
nodeConfig(backend1, backend2, backend3)(
|
||||
ConfigFactory.parseString("akka.cluster.roles =[backend]"))
|
||||
}
|
||||
|
||||
// need one concrete test class per node
|
||||
class TransformationSampleSpecMultiJvmNode1 extends TransformationSampleSpec
|
||||
class TransformationSampleSpecMultiJvmNode2 extends TransformationSampleSpec
|
||||
class TransformationSampleSpecMultiJvmNode3 extends TransformationSampleSpec
|
||||
class TransformationSampleSpecMultiJvmNode4 extends TransformationSampleSpec
|
||||
class TransformationSampleSpecMultiJvmNode5 extends TransformationSampleSpec
|
||||
|
||||
abstract class TransformationSampleSpec extends MultiNodeSpec(TransformationSampleSpecConfig)
|
||||
with WordSpecLike with MustMatchers with BeforeAndAfterAll with ImplicitSender {
|
||||
|
||||
import TransformationSampleSpecConfig._
|
||||
|
||||
override def initialParticipants = roles.size
|
||||
|
||||
override def beforeAll() = multiNodeSpecBeforeAll()
|
||||
|
||||
override def afterAll() = multiNodeSpecAfterAll()
|
||||
|
||||
"The transformation sample" must {
|
||||
"illustrate how to start first frontend" in within(15 seconds) {
|
||||
runOn(frontend1) {
|
||||
// this will only run on the 'first' node
|
||||
Cluster(system) join node(frontend1).address
|
||||
val transformationFrontend = system.actorOf(Props[TransformationFrontend], name = "frontend")
|
||||
transformationFrontend ! TransformationJob("hello")
|
||||
expectMsgPF() {
|
||||
// no backends yet, service unavailble
|
||||
case JobFailed(_, TransformationJob("hello")) =>
|
||||
}
|
||||
}
|
||||
|
||||
// this will run on all nodes
|
||||
// use barrier to coordinate test steps
|
||||
testConductor.enter("frontend1-started")
|
||||
}
|
||||
|
||||
"illustrate how a backend automatically registers" in within(15 seconds) {
|
||||
runOn(backend1) {
|
||||
Cluster(system) join node(frontend1).address
|
||||
system.actorOf(Props[TransformationBackend], name = "backend")
|
||||
}
|
||||
testConductor.enter("backend1-started")
|
||||
|
||||
runOn(frontend1) {
|
||||
assertServiceOk()
|
||||
}
|
||||
|
||||
testConductor.enter("frontend1-backend1-ok")
|
||||
}
|
||||
|
||||
"illustrate how more nodes registers" in within(20 seconds) {
|
||||
runOn(frontend2) {
|
||||
Cluster(system) join node(frontend1).address
|
||||
system.actorOf(Props[TransformationFrontend], name = "frontend")
|
||||
}
|
||||
testConductor.enter("frontend2-started")
|
||||
|
||||
runOn(backend2, backend3) {
|
||||
Cluster(system) join node(backend1).address
|
||||
system.actorOf(Props[TransformationBackend], name = "backend")
|
||||
}
|
||||
|
||||
testConductor.enter("all-started")
|
||||
|
||||
runOn(frontend1, frontend2) {
|
||||
assertServiceOk()
|
||||
}
|
||||
|
||||
testConductor.enter("all-ok")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def assertServiceOk(): Unit = {
|
||||
val transformationFrontend = system.actorSelection("akka://" + system.name + "/user/frontend")
|
||||
// eventually the service should be ok,
|
||||
// backends might not have registered initially
|
||||
awaitAssert {
|
||||
transformationFrontend ! TransformationJob("hello")
|
||||
expectMsgType[TransformationResult](1.second).text must be("HELLO")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue