Viktor,
Thanks for looking into my problem. Sorry for my late reply but I decided to first push ahead and get something working on my end. For reference to anyone else dealing with a similar issue, I used a multi-jvm setup with four nodes. Two nodes for my cluster, one node for the shared leveldb journal (I decided to use kafka in integration testing only), and one node for the cluster client. With this setup, I was able to verify the communication between the client, receptionist, my broker and finally my sharded cluster of processors. I’m having some issues with the cluster singleton but that is a topic for another post and I have been able to run the whole setup with the singleton as well, just not consistently. I think the above setup is sufficient for unit testing my cluster client, but it still bugs me that I can’t test my spray routes together with the cluster. Realistically, I will conclude that I’m mixing unit testing and integration testing. Since I can fully test my client with the cluster using the above setup, I will simply unit test my spray routes with a mock cluster client. On the other hand, I still wanted to ask: Are you aware of any workaround to combine unit testing spray routes with a multi-jvm setup? Or since spray is becoming part of akka, will such functionality be available as a result of this integration? Thanks again for your help, Sinan On Friday, September 26, 2014 12:27:52 AM UTC+3, √ wrote: > > Seems like a missing feature in the Scala compiler: > https://issues.scala-lang.org/browse/SI-1938 > > On Thu, Sep 25, 2014 at 10:02 PM, sinel <[email protected] <javascript:>> > wrote: > >> >> If you are asking what I tried for overriding system, it was simply: >> >> override val system = ActorSystem("test-system") >> >> I thought the rest of my code was irrelevant since the conflict is in the >> class declaration, but here’s how the spec looks after I take out stuff >> specific to my app logic: >> >> >> object MySpecConfig extends MultiNodeConfig { >> >> val node1 = role("node1") >> >> val node2 = role("node2") >> >> } >> >> class MySpecMultiJvmNode1 extends MySpec >> >> class MySpecMultiJvmNode2 extends MySpec >> >> class MySpec extends MultiNodeSpec(MySpecConfig) with STMultiNodeSpec >> with ScalatestRouteTest with MyRouter { >> >> import MySpecConfig._ >> >> // override val system = ActorSystem("test-system") >> >> implicit val actorRefFactory = system >> >> def initialParticipants = roles.size >> >> override def beforeAll(): Unit = { >> >> runOn(node1) { >> >> Cluster(system) join node(node1).address >> >> startNode() >> >> } >> >> enterBarrier(node1.name + "-joined") >> >> runOn(node2) { >> >> Cluster(system) join node(node1).address >> >> startNode() >> >> } >> >> enterBarrier(node2.name + "-joined") >> >> } >> >> override def afterAll(): Unit = { >> >> // shutdown test actor system >> >> system.shutdown() >> >> system.awaitTermination(10.seconds) >> >> } >> >> def startNode(): Unit = { >> >> ClusterSharding(system).start( >> >> typeName = MyProcessor.shardName, >> >> entryProps = Some(MyProcessor.props), >> >> idExtractor = MyProcessor.idExtractor, >> >> shardResolver = MyProcessor.shardResolver) >> >> >> ClusterReceptionistExtension(system).registerService(system.actorOf(CommandBroker.props, >> >> "broker")) >> >> } >> >> "The API service" when { >> >> "receives an HTTP POST ‘/mystuff’ request" which { >> >> "has valid json data" should { >> >> "respond with Ok" in { >> >> runOn(node1) { >> >> Post("/mystuff", Map(“name” -> "test")) ~> myRoutes ~> check { >> >> … >> >> } >> >> } >> >> } >> >> } >> >> } >> >> } >> >> >> STMultiNodeSpec is identical to what you have in the docs. MyRouter is >> just a trait containing my spray routes. CommandBroker is: >> >> class CommandBroker extends Actor with ActorLogging { >> >> val myProcessorRegion = >> ClusterSharding(context.system).shardRegion(MyProcessor.shardName) >> >> override def receive = { >> >> case cmd: MyProcessorCommand => >> >> myProcessorRegion ! cmd >> >> case msg: Any => >> >> log.warning(s"CommandBroker received unexpected message: '$msg'.") >> >> } >> >> } >> >> object CommandBroker { >> >> def props: Props = Props(new CommandBroker) >> >> } >> >> The idea is that the client will send all commands to the broker via the >> receptionist, and the broker will forward commands to appropriate >> persistent actors / shard regions. >> >> >> My config for the backend is as follows: >> >> akka { >> >> extensions = ["akka.contrib.pattern.ClusterReceptionistExtension"] >> >> actor { >> >> provider = "akka.cluster.ClusterActorRefProvider" >> >> } >> >> remote { >> >> log-remote-lifecycle-events = off >> >> netty.tcp { >> >> hostname = "127.0.0.1" >> >> port = 2551 >> >> } >> >> } >> >> cluster { >> >> seed-nodes = [ >> >> "akka.tcp://[email protected]:2551", >> >> "akka.tcp://[email protected]:2552"] >> >> auto-down-unreachable-after = 10s >> >> } >> >> akka.contrib.cluster.receptionist { >> >> name = receptionist >> >> role = "" >> >> number-of-contacts = 2 >> >> response-tunnel-receive-timeout = 30s >> >> } >> >> } >> >> akka.persistence.journal.plugin = "kafka-journal" >> >> akka.persistence.snapshot-store.plugin = "kafka-snapshot-store" >> >> kafka-journal.zookeeper.connect = "192.168.59.103:2181" >> >> kafka-snapshot-store.zookeeper.connect = "192.168.59.103:2181" >> >> >> I’m using kafka running locally on a separate docker container. And I >> don’t have any cluster-specific config for the frontend. It’s simply >> embedded in the code as follows: >> >> val initialContacts = Set( >> >> context.actorSelection("akka.tcp:// >> [email protected]:2551/user/receptionist"), >> >> context.actorSelection("akka.tcp:// >> [email protected]:2552/user/receptionist")) >> >> val commandBroker = >> context.actorOf(ClusterClient.props(initialContacts)) >> >> and later used as: >> >> broker ! ClusterClient.Send("/user/broker", msg, localAffinity = true) >> >> when the appropriate msg is created from the request in the router. >> >> >> I guess this pretty much covers what I have been trying to do. >> >> Thanks a lot for helping out, >> >> Sinan >> >> >> >> On Thursday, September 25, 2014 9:51:26 PM UTC+3, √ wrote: >>> >>> What exactly (code) did you try? >>> >>> Thanks >>> >>> On Thu, Sep 25, 2014 at 8:42 PM, sinel <[email protected]> wrote: >>> >>>> I have a rest api frontend implemented with spray which dispatches >>>> commands to a backend implemented using akka persistence. I unit tested >>>> the >>>> rest api frontend of this setup successfully using ScalatestRouteTest. >>>> >>>> Now, I have separated the backend using cluster sharding, and I have >>>> setup the rest api frontend to use cluster client for dispatching the >>>> commands. Again I would like to test the frontend using ScalatestRouteTest >>>> while also utilizing a multi-jvm setup to integrate the backend cluster. I >>>> put together my unit test in a manner similar to: >>>> >>>> class MySpec extends MultiNodeSpec(MySpecConfig) with STMultiNodeSpec >>>> with ScalatestRouteTest with MyRouter >>>> >>>> However, when I try to compile this, I get the following error: >>>> >>>> class MySpec inherits conflicting members: >>>> >>>> value system in class TestKit of type akka.actor.ActorSystem and >>>> >>>> value system in trait RouteTest of type akka.actor.ActorSystem >>>> >>>> (Note: this can be resolved by declaring an override in class MySpec.) >>>> >>>> I tried naively overriding system in MySpec but this just leads to >>>> other errors and doesn’t look right. Has anyone else tried using >>>> ScalatestRouteTest with multi-jvm? Is there any work around to this >>>> problem? Or am I approaching this the wrong way? I guess I can easily test >>>> the cluster separately by sending individual commands, but it would be >>>> really nice to test them together in an integrated manner, thus confirming >>>> that the cluster client works fine with the cluster sharding. >>>> >>>> Thanks, >>>> >>>> Sinan >>>> >>>> -- >>>> >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>> >>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/ >>>> current/additional/faq.html >>>> >>>>>>>>>> Search the archives: https://groups.google.com/ >>>> group/akka-user >>>> --- >>>> You received this message because you are subscribed to the Google >>>> Groups "Akka User List" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to [email protected]. >>>> To post to this group, send email to [email protected]. >>>> Visit this group at http://groups.google.com/group/akka-user. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> >>> >>> -- >>> Cheers, >>> √ >>> >> -- >> >>>>>>>>>> Read the docs: http://akka.io/docs/ >> >>>>>>>>>> Check the FAQ: >> http://doc.akka.io/docs/akka/current/additional/faq.html >> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user >> --- >> You received this message because you are subscribed to the Google Groups >> "Akka User List" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> To post to this group, send email to [email protected] >> <javascript:>. >> Visit this group at http://groups.google.com/group/akka-user. >> For more options, visit https://groups.google.com/d/optout. >> > > > > -- > Cheers, > √ > -- >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>>>>>>>> Check the FAQ: >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups "Akka User List" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.
