Akka actor model. Why sending messages to self? - java

I am new to akka, looking at existing code and see an actor gets Message1 form others and then sends Message2 to self. I understand the advantage of sending messages over method calls is the key in akka. However I do not see advantage in sending message to getSelf(). The code I see looks like this:
import java.util.Date;
import akka.actor.AbstractLoggingActor;
import akka.actor.Props;
public class myActor extends AbstractLoggingActor {
public static class Message1 {
}
public static class Message2 {
}
private Date date;
public static Props props(Date date) {
return Props.create(myActor.class, date);
}
#Override
public Receive createReceive() {
return receiveBuilder().match(Message1.class, message -> {
// some state change here, method calls, ...
getSelf().tell(new Message2(), getSelf());
}).match(Message2.class, message -> {
// some code here ...
this.doSomeLongProcessing();
}).build();
}
private void doSomeLongProcessing() {
// ... long time is taken here
}
}
Eventually there should be a blocking call to a method in the actor class (e.g. doSomeLongProcessing()) and we put this call in another message processing it will not be any better.
In this light the question is - why we may need to send messages to self in akka ?
Please explain as I saw some examples of this on the web as well.

I don't think I can give a real answer without seeing the complete code and context. But, in general, you are right, under normal circumstances there's not a whole lot of benefit to sending yourself a message just to continue normal processing. But I expect that this example is a bit contrived anyway because ordinarily you wouldn't want to mix blocking and non-blocking behavior in the same actor. (In general, the best practice would be to process message1 in one actor and then process message2 in a different actor so that you could put that second actor in a dedicated thread pool for blocking actors.)
There are several situations, however, where sending messages to yourself can be valid. Two of which are mentioned by Robert Harvey above in the comments: when using timers to send a message to yourself in the future and the "pipeTo" pattern where you are sending yourself a message from inside a Future completion. (This is important because you will no longer be inside the actor context in the completion handler, so you need to send yourself a message in order to get back into the context.)
I can also think of a few other edge cases where you might want to send a message to self. For example, if you are in a blocking actor, sending a message to yourself is effectively a yield allowing the actor to handle others messages.
If the code is public I could take a look at a specific example in more detail.

Related

Retrieve an Akka actor or create it if it does not exist

