Hi Eax,

Whether this is a race condition, is something that is unclear from the 
code itself. It would help if you would provide us with the expected order 
of operations.

I see 2 possible ways you could have in mind.

First:

(request 1) readSomethingFromDB() 
(request 1) readAndWriteActorState() 
(request 1) writeSomethingToDB()
...
(request 2) readSomethingFromDB() 
(request 2) readAndWriteActorState() 
(request 2) writeSomethingToDB()
...

In which case you can let the actor become waitingForResult and then pipe 
the result of the future to self, upon which it returns it to the original 
sender, and becomes waitingForTask (or similar) again. In this case, you 
need to handle the incoming SomeMessage messages, either by putting them in 
a queue local to the actor, or use a pull pattern (so the actor asks for a 
nextMessage once it completes a task)

Second:

(request 1) readSomethingFromDB() 
(request 2) readSomethingFromDB()
...
(request 1) readAndWriteActorState() 
(request 2) readAndWriteActorState()
...
(request 1) writeSomethingToDB()
(request 2) writeSomethingToDB()
...

In this case, you could create a couple of actors, working in serie, each 
of them doing a single task. You can forward the initial sender with each 
result if that sender is waiting for the response...


In any case, when using Futures within actors, you should be careful with 
just using sender, as it is a function call within the execution context of 
an actor. Once the future returns, the actor might already have moved on to 
processing a new message from another sender, to which the result of the 
future would then wrongfully get returned. You should do something like

val originalSender = sender
val fResult = for ...

fResult pipeTo originalSender

pjan

On Tuesday, June 2, 2015 at 3:49:43 AM UTC+9, Eax Melanhovich wrote:
>
> Hello. 
>
> As I understand code like this is quite common: 
>
> def receive = { 
>   case r: SomeMessage => 
>     val fResult: Future[SomeResult] = { 
>       for { 
>         _ <- readSomethingFromDB() 
>         _ = readAndWriteActorState() 
>         _ <- writeSomethingToDB() 
>         _ <- doSomethingElse() 
>       } yield result 
>     } 
>     fResult pipeTo sender 
> } 
>
> In such cases it is a good idea to use Stash trait and become / 
> unbecome to avoid cases like this: 
>
> (request 1) readSomethingFromDB() 
> (request 2) readSomethingFromDB() 
> (request 2) readAndWriteActorState() 
> (request 1) readAndWriteActorState() 
> (request 1) writeSomethingToDB() 
> (request 2) writeSomethingToDB() 
> ... etc ... 
>
> Which clearly is a race condition and almost always is not something 
> what programmer really wants. Still as I understand there is no 
> stashedPipeTo method or something like this in Akka, so every team has 
> to write its own version. 
>
> Am I right so far? And is there any reason not to add such a method to 
> Akka? 
>
> -- 
> Best regards, 
> Eax Melanhovich 
> http://eax.me/ 
>

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

Reply via email to