木曜日, 12月 24, 2015

Scala - akka アクタ

Akka actorのサンプルメモ..

import akka.actor._

/**
  * Created by neko32 on 2015/12/23.
  */

sealed abstract trait Message
case class Request(a:Int, b:Int, op:Operator) extends Message
case class Response(a:Int, b:Int, op:Operator, result:Int) extends Message
case class ExecStart(cmd:String) extends Message
case class ExecEnd(a:Any) extends Message

sealed abstract class Operator(a:Int, b:Int) {
  def calc():Int
}
case class Plus(a:Int, b:Int) extends Operator(a,b) {
  override def calc() = a + b
  override def toString() = " + "
}
case class Minus(a:Int, b:Int) extends Operator(a,b) {
  override def calc() = a - b
  override def toString() = " - "
}
case class Multiply(a:Int, b:Int) extends Operator(a,b) {
  override def calc() = a * b
  override def toString() = " * "
}
case class Divide(a:Int, b:Int) extends Operator(a,b) {
  require(b != 0, "zero divide not allowed")
  override def calc() = a / b
  override def toString() = " / "
}

class CalcWorker extends Actor {
  override def receive = {
    case Request(a,b,op) if op.isInstanceOf[Plus] => println("sending.."); sender ! Response(a, b, op, a + b)
    case Request(a,b,op) if op.isInstanceOf[Minus] => sender ! Response(a, b, op, a - b)
    case Request(a,b,op) if op.isInstanceOf[Multiply] => sender ! Response(a, b, op, a * b)
    case Request(a,b,op) if op.isInstanceOf[Divide] => sender ! Response(a, b, op, a / b)
    case ExecEnd => context.stop(self)
  }
}

trait Requester extends Actor with ActorLogging {
  override def receive = {
    case Response(a, b, op, rez) =>
      log.info(s"got result from calc agent .. ${a}${op}${b} = ${rez}")
    case ExecStart(cmd) => run(cmd)
    case ExecEnd => context.stop(self)
    case _ => log.info("....")
  }
  def run(cmd:String)
}

class CalcRequester(calcAgent:ActorRef) extends Requester {

  def toOp(vals:Array[String]):Operator = vals(2) match {
    case s if s == "plus" => Plus(vals(0).toInt, vals(1).toInt)
    case s if s == "minus" => Minus(vals(0).toInt, vals(1).toInt)
    case s if s == "mult" => Multiply(vals(0).toInt, vals(1).toInt)
    case s if s == "div" => Divide(vals(0).toInt, vals(1).toInt)
  }

  override def run(cmd:String) = {
      // parse a,b
      assume(cmd.count(_ == ',') == 2)
      val vals = cmd.toLowerCase().split(",")
      println("parsed input - " + vals(0) + "," + vals(1) + "," + vals(2))
      val res = calcAgent ! Request(vals(0).toInt, vals(1).toInt, toOp(vals))
  }
}

object MyApp {
  def main(args:Array[String]) = {
    val sys = ActorSystem("CalcSys")
    val calcAgent = sys.actorOf(Props[CalcWorker], "CalcAgent")
    val calcReq = sys.actorOf(Props(new CalcRequester(calcAgent)), "CalcReq")
    calcReq ! ExecStart("3,8,plus")
    Thread.sleep(3000)
    calcReq ! ExecEnd
    calcAgent ! ExecEnd
    val f = sys.terminate()
  }
}


0 件のコメント: