2012-09-17 45 views
6

我正在与Akka 2制作一个小型缓存演员,并且让演员不会阻止我在期货内执行所有计算。然而,一个问题是,这个角色还需要与不在actor中的代码进行交互,这样我需要使用“ask”模式来获得一个值。Akka在回应非演员代码时避免包装未来

我的问题是,如何在使用ask模式时避免将未来的计算包裹在另一个Future中?

例如

val f = myCache ? GetOrCalc("myKey", myCalculation) // this will be a Future[Future[...]] but I would like a Future[...] 

// meanwhile, inside the actor 
def receive = { 
    case GetOrCalc(key, calculation) => 
     if (keyNotExists) sender ! Future { calculation() } // calculation() is long-running 
     else sender ! cacheMap(key) 
} 

理想的情况下,我可以使用Future.pipeTo功能,但恐怕这并不被计数为“响应”非演员代码

回答

6

这是解决方案:

val f = myCache ? GetOrCalc("myKey", myCalculation) 

def receive = { 
    case GetOrCalc(key, calculation) => 
     if (keyNotExists) Future { calculation() } pipeTo sender 
     else sender ! cacheMap(key) 
} 

发送和接收,未来“> http://doc.akka.io/docs/akka/2.0.3/scala/actors.html# Ask_Send-And-Receive-Future

+0

奇怪的是,这正是我的原始伪代码,甚至没有测试它,因为我认为pipeTo不会作为“响应”工作。这就是我没有测试,只是假设!虽然事实被告知这种行为不在我上面提到的文档中。非常感谢Viktor! – Aktau

+3

相信巴生 –

+0

我想知道“pipeTo发件人”如何安全地访问发件人。我明白为什么你不能在Future中访问发件人,但是pipeTo发件人怎么没有同样的问题。是否因为pipeTo在未来完成之前在演员的上下文中评估发件人? –

3

添加的onComplete到未来的计算。

def receive = { 
    case GetOrCalc(key, calculation) => 
     if (keyNotExists) // calculation() is long-running 
      Future { calculation() } onComplete { 
       case Right(result) => result match { 
         case Some(value) => sender ! value 
         case None => sender ! Status.Failure(new Exception("Cannot find the value")) 
        } 
       case Left(ex) => 
        sender ! Status.Failure(ex) 

      } 
     else sender ! cacheMap(key) 
} 

还有一篇关于使用Akka构建缓存系统的文章。 http://letitcrash.com/post/30509298968/case-study-an-auto-updating-cache-using-actors

+0

但是,这不会发送两次吗?一旦未来[未来[...]](发送者!未来{...})和另一次未来[...]( sender!value)?它是否适用于非演员调用代码?如何使用CalcResult消息? – Aktau

+2

已更新代码。实际上,此解决方案来自文章(http://letitcrash.com/post/30509298968/case -study-an-auto-updating-cache-using-actors),我没时间去看现在就哄它。希望这对你有帮助。 –

+0

呵呵,谢谢!几个小时前我正在读这个源文件,其实是因为它谈到了Akka和缓存。我想我没有把它彻底读完,似乎在经过仔细检查之后,或多或少地按照我想要的方式来做。如果它按预期工作,我会选择你的答案作为正确的答案。 – Aktau