I am developing an application that creates some Akka actors to manage and process messages coming from a Kafka topic. Messages with the same key are processed by the same actor. I use the message key also to name the corresponding actor.
When a new message is read from the topic, I don't know if the actor with the id equal to the message key was already created by the actor system or not. Therefore, I try to resolve the actor using its name, and if it does not exist yet, I create it. I need to manage concurrency in regard to actor resolution. So it is possible that more than one client asks the actor system if an actor exists.
The code I am using right now is the following:
private CompletableFuture<ActorRef> getActor(String uuid) {
return system.actorSelection(String.format("/user/%s", uuid))
.resolveOne(Duration.ofMillis(1000))
.toCompletableFuture()
.exceptionally(ex ->
system.actorOf(Props.create(MyActor.class, uuid), uuid))
.exceptionally(ex -> {
try {
return system.actorSelection(String.format("/user/%s",uuid)).resolveOne(Duration.ofMillis(1000)).toCompletableFuture().get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
});
}
The above code is not optimised, and the exception handling can be made better.
However, is there in Akka a more idiomatic way to resolve an actor, or to create it if it does not exist? Am I missing something?
Consider creating an actor that maintains as its state a map of message IDs to ActorRefs. This "receptionist" actor would handle all requests to obtain a message processing actor. When the receptionist receives a request for an actor (the request would include the message ID), it tries to look up an associated actor in its map: if such an actor is found, it returns the ActorRef to the sender; otherwise it creates a new processing actor, adds that actor to its map, and returns that actor reference to the sender.
I would consider using akka-cluster and akka-cluster-sharding. First, this gives you throughput, and as well, reliability. However, it will also make the system manage the creation of the 'entity' actors.
But you have to change the way you talk to those actors. You create a ShardRegion actor which handles all the messages:
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.cluster.sharding.ClusterSharding;
import akka.cluster.sharding.ClusterShardingSettings;
import akka.cluster.sharding.ShardRegion;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class MyEventReceiver extends AbstractActor {
private final ActorRef shardRegion;
public static Props props() {
return Props.create(MyEventReceiver.class, MyEventReceiver::new);
}
static ShardRegion.MessageExtractor messageExtractor
= new ShardRegion.HashCodeMessageExtractor(100) {
// using the supplied hash code extractor to shard
// the actors based on the hashcode of the entityid
#Override
public String entityId(Object message) {
if (message instanceof EventInput) {
return ((EventInput) message).uuid().toString();
}
return null;
}
#Override
public Object entityMessage(Object message) {
if (message instanceof EventInput) {
return message;
}
return message; // I don't know why they do this it's in the sample
}
};
public MyEventReceiver() {
ActorSystem system = getContext().getSystem();
ClusterShardingSettings settings =
ClusterShardingSettings.create(system);
// this is setup for the money shot
shardRegion = ClusterSharding.get(system)
.start("EventShardingSytem",
Props.create(EventActor.class),
settings,
messageExtractor);
}
#Override
public Receive createReceive() {
return receiveBuilder().match(
EventInput.class,
e -> {
log.info("Got an event with UUID {} forwarding ... ",
e.uuid());
// the money shot
deviceRegion.tell(e, getSender());
}
).build();
}
}
So this Actor MyEventReceiver runs on all nodes of your cluster, and encapsulates the shardRegion Actor. You no longer message your EventActors directly, but, using the MyEventReceiver and deviceRegion Actors, you use the sharding system keep track of which node in the cluster the particular EventActor lives on. It will create one if none have been created before, or route it messages if it has. Every EventActor must have a unique id: which is extracted from the message (so a UUID is pretty good for that, but it could be some other id, like a customerID, or an orderID, or whatever, as long as its unique for the Actor instance you want to process it with).
(I'm omitting the EventActor code, it's otherwise a pretty normal Actor, depending what you are doing with it, the 'magic' is in the code above).
The sharding system automatically knows to create the EventActor and allocate it to a shard, based on the algorithm you've chosen (in this particular case, it's based on the hashCode of the unique ID, which is all I've ever used). Furthermore, you're guaranteed only one Actor for any given unique ID. The message is transparently routed to the correct Node and Shard wherever it is; from whichever Node and Shard it's being sent.
There's more info and sample code in the Akka site & documentation.
This is a pretty rad way to make sure that the same Entity/Actor always processes messages meant for it. The cluster and sharding takes automatic care of distributing the Actors properly, and failover and the like (you would have to add akka-persistence to get passivation, rehydration, and failover if the Actor has a bunch of strict state associated with it (that must be restored)).
The answer by Jeffrey Chung is indeed of Akka way. The downside of such approach is its low performance. The most performant solution is to use Java's ConcurrentHashMap.computeIfAbsent() method.

Unit testing private methods in Akka

I'm new to akka and I'm trying akka on java. I'd like to understand unit testing of business logic within actors. I read documentation and the only example of isolated business logic within actor is:
static class MyActor extends UntypedActor {
public void onReceive(Object o) throws Exception {
if (o.equals("say42")) {
getSender().tell(42, getSelf());
} else if (o instanceof Exception) {
throw (Exception) o;
}
}
public boolean testMe() { return true; }
}
#Test
public void demonstrateTestActorRef() {
final Props props = Props.create(MyActor.class);
final TestActorRef<MyActor> ref = TestActorRef.create(system, props, "testA");
final MyActor actor = ref.underlyingActor();
assertTrue(actor.testMe());
}
While this is simple, it implies that the method I want to test is public. However, considering actors should communicate only via messages, my understanding that there is no reason to have public methods, so I'd made my method private. Like in example below:
public class LogRowParser extends AbstractActor {
private final Logger logger = LoggerFactory.getLogger(LogRowParser.class);
public LogRowParser() {
receive(ReceiveBuilder.
match(LogRow.class, lr -> {
ParsedLog log = parse(lr.rowText);
final ActorRef logWriter = getContext().actorOf(Props.create(LogWriter.class));
logWriter.tell(log, self());
}).
matchAny(o -> logger.info("Unknown message")).build()
);
}
private ParsedLog parse(String rowText) {
// Log parsing logic
}
}
So to test method parse I either:
need it to make package-private
Or test actor's public interface, i.e. that next actor LogWriter received correct parsed message from my actor LogRowParser
My questions:
Are there any downsides on option #1? Assuming that actors communicating only via messages, encapsulation and clean open interfaces are less important?
In case if I try to use option #2, is there a way to catch messages sent from actor in test downstream (testing LogRowParser and catching in LogWriter)? I reviewed various examples on JavaTestKit but all of them are catching messages that are responses back to sender and none that would show how to intercept the message send to new actor.
Is there another option that I'm missing?
Thanks!
UPD:
Forgot to mention that I also considered options like:
Moving logic out of actors completely into helper classes. Is it common practice with akka?
Powermock... but i'm trying to avoid it if redesign is possible
There's really no good reason to make that method private. One generally makes a method on a class private to prevent someone who has a direct reference to an instance of that class from calling that method. With an actor instance, no one will have a direct reference to an instance of that actor class. All you can get to communicate with an instance of that actor class is an ActorRef which is a light weight proxy that only allows you to communicate by sending messages to be handled by onReceive via the mailbox. An ActorRef does not expose any internal state or methods of that actor class. That's sort of one of the big selling points of an actor system. An actor instance completely encapsulates its internal state and methods, protecting them from the outside world and only allows those internal things to change in response to receiving messages. That's why it does not seem necessary to mark that method as private.
Edit
Unit testing of an actor, IMO, should always go through the receive functionality. If you have some internal methods that are then called by the handling in receive, you should not focus on testing these methods in isolation but instead make sure that the paths that lead to their invocation are properly exercised via the messages that you pass during test scenarios.
In your particular example, parse is producing a ParsedLog message that is then sent on to a logWriter child actor. For me, knowing that parse works as expected means asserting that the logWriter received the correct message. In order to do this, I would allow the creation of the child logWriter to be overridden and then do just that in the test code and replace the actor creation with a TestProbe. Then, you can use expectMsg on that probe to make sure that it received the expected ParsedLog message thus also testing the functionality in parse.
As far as your other comment around moving the real business for the actor out into a separate and more testable class and then calling that from in the actor, some people do this, so it's not unheard of. I personally don't, but that's just me. If that approach works for you, I don't see any major issues with it.
I had the same problem 3 years ago, when dealing with actors : the best approach i found was to have minimum responsability to the actor messenging responsability.
The actor will receive the message and choose the Object's method to call or the message to send or the exception to throw and that's it.
This way it will be very simple to mock up either the services called by the actor and the input to those services.

Conditional ExecutionHandler in pipeline

The server I'm developing has different tasks to perform based on messages received from clients, some tasks are very simple and require little time to perform, but other may take a while.
Adding an ExecutionHandler to the pipeline seems like a good solution for the complicated tasks but I would like to avoid threading simple tasks.
My pipeline looks like this:
pipeline.addLast("decoder", new MessageDecoder());
pipeline.addLast("encoder", new MessageEncoder());
pipeline.addLast("executor", this.executionHandler);
pipeline.addLast("handler", new ServerHandler(this.networkingListener));
Where MessageEncoder returns a Message object (for decode) which defines the requested task.
Is there a way to skip the execution handler based on the decoded message?
The question can be generalized to: is there a way to condition whether or not the next handler will be used?
Thanks.
Instead of using ExecutionHandler as is, you can extend it to override its handlerUpstream() method to intercept the upstream events and call ctx.sendUpstream(e) for the MessageEvents whose message meets your criteria. All other events could be handled by the ExecutionHandler via super.sendUpstream(e). That is:
public class MyExecutionHandler extends ExecutionHandler {
public void handleUpstream(ctx, evt) throws Exception {
if (evt instanceof MessageEvent) {
Object msg = ((MessageEvent) evt).getMessage();
if (msg instanceof ExecutionSkippable) {
ctx.sendUpstream(evt);
return;
}
}
super.handleUpstream(evt);
}
...
}
You can remove it (or add it on demand) from the pipeline inside your MessageDecoder before you send the message upstream. You can also check the message inside your executionHandler and just pass it upstream.
In case you cannot modify these two files you can create another handler which removes executionHandler based on the message type.

Java ExecutorCompletionService as API Responder

I have a server application that listens on a ServerSocket for incoming queries. The clients submitting the queries expect to open a socket to the server, pass their query upstream, and then (possibly after a short period of time) read the response to their query from the same socket that they used to submit the query.
For this I am trying to use an ExecutorCompletionService. Different query classes are passed to different Callables, but all are expected to return a String as their result.
All of this is quite manageable until I reach the stage of actually trying to reply to the clients. The Future objects are currently all of type Future<String>, but I am unable to marry that result (the String) up to the appropriate Socket.
My solution is about to be to make all of my Callables be of type Callable<StringSocketPair> where StringSocketPair looks like;
public class StringSocketPair {
Socket sock;
String content;
}
But this all seems a little odd, as now I have to pass the Socket to the Callable constructor, so that it can return it alongside the String result from its call() method. All so that I can push the String onto the Socket in yet another thread which polls ExecutorCompletionService.take().
The other option is to use Runnables instead of Callables and have each Runnable task respond on its own Socket, but as I have a dozen or so query types, each has their own task object, and I'd rather not have to add a respondToClient() call of some kind to the end of every run() method for every task object.
There must be a simpler solution to what I would think is a fairly common setup?
Following the idea of using a Runnable, you could use the Template Method Pattern to define the functionality for responding. This would prevent you from having to write that common code for every task as the common code would be placed in the abstract parent class which implements Runnable.
Template Method Pattern:
abstract class TemplateSuperClass implements Runnable {
public void run() {
//some setup code here
String message = taskWork(...);
socket.write(message);
//common cleanup code
}
abstract String taskWork(...);
}
class HelloWorld extends TemplateSuperClass {
String taskWork(...) {
return "Hello World";
}
}
Otherwise, you are probably right to change the Callable to return the tuple of response message and socket.

Ashynchronous Multithreaded

I have a centralized socket class which is responsible for sending and retrieving data. I have 2 classes:
one which listens to the input stream and
the other one which takes care of writing to it.
Listening running on an infinite loop and then process the messages. For synchronous i block the read and reset these values once i receive the response from the server.
Now i am stuck with asycnhronous. I have 3 methods in my service.
getSomething
readSomething
saySomething.
In my getSomething i want to implement async functionality based on the boolean flag provided. When my app starts i also start both of my threads and if i send concurrent request.
For example readSomething first and then getSomething then i get the return value for readSomething in getSomething which is not what i desire and i can see in the logs that the output for getSomething comes after a while.
It looks like the Future object requires to submit a new task which will run in it's own thread but the way i have design this app, i just can't create a new thread. Can anyone give me insights on how should i handle this asycnhronous like a flow chart etc ?.
If you're doing work Asynchronously, that means that other part of the application does not care when the async work is done.
What you'll normally want to do is notify the other part, when the async work is done. For this, you'll want to use the "Observer Pattern" (the article includes flow-charts).
The basic idea is, that your app starts the async work and is notified, when the work is done. That way, you can loosely couple two parts of the application. A quick example:
/**
* The observer
*/
public interface AsyncWorkDoneListener{
/**
* This method will be called when the async-thread is
* done.
*/
public void done(Object unit);
}
/**
* The worker (which does the asyc-work on another thread).
*/
public class AsyncWorker{
private AsyncWorkDoneListener listener;
/**
* Set (you might want to maintain a list here) the current
* listener for this "AsyncWorker".
*/
public void setListener(AsyncWorkDoneListener listener){
this.listener = listener;
}
/**
* Will do the async-work
*/
public void doWork(){
// Do the work in another thread...
// When done, notify the registered listener with the
// result of the async work:
this.listener.done(the_object_containing_the_result);
}
}
/**
* The application
*/
public class App implements AsyncWorkDoneListener{
public void someMethod(){
// Work on something asynchronously:
mAsyncWorker.setListener(this);
mAsyncWorker.doWork();
}
#Override
public void done(Object unit){
// The asyc work has finished, do something with
// the result in "unit".
}
}
A couple of insights:
you need dataflow, not flow charts
if you cannot create new thread for each task, you can use fixed-sized thread pool created by java.util.concurrent.Executors.newFixedThreadPool()
you cannot use Future.get() from within a task running in a threadpool, or thread starvation deadlock may occur.
your description of the problem is unclear: too many undeclared notions. "reset these values" - what values? "3 methods in my service" - is it server side or client-side? "boolean flag provided" - do we need to understand who provided that flag and what does it mean?
Please provide a dataflow representation of the program you need to implement in order we could help you.

Categories