Building actors with environment-dependent actor paths for different environments

56 views
Skip to first unread message

Geoff Groos

unread,
Sep 20, 2015, 4:54:33 PM9/20/15
to Akka User List
Hey guys,

So I'm a complete newbie to this and a complete newbie to AKKA and to Scala, so I'm sure my question is simple, but after an hour of reading I cant really find a concise explanation.

Our application is currently simple enough: Our front-end will create a 'dispatcher' actor locally, which will connect to a number of 'worker' actors. It then receives configurations from the front-end and dispatches them as sizable computation work to each of the workers. At time of writing I really don't think we're going to need complex paths or sym-link-ish things or complex routing --we don't need an actor tree, just an actor list.

My understanding of the problem:
- Akka wants me to use it as a static factory to find actors. Once found, I acquire an `ActorRef`, which is a proxy for an actor object somewhere {one of 'same JVM', 'same machine', 'same network'}
- The mechanism used to identify (and thus find) these actors is akin to a path on a file system --maybe a bit more like a URL with protocols and addresses and (presumably) credentials embedded in it.

My problem:
I need my actor environment to be configured in 3+ different ways:
  1. a unit-testing mode where everything is whiten the same JVM --for consistency and least-suprise as an additional caveat I want messages to be serialized using our serializer despite not them not actually needing it.
  2. a local-functional-testing mode where the actors exist on different JVMs on the same machine --ideally I'd also like to be able to flip this mode into most of mode 1 by specifying a `-DMakeActorsLocally=true`
    option or similar
  3. a production mode where the actors exist on different jvms on different machines.

In the pursuit of #1 and #2 (haven't gotten around to #3 yet), I've cobbled these two lines together from the remote sample and the calculator sample:


    //works for mode #2

    val workerActor = context.actorSelection("akka.tcp://" + ProxyActor.SystemName + "@127.0.0.1:5150/user/" + ProxyActor.ActorName)

    //for mode #1

    val workerRouter = context.actorOf(
        ProxyActor.props().withRouter(RoundRobinRouter(1)),
        name = Proxy.ActorName
    )


Now I could hack it together and do an if(mode1){ actor = ... } else if (mode2) { actor = ... }, but that's not nice. What I want to do is combine these two lines polymorphically so that this code doesn't change its behaviour between unit testing and deployment and everything in between. I'm not sure how to leverage paths and the various AKKA factories to do this.


What I believe is the solution:
Right now most of our unit testing leverages guice, such that any class takes the bulk of its dependencies through its constructor. At production these are all live classes, in development these are all mock/fake/stub classes. We do have some classes that will act differently based on what boil down to system properties --we've written some tooling to add a couple features to the System.properties outside of simply getting and setting strings.

So, would like to do is have some static resource (perhalps a couple of enums?) that each specify a different strategy to produce actor refs, ideally we would injcet these enums, but because of the static-factory-ness of AKKA I think my best bet (for simplicity --feel free to wow me with an amazing guice configuration but I cant really accept work I dont understand--) might be to push these values to AKKA configuration through the system properties (and/or static fields)

I've created a gist containing the bulk of the functional code here --Its got too much of my projects markup on it for you to be able to compile it, but thanks to Scala (im really liking this language) its all fairly short and concise. Hopefully you can read it. I haven't TDD'd pefectly, but I have been trying to drive my changes with a test fixture, so any change I make id like to be able to create a test for.
 
Any advice about coding style or testing strategy are welcome
  • Specifically you'll note the pumping events behaviour I've got on the JobDispatcherActor. I need the exact same behaviour on the ProxyActor. With java I'd simply inject something and delegate to it, but with scala... a trait? a mixin? Maybe KISS and just do what I'd do for java?
  • Also, I discovered the `Nothing` type is a subclass of all classes, I presume `Any` has a similar relationship, but the bang-operator ('publish' method on actorref) takes an Any, which because of my confusion with pattern matching got me mixed up on what I was actually posting. Can I override this to take a less-open type? (such as a AKKAMessage?)

I've also got a more complex question about akka, guice, and xstream over at stack-overflow, here.

Thanks for any help guys, if nothing else you've made my job pretty exciting for the past week or two!

-Geoff

Patrik Nordwall

unread,
Sep 25, 2015, 11:17:11 AM9/25/15
to akka...@googlegroups.com
Hi Geoff,

I would recommend that you take a look at Akka Cluster
There you will find many things that will help you with these problems.

For example, if you need to do different things on different nodes in the cluster you can assign roles to the nodes and startup actors based on the node role. In testing mode you can assign all roles to one node (ActorSystem).

For #2 I also recommend that you use Multi Node Testing (works great on one machine with many JVMs also).

Regards,
Patrik

--
>>>>>>>>>> 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 akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.



--

Patrik Nordwall
Typesafe Reactive apps on the JVM
Twitter: @patriknw

Geoff Groos

unread,
Oct 3, 2015, 2:14:21 AM10/3/15
to Akka User List
Hey Patrik

Thanks for this, I dont know why I didnt discover akka cluster earlier.

But I have run into a problem; I've followed the factorial example as best I can and whenever I post any message I get deadLetters. Is there a way I can get akka to log why it generates deadLetter actors?

I do get messages saying my actors see each other on the cluster ("leader welcomes xyz"), but I cant route any messages between them.

The code's up here in a gist: https://gist.github.com/Groostav/92054036601fab832a37

I guess my question is, how do I go about debugging this? My problem is reasonably clearly with actor paths, but I'm not sure how those work, or where I've screwed them up.

thanks for any help!

-Geoff

Martynas Mickevičius

unread,
Oct 11, 2015, 12:19:27 PM10/11/15
to akka...@googlegroups.com
Hi Geoff,

when a message goes to dead letters it means that an actor, for which that message is destined, is not there anymore (or has never been). You can try printing ActorRef out and see what actor you are trying to send messages to. Then you have to make sure that an actor on such path is up and running.

I think you see messages go to DeadLetters when you access sender from a Google Event Bus thread. If your actor is not processing a message at that point, sender method is going to return a reference to DeadLetters.

Also you should not mix and match Akka Actors with Google Event Bus in the same class as that can cause memory visibility issues. I would recommend to have a separate class which would subscribe to Google Event Bus and would relay messages to some actor which ActorRef it gets via dependency injection.

--
>>>>>>>>>> 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 akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.



--
Martynas Mickevičius
TypesafeReactive Apps on the JVM
Reply all
Reply to author
Forward
0 new messages