2012-08-23 2 views
5

나는 akka를 사용하고 있습니다. 비동기 io에 대한 늦은 답장을 해결하기 위해 코드에서 일부 패턴을 보았습니다. 이 구현은 괜찮습니까? 블록없이 늦게 답장을 보내는 또 다른 방법이 있습니까? 응답을 기다리는 것은 ask 방법-a.k.a을 사용하여 보내는 동안Akka의 async io에서 늦게 응답

class ApplicationApi(asyncIo : ActorRef) extends Actor { 
    // store senders to late reply 
    val waiting = Map[request, ActorRef]() 

    def receive = { 
     // an actore request for a user, store it to late reply and ask for asyncIo actor to do the real job 
     case request : GetUser => 
      waiting += (sender -> request) 
      asyncIo ! AsyncGet("http://app/user/" + request.userId) 
     // asyncio response, parse and reply 
     case response : AsyncResponse => 
      val user = parseUser(response.body) 
      waiting.remove(response.request) match { 
       case Some(actor) => actor ! GetUserResponse(user) 
      } 
    } 
} 

답변

5

한 가지 방법은 차단 방지 할 수 있습니다. ? 연산자 - Future을 반환합니다 (!()을 반환 함).

onSuccess 또는 foreach 방법을 사용하면 응답이있는 미래가 완료 될 때 수행 할 작업을 지정할 수 있습니다. 수신 아웃 오브 동기와 효과가 발생하기 때문에,

class ApplicationApi(asyncIo : ActorRef) extends Actor with AskSupport { 

    def receive = { 
    case request: GetUser => 
     val replyTo = sender 
     asyncIo ? AsyncGet("http://app/user/" + request.userId) onSuccess { 
     case response: AsyncResponse => 
      val user = parseUser(response.body) 
      replyTo ! GetUserResponse(user) 
     } 

} 

피가 ApplicationApi 배우의 상태를 수정하는 부작용을 수행하기 위해이 기술을 사용 : 당신이 AskSupport 특성에 혼합하기 위해 필요한이를 사용하려면 고리. 다른 액터로 메시지를 전달하는 것은 안전해야합니다.

그런데

, 여기에 나중에 변수에 할당 할 필요가 피하는, 패턴 일치의 일환으로 현재 sender을 캡처하는 트릭이다.

trait FromSupport { this: Actor => 
    case object from { 
    def unapply(msg: Any) = Some(msg, sender) 
    } 
} 

class MyActor extends Actor with FromSupport { 
    def receive = { 
    case (request: GetUser) from sender => 
     // sender is now a variable (shadowing the method) that is safe to use in a closure 
    } 
} 
+1

나는 정확하다고 생각합니다. 나는'sender'가 Actor를 변경할 수있는 변수가 아니라 Actor의 변경 가능한 속성이라는 사실을 잊어 버렸습니다. –

+2

중절 추출기가 정말 흥미 롭습니다. – sourcedelica

관련 문제