Send message to existing Actor in different project - scala

I am wondering if it is possible to send message to an existing Actor from another project?
Existing Actor & allowed Messages:
package org.x.y.z
private case object MA
private case object MB
private class ExistActor extends Actor {
def receive: Receive = {
case MA =>
case MB =>
}
}
However my current project is different from the above, it's org.w.h.i, for example.
Suppose I know the actorSystem name, url and everything that is needed to construct an ActorSelection of org.x.y.ExistActor, So is it possible to send a message and get results?
Note the allowed message of org.x.y.ExistActor and itself are all private, if I am sending a message, I would make a local copy of allowed messages.

Yes, if both systems are set up for remoting you can send a message to any actor that you know the path for using ActorSelection.
However, unless your remote actor system is able to send messages that your actor will respond do, addressing it (as in your example) will be pointless.

First of all Akka Remoting should be enabled on both JVMs obviously. Once you successfully get ActorSelection you can send messages to that actor. It does not matter whether the actor is defined as private class. All that matters that it's running and accessible.
Now the question is whether the actor would accept the messages that you send and whether you can construct these messages since they are private in your case.
It all depends on a serializer configured for Akka Remoting. See these docs for config options and check whether remote project uses serializer that does not depend on Java serialization or any class version specific serialization.
By default Akka Remoting uses Protocol Buffers so that should allow you to construct messages of exactly same type and shape on your side and send them over successfully.

Related

How to test an actor?

How can I test an actor? Since the calls are not synchronous, and one messages can cause multiple messages to be sent, what are the ways of testing it?
E.g. How can I test that my actor sent 3 messages in response to another message?
In general you cannot test what an actor has done unless it interacts with a trait or interface you provide in the construction or in an input message. So if you have an actor like the following.
actor MyActor
be do_stuff(receiver: MyReceiver)
You use a pattern where you combine a timer, for a timeout, and a wrapper actor that provides MyReceiver to test if the actor actually did send the message or sequence of messages that where expected.
Pony already includes the ponytest package with some support for this kind of tests. You can check the PonyTest actor at GitHub. Basically you have to specify a timeout and ensure one of your actors calls complete in the test helper for success. Note that the API has changed since the last stable version.

How to dynamically check type of an actor

It is a general question about developing with akka actor system.
I know, it sacrifices static type checking for greater flexibility, that is not the problem. Java does the same thing all the way.
But I'd like at least to check compatibility of ActorRefs dynamically. I searched for some method like actorRef.asInstanceOf[ActorType]. Such method should provide validation for an actorRef passed through messages. And it would allow safe application development. But I've found no method to do any kind of type check. Its even impossible to check if an actorRef correspond to given Props.
How this task typically solved in akka application? Are there any third-party tools for dynamic checks?
The purpose of ActorRef is to completely abstract the recipient. Sending a message to it provides absolutely no guarantees about a response or even suitability of the message being sent. The recipient could drop the message, route it, stash it or handle it. Any contract about handling and causing possible response messages to be emitted is entirely an informal agreement.
Now, that sounds like a lot to give up in a statically typed environment, but it provides a programming model that brings its own slew of advantages which by their design require that you are sending and receiving messages with the assumption that the messages will be handled but without any knowledge where or when they will be handled.
Regarding how this task is typically solved in akka applications is by configuration and/discovery. The contract of acceptable Messages is usually placed into a Protocol object, while the valid recipient for those Messages is either injected into the calling Actor at creation or queryable via some DiscoveryProtocol (itself hidden behind an ActorRef)
Let's say you have a UserRepository you want to query, you would create protocol like this:
case class User(id: Int, ... )
object UserRepositoryProtocol {
case class GetUser(userId: Int)
}
Further, let's assume that the ActorRef of UserRepository was not injected, but because it is just one of many services your actor might use has to be discovered via a general Discovery service:
object DiscoveryProtocol {
case class Discover(type: String)
case class Discovered(type: String, ref: ActorRef)
}
Now you can fetch a user like this:
(discoveryRef ? Discover("UserRepository")).flatMap {
case Discovered("UserRepository",repository) =>
(repository ? GetUser(id)).map {
case user:User => // do something with the user
}
}
The above condenses discovery and calls into a chain of ask operations. Chances are you would want to cache the discovered ref and or hand off the retrieved user to some other Actor that's doing the work, breaking each '?' into a ! and a matching receive in the same or different actor.
This last point illustrates the power of the actor model. In a traditional request => response model, the requestor and recipient of the response would have to be the same just by virtue of function signatures, but in the actor model, you can send from one actor, spawn a worker that will handle the response, etc.
Assume that an actor is not only encapsulated behind an actor ref, but that the physical location of an actor is also unknown. An actor can be running on another physical server or VM. You can't call instanceOf on an object in another VM - how can you expect to get the class of an actor then?
Now, when building, I would recommend you consider that all actors are remote via Akka's location transparency. (http://doc.akka.io/docs/akka/snapshot/general/remoting.html) If you assume all actors are remote, suddenly you'll think about your designs a little differently. Think of Akka as a Distribution Toolkit - that is its primary benefit!
If you're trying to reflect on actors during runtime, then there is probably something wrong with your design. Instead, you need to know what messages actors can accept and respond to.
If you really want to know what an actor can and can't do, then you could think of modelling some sort of "Accepts" method where an actor would reply with the current version of the described API that the actor implements for example - in this way your client and server can talk back and forth about what capabilities etc are supported dynamically during runtime.
I hope that contributes something to the discussion - just remember to always think of an actor as something that's running somewhere else and you'll design appropriately. The benefit of doing so is that you'll be able to scale out your applications with very minimal effort if your user base unexpectedly explodes!

