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.