I start my actor in controller in Play 2. I read somewhere that I must stop my actors. When I stop it as in example below I got the problem that file do not upload at all. When I comment it starts uploading it.
//Akka
ActorSystem system = Akka.system();
ActorRef uploader = system.actorOf(new Props(UploaderActor.class), "uploader");
uploader.tell(new Uploader(post.id, "/public/images/post/",post, request()), uploader);
//system.stop(uploader);
Please help.
My question is: When I must stop my Actors?
One additional question:
How can I access this actor in another controller(get this reference) ?
I'd suggest to create a long-lived uploader that you send the upload-messages to, and it can internally create new actors to handle the actual uploads and shut them down if need be. This frees the client, you, from managing the life-cycle.
If this actor is meant to be short lived and only process a single request, then you can have the actor stop itself in the receive method after it's done like this:
getContext().stop(getSelf());
That way you can be sure the actor is done before being stopped. For your second question, if you want to look up this actor instance from somewhere else, all you need is a reference to the actor system that it is running in. If you have that then it's just:
ActorRef ref = system.actorFor("/user/uploader")
If you are going to be spawning multiple uploaders at a time then be sure to name them uniquely. The name you give it when starting it is the name you can use to look it up from some other piece of code.
Related
I have an actor system "Main" running potentially forever. This main actor understands "Snapshot" or "Stop" messages (defined by me).
I would like to create a bash script that, while Main actor is running, launches a second (short lived) system, or actor, or whatever and sends a snapshot or stop message to the Main actor.
With akka classic that was very easy with actorSelection from a secondary actor
ActorRef mainActorRef = Await.result(system.actorSelection("akka.main.actor.path").resolveOne(timeout));
mainActorRef.send(new StopMessage() or new SnapsthotMessage());
What is the analogous and hopefully equally easy solution in akka typed?
Ok, let's try to sort this mess a bit... First of all, your question is highly unclear:
In the title, you ask for something based on two JVMs, but in the text you ask for a "second (short lived) system, or actor, or whatever". No clue if multiple JVMs are a requirement or just an idea to solve this. Additionally, your example code is something that - disregarding clustering - works in one JVM and you also only mention a second "actor" there.
So, if the requirement is using two JVMs, then I would suggest making it more clear in what way, why, etc. Then people can also actually provide help for that part.
For now, let me assume you want to simply have...
A (typed) actor system
...that can somehow process StopMessage/SnapshotMessage...
...both of which can be triggered from the outside
The way you can do this very simply is the usual typed way:
Define a RootGuardian actor that accepts those two messages (that actor is basically what the implicit /user actor was in classic) - you have to do that for your Typed actor system anyway (because to setup a typed actor system, you supply the behavior of the RootGuardian).
Let it create the needed child actors to process those messages (either at start or when needed). Of course, in your simple example, the root guardian can also process these messages itself, but an actorsystem with only one actor is not a very typical use-case.
Let it delegate the messages to the appropriate child actor(s)
Add a simple api endpoint to call system.tell ( ... ) to send the message into the system, where your RootGuardian actor will delegate it correctly.
Use curl to call your api endpoint (or use any other way to communicate with your application, there are dozens, but most of them are outside the scope of akka itself)
As a general idea, Akka Typed tends to be much more strict about who can send what messages where. In Akka classic, it was easy to basically send everything everywhere and find and access any actor from everywhere, including outside the system. Unfortunately, this "freedom" leads to a huge amount of problems and was thus severely limited in Typed, which makes for clearer contracts and better defined message flows.
Of course, in a highly complex system, you might, for example, want to use a Receptionist instead to find the target actor for your specific message, but since the question was for a simple application, I would skip that for now.
You can, of course, also add ways to get your ActorRefs outside the system, for example by using the Ask Pattern to implement something like an actor discovery in the RootGuardian, but there is simply no need to try to circumvent the concepts of Akka Typed by re-implementing ActorSelection.
Obviously you also could use clustering, start up a 2nd JVM, connect it to the cluster, send the message and shut it down again, but we can assume that this would be overkill and very, very slow (waiting for long seconds while starting up the app, connecting to the cluster, etc. just to then use a few milliseconds to send the message).
If you absolutely want a 2nd JVM there, you can, of course, for example, create simply REST client that sends the message and start that, but... curl exists, so... what for?
So, tl;dr: The "analogous and hopefully equally easy solution" is system.tell( new StopMessage() );, which is basically the same in akka typed as the code for akka classic you provided. Obviously, implementing the actor system in a way that this code works, is the (slightly) more tricky part.
First, to shortly describe my problem. Based on the simbad simulator ( http://simbad.sourceforge.net/doc.php - not important for my question ), I want to build a system that deploys rovers which will explore the environment. The idea is that these rovers will avoid obstacles in the environment as well as other rovers. Let's call this a simulation.
The main elements in this simulation are of course the rovers, the environment, and a central station which will control the rovers and also send commands to it. This will run on a thread.
What I would like to have, is on another thread/process, to have a listener. This will listen to commands inputted from the keyboard and translate them into commands that will be applied in my simulation by the central station.
For example, each rover might have an ID, and I might want to remove a remover based on its id. Then I'd like to write something like: remove rover 1, the listener that is running on another thread maps this to a command and for example calls the function centralStation.removeRobot(id_of_robot).
What is the best way of implementing this ? Basically I will have 2 threads, one running the simulation, one listening to commands, and the centralStation should be a shared resource ? How do I make it a shared resource (make a main, initiate the central station, then call the other 2 threads to start doing their job? ) ?
I was wondering what the best practices for this is, and how to make it as simple as possible.
Thank you :)
A simple solution is to simply put an appropriate data structure "between" your components.
For example an instance of ConcurrentLinkedQueue. The idea here: your "input" thread writes "command" objects into that queue; and the other thread looks into that queue, and when it finds a new command, that is "applied" to the simulation.
The important aspect is: you really do not want that two threads are operating on the same data somehow.
Well how about Java Exchanger, where String is the id of rover/command that your listener would transfer to central station
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html
If I am understanding it correct then you want to start the system and at runtime pass the rover id/command, after processing it via a Listener(which would be in a separate thread), to the central station(which would be in a separate thread).
So how I might have proceeded with this would be:
In main thread, start the simulator, Create an Exchanger, and start two threads, one for central station and another for listener.
// pseudocode for main
main() {
// start simulator ( I am not sure what this thing is)
Exchanger<String> exc = new Exchanger<String>();
new CentralStationThread(exc);
new CommandListenerThread(exc);
}
Now in CentralStationThread one of the first thing that you might wanna do is register with the listener
//pseudocode for run method of central station
public void run(){
String roverIdToStop = exc.exchange(new String);
// some code to trigger the rover stop
// send in replacement rover
}
And something similar in CommandListenerThread thread, but not at start
//pseudocode for run method of listener
public void run(){
// Listen to keyboard
// String roverIdOrCommand = Parse the command & make something out out it
// when the command is ready to be sent to central station do following
String roverIdToStop = exc.exchange(roverIdOrCommand);
// keep looking for further commands
}
I agree, There might me several ways to achieve the same but this is what came to my mind. Hope it helps !
I'm trying to use GPars in Java to handle messages of a few types.
There is one actor for each message type.
But message processing takes a lot of time, while messages keep coming. I need to ignore upcoming messages (just throw them away) while the actor is busy.
How do I know if an GPars actor is busy? I know about Actor.isActive() method, but I'm not too sure that it is the thing (the JavaDoc is pretty ambiguous and unclear) and I couldn't find any useful info ether.
There's no built-in way to determine this, I'm afraid. You'd have to implement a busy-controlling algorithm yourself, perhaps based on CountdownLatches.
In general, this can be problematic, as an actor can only process one message at a time, whatever solution you have to do this, will have limitations. For instance you can have an actor within an actor, a supervisor and a worker.
The worker actor is the one which actually does the work. What happens is work is sent to the supervisor. The supervisor has a boolean variable such as isBusy, which is initially false. When work is received the supervisor sets the variable to true, and passes the work on to the worker. When the work is finished the worker sends the result back to the supervisor and the supervisor sets the isBusy to false and returns the result.
If another message comes in whilst the isBusy is false the supervisor can just send a message back such as an isBusy message, or do nothing which is what you say you want.
Note that if the worker crashes, or restarts, the isBusy will still be true. You will need to think about this solution, if it will meet your needs. There maybe a mailbox which would be better for this I don't know.
Whatever you do, you should try your best to avoid creating situations where you could leave your actor system in a bad state, best of luck.
My project is not using Akka as of now, it runs as a single process and does too many things.
As a first inital step, we are trying to put a scaffolding in place so that we get Fault Tolerance. For example,
ProjectSupervisor
|
ExistingProcessActor
Where ExistingProcessActor would run as a forever long running job anf if it gets killed because of some Exception, ProjectSupervisor will restart it
I wasn't too sure about this, so I asked on user-group, and received an interesting advice as
[Me] def run: Unit = LogReaderDisruptor.main(Array())
is a method that is supposed to run forever, plus it required some setup (that is available on client's machine or test environment)
[Advice here] By that do you
mean that the main() is never returning? If so, then you're blocking
the Actor and wasting an entire thread. Spawn this off on a dedicated
dispatcher instead (see dispatchers and futures docs).
I went through the documentation but did not understood what I need to do.
Does that mean following?
ExistingProcessActor will start a new future by giving a custom dispatcher of type PinnedDispatcher?
If so, then in case of any failure how would ProjectSupervisor be notified? He is monitoring ExistingProcessActor and not future (future is not Actor)
I am confused, kindly guide me
You don't need to use a Future in order to have the work done in a dedicated dispatcher. This can be done by spawning an actor and assigning that actor to the dedicated dispatcher. A simple example from the akka docs:
val myActor =
context.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), "myactor1")
http://doc.akka.io/docs/akka/snapshot/scala/dispatchers.html
You could do this within your project supervisor when creating the ExistingProcessActor, putting that actor on a pinned dispatcher, and then your supervision strategy will continue to work as you want.
I have a Java class which creates a supervisor Actor which then creates a child actor for each request it needs to generate.
Java class uses a Future to get response back from supervisor Actor
Supervisor uses tell and sender reference to get response back from child Actor
However my supervisor Actor is a singleton scoped bean so i need to be able find a way to store the sender reference each time my Java class makes a request to the supervisor. What is the best way to do this?
I don't think singleton scope is a good isea, as Akka needs to be able to restart actors when exceptions occur. That might lead to some weird problems. We used prototype scope ourselves.
Other than that, one possibility is to simply decouple receiving the request and sending the response by passing the server through your actors, you just use forward instead of tell, and the last actor in your pipeline will respond to the sender. This way the supervisor does not need to care about the response. Obviously this is ideal if your supervisor does nothing but sending the response to the sender.
If there is some processing to be done before sending the response, you can create a temporary actor and pass it the sender reference, and let this actor collect the results, send the response to your future and stop itself. This is especially useful if you need to wait for more than one response and aggregate it.
You can also add the sender reference to the message you send from the supervisor to your actors and back to the supervisor. Simple, yet effective.