When using the pipe pattern in Akka the future failed result is wrapped inside a akka.actor.status.Failure, however the future success result is NOT wrapped in the corresponding akka.actor.status.Success.
I was wondering what is the reasoning behind this decision? Why just the failure and not the success?
It seems more logical to not wrap anything at all.
Here is the link to the implementation:
https://github.com/akka/akka/blob/v2.4-M2/akka-actor/src/main/scala/akka/pattern/PipeToSupport.scala
Let's say you have an actor A that sends a message to actor B and A expects some sort of response message from B. Inside of B, in order for it to do it's work, it needs a Future for some reason. After that Future completes, it wants to send the result back to A. The person who coded B wants to be careful to not close over the sender() when responding back to A, so they use the pipeTo pattern like so:
fut pipeTo sender()
Now back in A, you are expecting a response of a certain type, and you should not have to deal with the internal intricacies of actor B and the fact that it needed a Future in order to do it's work. In other words, you don't want the response to come back to you wrapped in a scala.util.Try (Success or Failure). If you expect a String, then if all goes well, that's exactly what you want back from B. But in the case that everything does not go well in B, A needs to know this and the way that the Akka team chose to do so was to wrap it in Status.Failure. This to me seems better than sending the raw Exception as is.
Now, us, we use a standard communication model between actors where we have something similar to this simple model (simplified for brevity):
sealed trait ServiceResult[+A]
case object EmptyResult extends ServiceResult[Nothing]
case class FullResult[+A](value:A) extends ServiceResult[A]
case class Failure(error:ErrorMessage, ex:Option[Throwable]) extends ServiceResult[Nothing]
All services always respond with some form of ServiceResult. So if we are piping back to a sender() from a Future we do something like this:
fut.recover{case ex => Failure(someErrorMessage, Some(ex)} pipeTo sender()
That way we don't have to really deal with Status.Failure anywhere.
future onComplete will resolve to either scala.util.Success(futureResult) or scala.util.Failure(someThrowable).
If the future succeeds, it is convenient to get back the futureResult directly.
If the future failed, you probably don't want to receive back an unwrapped throwable. It's nicer to get it back wrapped in akka.actor.status.Failure.
Related
I am referring to api
Patters.ask(actor, msg, duration);
here is sample
class MyActor extends AbstractBehavior{
interface Command{}
interface SomeMessage implements Command{ INSTANCE}
public Reveive<Comamnd> receive(){
return newReceiveBuilder().onMessage(SomeMessage.class, this::someMessage).build();
}
private Behavior<Command> someMessage(SomeMessage ref){
System.out.println("Dru lalal");
}
}
ActorRef<MyActor.Command> myActor = ...;
Future<Object> future = Patterns.ask(myActor, SomeMessage.INSTANCE, Duration.ofMillis(10000));
What is gone be object ?
Obviously this won't compile. Some part of picture is missing, but javadoc doesn't state what.
Call "Patterns.ask" suppose to return future with object, those value is provided by actor as business logic. But there is not business logic in actor. I assume there is suppose to be some kind of convention or mapping for method that returns value with what "Patters.ask" triggers.
Same is true about back logic. I will not able to define receiver since it expect to return Receiver not SomeObject and thus, api want't let me bind result to some message. Only thing I can do is manually pass ComputableFuture
ComputableFuture<MyOBject> future = new ComputableFuture<>();
myActor.tell(new Message(future));
private Behavior<Command> someMessage(Message message){
var result = compute();
message.future.comlete(result);
}
And here we go, I have manually manage everything, also issues with passing non serializable message, lifecycle of objects and so on.
Wrong objects is used. Instead of "AskPattern.ask" for new java typed dsl, I used classic "Patterns.ask".
Most of times new api objects has same object name but located in different package. I used to check only package name becouse while playing with in IDE they always next to each other since name is the same. I got used to ignore the classic "com.akka" objects while playing with api.
And here I got into trap, object name is different and not placed in IDE next to "classic" package object.
good day,everyone.
i have some question about how bad is setting CompletableFuture in mesage from one actor to another and use get() to wait for it compleation. i have code example that i think is too complex to use in practice, but cant find any sutable arguments to advice to refactor it
code that send msg with future
private void onSomeSignal(SomeMsg smsg){
MessageToActor msg = new MessageToActor()
future = new CompletableFuture<>();
msg.setFuture(future);
actortRef.tell(msg, null);
response = future.get(2, TimeUnit.SECONDS);
/* do something with responce*/
}
code that complete future (in another actor)
private void onSomeSignal(MessageToActor msg){
response = responseService.getResponse();
msg.getFuture().complete(response);
}
is something wrong here , except that future.get() is blocking operation
Yes, doing that will come back and bite you: with this pattern you block one actor until some other actor responds, which means that if you use that elsewhere in your program there is a high risk of running into a deadlock (i.e. your whole program stops and cannot continue).
Instead of using a Future to send back a response, actors are made for sending messages. In “another actor”, you should use getContext().getSender().tell(response), and in the first actor you should handle that response as a normal message instead of the future.get() call.
Consider the following code bit:
def receive = {
case ComputeResult(itemId: Long) =>
//val originalSender = sender
computeResult(itemId).map { result =>
originalSender ! result
}
}
The computeResult results in a Future, so how would the introduction of a val prevent my from sending the result to the wrong sender? Let us say I have a completely different Senders (sender1 and sender2).
Sender1 first sends a message followed by Sender2. Without the val in my method above, I clearly see that there is a possibility that my Sender2 could get the result that was actually meant for Sender1.
What I don't get is that how would the introduction of a val prevent me from the scenario that I just described?
sender is actually a function (that's why the convention from Akka 2.3 onwards is to write sender()). By binding the value to originalSender, we can close over that immutable value and know that it won't change, even if another message comes in before the Future from completeResult completes.
Because receive is a function, every invocation will result in a new local value called originalSender.
I have a List (e.g. the output of a database query) variable, which I use to create actors (they could be many and they are varied). I use the following code (in TestedActor preStart()), the actor qualified name is from the List variable as an example):
Class<?> classobject = Class.forName("com.java.anything.actor.MyActor"); //create class from name string
ActorRef actref = getContext().actorOf(Props.create(classobject), actorname); //creation
the code was tested:
#Test
public void testPreStart() throws Exception {
final Props props = Props.create(TestedActor.class);
final TestActorRef<TestedActor > ref = TestActorRef.create(system, props, "testA");
#SuppressWarnings("unused")
final TestedActor actor = ref.underlyingActor();
}
EDIT : it is working fine (contrary to the previous post, where I have seen a timeout error, it turned out as an unrelated alarm).
I have googled some posts related to this issue (e.g. suggesting the usage of newInstance), however I am still confused as these were superseded by mentioning it as a bad pattern. So, I am looking for a solution in java, which is also safe from the akka point of view (or the confirmation of the above pattern).
Maybe if you would write us why you need to create those actors this way it would help to find the solution.
Actually most people will tell you that using reflection is not the best idea. Sometimes it's the only option but you should avoid it.
Maybe this would be a solution for you:
Since actors are really cheap you can create all of them upfront. How many of them do you have?
Now the query could return you a path to the actor, not the class. Select it with actorSelection and send messages to it.
If your actors does a long running job you can use a router or if you want to a Proxy Actor that will spawn other actors as needed. Other option is to create futures from a single actor.
It really depends on the case, because you may need to create multiple execution context's not to starve any of the actors (of futures).
I'm writing a little clojure pub/sub interface. It's very barebones, only two methods that will actually be used: do-pub and sub-listen. sub-listen takes a string (a sub name) and do-pub takes two strings (a sub name and a value).
I'm still fairly new at clojure and am having some trouble coming up with a workable way to do this. My first thought (and indeed my first implementation) uses a single agent which holds a hash:
{ subname (promise1 promise2 etc) }
When a thread wants to sub it conj's a promise object to the list associated with the sub it wants, then immediately tries to de-reference that promise (therefore blocking).
When a pub happens it goes through every item in the list for the sub and delivers the value to that item (the promise). It then dissoc's that subname from the map and returns it to the agent.
In this way I got a simple pub sub implementation working. However, the problem comes when someone subs, doesn't receive a pub for a certain amount of time, then gets killed due to timeout. In this scenario there will be a worthless promise in the agent that doesn't need to be, and moreover this will be a source of a memory leak if that sub never gets pub'd.
Does anyone have any thoughts on how to solve this? Or if there is a better way to do what I'm trying to do overall (I'm trying to avoid using any external pre-cooked pubsub libraries, this is a pet project not a work one)?
You can do something like this:
Create an atom
publish function will update the atom value by the passed in value to the function
Subscribers can use add-watch on the atom to be notified of when the atom value changes i.e due to call to publish function
Use remove-watch to remove the subscription.
This way you will have a very basic pub-sub system.
I have marked Ankur's answer as the solution but I wanted to expand on it a bit. What I ended up doing is having a central atom that all client threads do an add-watch on. When a pub is done the atom's value is changed to a vector containing the name of the sub and the value being pub'd.
The function the clients pass to add-watch is a partial function which looks like
(partial (fn [prom sub key ref _old new] ...) sub prom)
where prom is a promise previously generated. The client then blocks while waiting on that promise. The partial function checks if the sub in new is the same as sub, if so it removes the watch and delivers on the promise with the value from new.