Does the ask pattern work with Akka IO actors?

Say I have an IO Actor connection capable of sending and receiving messages over TCP. In my actor, I ask the other side of the connection for a response:
connection.ask(ByteString("stuff")).collect {
case Received(response) => log.debug(response.utf8String)
}
It appears that with this code the ask future times out, and instead the containing actor receives the raw message outside of the ask pattern.
Can you use the ask pattern with Akka IO actors? If not, why not?
I don't know the architecture in detail, but here's how I would explain it to myself:
The problem with Akka IO connector actors here is that they don't work in a request-response manner. And if you think about it - that makes sense, because TCP is not a request-response protocol. TCP doesn't even have a notion of message. From programmer's perspective TCP connection is just a pair of continuous byte streams - one in each direction. That's it.
Akka IO is a minimal actor layer on top of network protocols, so it's not surprising that it mimics this behaviour. When TCP actor receives some data from the network, it only knows one thing - that it should send a Received message to the actor that originally sent the Connect message. That's all. It has no idea that the data it received from the network is somehow related to the data that you sent earlier.
Adding to all of that, ask pattern works only under assumption that when you send message A to some actor, it will respond with the message B by sending it exactly to the sender of message A. As we already know, TCP actor doesn't do that - it simply sends everything to the sender of original Connect message.
The reason why this assumption is required is that ask pattern actually creates some sort of a "phantom" actor that is set as the sender of the message sent using ask. This "phantom" actor will then receive the response and invoke all the callbacks registered on the Future. As a side note - be aware that those callbacks are invoked completely independently of the sending actor, i.e. they may run concurrently to it!
So, I would finally conclude that the ask pattern used like this will not work with Akka IO, because it's simply too low level for such an abstraction. If you still want it, you need to create you own layer of abstraction on top of Akka IO, e.g. some simple intermediate actor that covers TCP connector actor and implements the request-response behaviour.
As an additional reference to #ghik's answer, here's roughly how I created an intermediate actor to enable the ask pattern for IO on the rest of my actors.
class IOAskHandlerActor(address: InetSocketAddress) extends Actor {
override def receive = {
// Connection setup code omitted
case Connected(remote, local) =>
// other code omitted
context become latch(sender())
}
def latch(connection: ActorRef): Receive = {
case outgoing =>
context become receiving(connection, sender())
connection ! MySerializer.write(outgoing)
}
def receiving(connection: ActorRef, asker: ActorRef): Receive = {
case Received(incoming) =>
context become latch(connection)
asker ! MySerializer.read(incoming)
}
}
Instances of this class can be asked for responses. Note that I have only tested this with one simultaneous asker (which is my use case) and this probably doesn't work for multiple askers.

What is the best way to get a reference to an Akka Actor

