2016-07-25 4 views
1

Я хочу сделать что-то вроде этого -Возвращаясь к «отправитель» из будущего внутри актера

class MyActor extends Actor { 
.... 
override def receive = { 
    case msg => 
    .... // do something 
    Future { 
     ... // calculate response 
     sender ! response 
    } 
} 
} 

// in some other code - 
val future = myActorRef ? msg 
future.onSuccess { 
    .... 
} 

бы эту работу? Другими словами, помогает ли Akka «спросить», отвечает ли ответ, прежде чем метод «получать» заканчивается или нет?

ответ

5

Да он будет работать, и есть даже встроенный AKKA шаблон для него - pipe:

import akka.pattern.pipe 

override def receive = { 
    case msg => 
    .... // do something 
    Future { 
     ... // calculate response 
     response 
    } pipeTo sender() 
} 

Там, однако некоторые предостережения в коде следует отметить:

sender является функция, поэтому, когда код внутри вашего блока Future{...} выполняется, актер может обрабатывать сообщение от другого отправителя, чтобы вы могли ответить неверному отправителю. Чтобы избежать этого, оценить ваш отправитель вне замыкания:

val mySender = sender() 
Future { 
    ... // calculate response 
    mySender ! response 
} 

Вы, однако, не нужно беспокоиться об этом, если вы используете pipe.


Вы обертывание будущего в качестве актера и называя этот актер с ask, который снова дает вам будущее. Вы должны действительно думать о будущем, без актеров. Если вам действительно нужен актер, например. потому что вы изолируете какое-то изменчивое состояние или упорядочиваете сообщения, важно знать, что вычисление Future не будет происходить в потоке актера, так что вы теряете согласованность состояния и порядок сообщений - еще одна причина считать проигрыш актера и зная будущее напрямую.

+0

Обычно я не буду искать будущее внутри актера (где актер почти ничего не делает). Но в моем случае я зависим от другой библиотеки, которая может отправлять сообщения только актеру (и это также как вопрос). Отсюда вопрос :-) – anindyaju99

1

Проблема в том, что sender может быть недействительным, когда будущее будет выполнено. У вас есть несколько вариантов, вот два из верхней части моей головы:

Вы можете захватsender перед будущим:

override def receive = { 
    case msg => 
    .... // do something 
    val replyTo = sender 

    Future { 
     ... // calculate response 
     replyTo ! response 
    } 
} 

Или вы можете использовать pipeTo шаблона:

override def receive = { 
    case msg => 
    .... // do something 
    import akka.pattern.pipe 

    Future { 
     ... // calculate response 
    }.pipeTo(sender()) 
}