演员如何知道它是否具有进行所需的所有响应?

时间:2015-05-25 17:04:00

标签: scala akka

我对akka很新,不确定是否接近这个问题。

  • 我有一个Monitor演员,以DiskMonitorMemoryMonitor

  • 的形式产生其他两个演员
  • DiskMonitor检查diskUsage并报告DiskReport消息

  • MemoryMonitor检查diskUsage并报告MemoryReport消息

我想将DiskReportMemoryReport合并到Report对象中,并通过API发送到远程计算机。

问题

由于DiskMonitorMemoryMonitor都是演员,因此他们在完成工作后会将响应发送回来电

监控

diskMonitor ! DiskMonitorRequest
memoryMonitor ! MemoryMonitorRequest

Monitor如何知道它具有所需的所有结果,以便它可以创建Report对象并通过API发送它?

演员是解决这个问题的好方法吗?

我也读到了关于未来但我不太了解它们并且不确定它们是否会对这个问题背景有所帮助

2 个答案:

答案 0 :(得分:1)

这是做这些事情的简单方法。其他选项可以使用context.become或特征FSM

class Monitor extends Actor {
  // Somewhere do this:    
  diskMonitor ! DiskMonitorRequest
  memoryMonitor ! MemoryMonitorRequest

  var diskMonitorResult = Option.empty[DiskMonitor]
  var memoryMonitorResult = Option.empty[MemoryMonitor]

  def recieve = {
    case d: DiskMonitor => 
      diskMonitorResult = Some(d)
      checkIfCompleted()
    case m: MemoryMonitor =>
      memoryMonitorResult = Some(m)
      checkIfCompleted()
  }

  def checkIfCompleted = {
    (diskMonitorResult, memoryMonitorResult) match {
      case (Some(diskMonitor), Some(memoryMonitor)) =>
         // send to external API
         externalApi ! Report(diskMonitor, memoryMonitor)
         // Possibly stop this actor
      case _ => // do nothing
    }
  }
}

答案 1 :(得分:0)

您可以使用询问模式并结合期货..

import akka.actor._
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._

sealed trait Message
case object Create extends Message
case object MakeDiskReport extends Message
case object MakeMemoryReport extends Message
case class DiskReport(report: String) extends Message
case class MemoryReport(report: String) extends Message
case class Report(memReport: String, diskReport: String) extends Message

class Monitor extends Actor with ActorLogging {

  implicit val timeout = Timeout(5 seconds)
  implicit val ec = context.dispatcher

  val diskM = context.system.actorOf(Props[DiskMonitor])
  val memoryM = context.system.actorOf(Props[MemoryMonitor])
  val remoteM = context.system.actorOf(Props[RemoteMachine])

  override def preStart = {
    // can also be send at start of actor creation or scheduled 
    log.info("Monitor Created..")
    self ! Create
  }

  override def receive = {
    case Create => {
      ask(diskM, MakeDiskReport).mapTo[DiskReport]
        .flatMap { diskR =>
          ask(memoryM, MakeMemoryReport)
            .mapTo[MemoryReport].map { memR => remoteM ! Report(memR.report, diskR.report) }
        }
    }
  }
}

class DiskMonitor extends Actor with ActorLogging {
  override def receive = {
    case MakeDiskReport => {
      log.info("Creating DiskReport..")
      val client = sender
      client ! DiskReport("DiskReport")
    }
  }
}

class MemoryMonitor extends Actor with ActorLogging {
  override def receive = {
    case MakeMemoryReport => {
      log.info("Creating MemoryReport..")
      val client = sender
      client ! MemoryReport("MemoryReport")
    }
  }
}

class RemoteMachine extends Actor with ActorLogging {
  override def receive = {
    case Report(memr, diskr) => {
      log.info(s"Final Report.. $memr, $diskr")
    }
  }
}

object Main extends App {
  val sys = ActorSystem()
  sys.actorOf(Props[Monitor])
}