Reputation: 63
When working with Actors, if an Actor needs to co-operate with multiple other Actors to fulfil a request then what's the recommended approach here? To be more precise, if Actor A (through processing message M) needs to retrieve information from Actor B + Actor C, then it can send messages asynchronously to Actor B + C, but how should it correlate the responses from Actor B + C to the original message M ?
I've looked at the Akka framework and can't see how this is done so have had to implement something myself whereby an Actor keeps track of what messages have been sent and attempts to correlate their responses back to the source message. I must be missing something as I would've thought that this type of behaviour would already be built into various Actor frameworks
Upvotes: 2
Views: 842
Reputation: 26579
Just create a new actor and use that to preserve the context and stop it after a timeout or when it has performed the "join". You can also use Future-composition instead of spawning an actor:
class A extends Actor {
def receive = {
case DoX(x) =>
val b = actorB ? DoYourPartOf(x) mapTo manifest[BResult]
val c = actorC ? DoYourPartOf(x) mapTo manifest[CResult]
b zip c map { case (b,c) => merge(b,c) } pipeTo sender
}
}
}
Or Dataflow:
class A extends Actor {
def receive = {
case DoX(x) => flow {
val b = actorB ? DoYourPartOf(x) mapTo manifest[BResult]
val c = actorC ? DoYourPartOf(x) mapTo manifest[CResult]
merge(b(),c())
} pipeTo sender
}
}
}
Upvotes: 1
Reputation: 14053
Generally if you need to send a message and get a correlated response, you end up having to send some kind of nonce in the original message that the responder must return with its reply. This can be explicit or it can be supported in the messaging layer. Not sure about Akka, but that's how Erlang handles RPCs in OTP.
Upvotes: 2