远程actor用jobID和结果来回应未来

时间:2013-04-03 09:55:34

标签: scala akka

在不同JVM上的远程Akka演员之间发送消息的未来是否安全/可行?我怀疑不是。那么我怎样才能实现如下的目标。关键方面是尝试让答复(Ack)返回未来结果,以及允许取消的参考。

case class BigJob()
case class Ack(jobId: Long, result: Future[Int])
case class Cancel(jobID: Long)

val ack = (remoteActor ? BigJob()).mapTo[Ack]

if(changedMyMind) remoteActor ! Cancel(ack.jobID)
else ack.result foreach println

更新:使用Scala 2.10.1和Akka 2.1.2

1 个答案:

答案 0 :(得分:1)

对于远程演员,你可以使用额外的等待演员:

var myActor = actor {
  var waitingSender: Option[OutputChannel[Any]] = None
  var result: Option[BigJobResult] = None
  val jobID = remoteActor !? StartBigJob() match { case l: Long => l }
  loop {
    react {
      case "stop" =>
        remoteActor ! Cancel(jobID)
        exit
      case "getResult" => result match {
        case Some(r) =>
          sender ! r
          exit
        case None => waitingSender = Some(sender)
      }
      case r: BigJobResult => waitingSender match {
        case Some(s) =>
          s ! r
          exit
        case None => result = Some(BigJobResult)
      }
    }
  }
}.start 

if(changedMyMind) myActor ! "stop" 
else myActor !? "getResult" ...

更新:使用akka

case object ChangedMyMind
case object GetResult
case object BigJob
case class BigJobResult(i: Int)
case class Cancel(jobId: Long)
case class JobStarted(jobId: Long)

val remoteActor = actor( new Act {
  become {
    case c: Cancel => println(c); context.stop(self)
    case BigJob =>
      val target = sender
      sender ! JobStarted(666)
      Future{ Thread.sleep(10000); target ! BigJobResult(13) }
  }
})

val a = actor(new ActWithStash {
  whenStarting { remoteActor ! BigJob }
  become {
    case JobStarted(jobId) => unstashAll(); becomeStacked {
      case ChangedMyMind => remoteActor ! Cancel(jobId); context.stop(self)
      case r: BigJobResult => unstashAll(); becomeStacked {
        case GetResult => sender ! r; context.stop(self)
        case ChangedMyMind => context.stop(self)
      }
      case GetResult => stash()
    }
    case ChangedMyMind | BigJobResult(_) | GetResult => stash()
  }
})

if(changedMyMind) a ! ChangedMyMind
else (a ? GetResult) foreach println