i want to use akka actors in parent child hierarchy where the parent can send the final computed result to the calling code which may/may not be an actor here is my use case
parent->child->childManager
childManager has three worker actor (3 childs) childManager (worker1,worker2,worker3)
now worker1 gets the value process it and its response value sends to worker2
- worker1->process the value & send result to worker2
- worker2->process the worker1 result & send worker2 result to worker3
- worker3->process the worker2 result & send final computed value to childManager
- childManager send result to child
- child send result to parent
here is what i am trying to do
final case class GetValue(value:String)
final case class sendToChildManager(value:String)
final case class sendToChild(value:String)
final case class processToken(value:String)
final case class processPublicKey(value:String)
final case class processUserDeatils(accessToken:string,publicKey:PublicKey)
class worker1 extends Actor {
def receive {
case ProcessToken(token)=>
val request = httpRequest(token)
request.onComplete{
case Success(accessToken)=>
//generate access token
sender ! accessToken
case Failure(e)=>throw e
}
}
}
class worker2 extends Actor {
def receive {
case processPublicKey(token)=>
val request=HttpRequest(token)//based on accessToken compute publicKey
request.onComplete {
case Suceess(publicKey)=>
// calculate publicKey from accessToken
sender ! publicKey
case Failure(e)=>throw e
}
}
}
class worker3 extends Actor {
def receive {
case processUserDeatils(accessToken,publicKey)=>
val request = HttpRequest(accessToken,publicKey)
request.onCompelete {
case Success(value)=>
//process the resulted value got userInfo as a result
sender ! UserInfo
case Failure(e)=> throw e
}
}
}
class ChildManager extends Actor {
def receive {
case sendtoChildManager(value)=>
val worker1=context.actorOf//
val worker2=context.actorOf//
val worker3=context.actorOf//
val futureToken = ask(worker1,processToken)
futureToken.onComplete {
case Sucess(token)=>
val futurePublickKey = ask(worker2,processPublicKey(token))
futurePublickKey.onComplete {
case Sucess(publicKey)=>
val futureVerified=ask(worker3,processUserDeatils(token,publicKey))
futureVerified.pipeTo(sender)
case Failure(e)=> throw e
}
case Failure(e)=>throw e
}
}
}
class child extends Actor {
val childMnager = context.actorOf//
def receive {
case sendToChild(value)=>
childMnager.forward(sendtoChildManager(value))
}
class parent extends Actor {
val child = context.actorOf()//
def receive {
case Getvalue(value)=>
child.forward(sendtoChild(value))
}
}
}
object Main {
def main {
val system =ActorSystem("myActorsystem")
val parent=system.actorOf(Props[Parent],"parent")
val future=ask(parent,GetValue("token-id"))
future.onComplete {
case Success(result)=>Complete("user information is",result)
case Failure(e) Complete("InternelserverError",e)
}
}
}
i have read that using onComplete is not recommended to use inside actors and it should be pipeTo to the sender
Warning When using future callbacks, such as onComplete, or mapsuch as thenRun, or thenApply inside actors you need to carefully avoid closing over the containing actor’s reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time. See also: Actors and shared mutable state Warning When using future callbacks, such as onComplete, or mapsuch as thenRun, or thenApply inside actors you need to carefully avoid closing over the containing actor’s reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time. See also: Actors and shared mutable state https://doc.akka.io/docs/akka/current/actors.html#ask-send-and-receive-future
but i want to do all the processing inside an actor so the parent actor return the final computed value to the calling code
how can i achieve that ?
i am using akka http
**Edit**
my problem is how can i use future inside actors as its recommended to not to use .map or onComplete or await,i don't want to send multiple future to the calling code and then calculate the final result i want to send the final calculated result to the calling code