I am a little confused by how I am supposed to get a reference to my Actor once it has been crerated in the Akka system. Say I have the following:
class MyActor(val x: Int) extends Actor {
def receive = {
case Msg => doSth()
}
}
And at some stage I would create the actor as follows:
val actorRef = system.actorOf(Props(new MyActor(2), name = "Some actor")
But when I need to refer to the MyActor object I cannot see any way to get it from the actor ref?
Thanks
Des
I'm adding my comment as an answer since it seems to be viewed as something worth putting in as an answer.
Not being able to directly access the actor is the whole idea behind actor systems. You are not supposed to be able to get at the underlying actor class instance. The actor ref is a lightweight proxy to your actor class instance. Allowing people to directly access the actor instance could lead down the path of mutable data issues/concurrent state update issues and that's a bad path to go down. By forcing you to go through the ref (and thus the mailbox), state and data will always be safe as only one message is processed at a time.
I think cmbaxter has a good answer, but I want to make it just a bit more clear. The ActorRef is your friend for the following reasons:
You cannot ever access the underlying actor. Actors receive their thread of execution from the Dispatcher given to them when they are created. They operate on one mailbox message at a time, so you never have to worry about concurrency inside of the actor unless YOU introduce it (by handling a message asynchronously with a Future or another Actor instance via delegation, for example). If someone had access to the underlying class behind the ActorRef, they could easily call into the actor via a method using another thread, thus negating the point of using the Actor to avoid concurrency in the first place.
ActorRefs provide Location Transparency. By this, I mean that the Actor instance could exist locally on the same JVM and machine as the actor from which you would like to send it a message, or it could exist on a different JVM, on a different box, in a different data center. You don't know, you don't care, and your code is not littered with the details of HOW the message will be sent to that actor, thus making it more declarative (focused on the what you want to do business-wise, not how it will be done). When you start using Remoting or Clusters, this will prove very valuable.
ActorRefs mask the instance of the actor behind it when failure occurs, as well. With the old Scala Actors, you had no such proxy and when an actor "died" (threw an Exception) that resulted in a new instance of the Actor type being created in its place. You then had to propagate that new instance reference to anyone who needed it. With ActorRef, you don't care that the Actor has been reincarnated - it's all transparent.
There is one way to get access to the underlying actor when you want to do testing, using TestActorRef.underlyingActor. This way, you can write unit tests against functionality written in methods inside the actor. Useful for checking basic business logic without worrying about Akka dynamics.
Hope that helps.

Actor addresses and tests

I'm building up an actor hierarchy in which some actors reply to messages they get directly to a well-known actor (fixed name). I.e. these actors (far-removed in the hierarchy) obtain an actorRef via context.actorFor("akka://...").
I.e. for example, I have an "orchestrating" actor:
system.actorOf(Props[OrchestratingActor], name = "orchestrator")
which will then have an address of the kind akka://application/user/orchestrator
and someplace else, a random worker that received a message and wants to talk to the orchestrator:
class RandomWorker extends Actor {
def theOrchestrator = context.actorFor("akka://application/user/orchestrator")
def receive = {
case Foo =>
theOrchestrator ! "Bar"
}
}
Now, I'd like to test those actors and am wondering about how to deal with those addresses: when unit-testing an actor (e.g. using TestActorRef), how do I go about checking what's being sent to the remote address? One idea would be to (when possible) provide the address to the well-known actor via the constructor, and pass in the address of a TestActor to see what's being received. However I wonder if there isn't a way to "impersonate" a given address in the test, esp. in situation where the addresses aren't simple.
In other words I'd like to test the behavior of the actor (will it indeed have sent "Bar" to the orchestrator upon receiving a Foo
My recommendation would be to avoid using look-ups of actors for the purpose you show. It is rather a tool for the setup phase of your application, when wiring it all together. But even then most actors’ supervisors will know the dependencies of their children without using look-ups.
Within a local actor system all ActorRefs can be injected top to bottom (using constructor arguments or introduction messages). Look-ups are most useful when introducing remote systems with each other.
There is nothing wrong with injecting the address via the constructor. Let it me know if you need any details, because at the moment I don't know how to make this more clear, since you basically answered your own question. And btw, I don't know, which Akka version you are using, but actorFor has been recently deprecated in favor of ActorSelection, and there are good reasons for this.