Отправителя внутри будущего
У меня есть актер, который при получении сообщения ищет файловую систему для файла и возвращает полный путь к файлу.
Чтобы сохранить его асинхронным, я сделал:
def receive ={
case s:String => {
val f = future{
val ans = search(s)
println("Input Request: "+s+" output:"+ans+" "+sender.path)
}
f.onComplete{
case Success(x) => sender ! x
case Failure(y) => println("Could not complete it")
}
}
Но я заметил, что он возвращает сообщение akka://FileSystem/deadLetters
, а не sender
. Документация гласит, что:
Действует только в самом Актере, поэтому не закрывайте его и * публиковать его в других потоках!
Так значит ли это, мне придется обязательно поддерживать синхронность? Есть ли другой путь?
Ответы
Ответ 1
Вы делаете очень распространенную ошибку "закрытие изменчивого состояния". Закрытие, которое вы переходите на onComplete
, не делает копию this.sender
, поэтому, когда вы вызываете onComplete
, вы отправляете сообщение на то, что this.sender
указывает на то время, а не то, на что оно указывало когда вы создали закрытие.
Вы можете избежать этой проблемы, создав собственную локальную, неизменяемую копию текущего содержимого this.sender
и ссылаясь на это значение в закрытии:
val origSender = sender
f.onComplete {
case Successs(x) => origSender ! x
...
}
Ответ 2
import akka.pattern.pipe
Есть трюк. Выполнение:
val reply = sender
future {
val ans = searchAndCache(s)
println("Input Request: "+s+" output:"+ans+" "+reply.path)
ans
} pipeTo reply
отвечает отправителю