Scala,Akka:特征问题中对象的模式匹配

时间:2017-06-15 22:49:31

标签: scala akka

美好的一天。我正在制作一个简单的程序来检查某些服务器状态并面临模式匹配的问题。 这是代码: 切入点:

object Run extends App with StateActor.Api{
  private implicit val system = ActorSystem()
  implicit val blockingDispatcher: MessageDispatcher = system.dispatchers.lookup("blocking-dispatcher")
  protected val log: LoggingAdapter = Logging(system, getClass)
  protected implicit val materializer: ActorMaterializer = ActorMaterializer()

  import scala.concurrent.duration._
  implicit val timeout = Timeout(17 seconds)

  val listener = system.actorOf(StateActor.props)
  system.scheduler.schedule(
    0 milliseconds,
    5 minutes,
    listener,
    Ping
  )
}

演员:

class StateActor(implicit val blockingDispatcher: MessageDispatcher) extends Actor with StateActor.Api with ActorLogging {

  import akka.pattern.pipe
  private val formatter = JSONFormat.defaultFormatter
  private val mHookUrl = ...

  var mState: State = UNDEFINED
  override def receive: Receive = {
    case Ping =>
      log.debug("Ping")
      Future(Http("http://...").timeout(15000, 15000).asString)
        .map {
          case HttpResponse(_, 200, _) => UpResponse
          case HttpResponse(body, code, _) => DownResponse(s"Code: $code, body:\n $body")
          case rest => DownResponse(s"Undefined object: ${rest.toString}")
        } recover { case e => DownResponse(e.getMessage) } pipeTo self

    case UpResponse =>
      if (mState == DOWN || mState == UNDEFINED) {
        mState == UP
        reportToSlack("Client Up")
      }

    case DownResponse(reason) =>
      if (mState == UP || mState == UNDEFINED) {
        mState == DOWN
        reportToSlack(s"Client DOWN!\n Reason: $reason")
      }
    case other =>
      println(other)
      println(other.getClass)
  }

  def reportToSlack(message: String): Unit = {
    ...
  }
}

object StateActor {
  trait Api {
    case object Ping

    sealed trait State
    case object UP extends State
    case object DOWN extends State
    case object UNDEFINED extends State

    sealed trait StateMessage
    case object UpResponse extends StateMessage
    case class DownResponse(reason: String) extends StateMessage
  }

  def props(implicit blockingDispatcher: MessageDispatcher) = Props(new StateActor())
}

正如您所看到的,我将所有消息和其他内容放在“StateActor”伴随对象中的特征“API”中。但是当调度程序向actor发送“Ping”时,它匹配'case other',而不是'case Ping'。只需将“案例对象Ping”从特征和伴随对象中移出并使其成为“独立”对象即可解决问题。像这样:

case object Ping
object StateActor {
      trait Api {
        ...
    }
    ...
}

但是为什么它在内在特质时不起作用?特征模式中的所有其他案例类和对象都匹配得很好。

1 个答案:

答案 0 :(得分:2)

RunStateActor都会分别扩展特征,因此每个特征都有自己的Ping对象,并且它们不应该匹配。其他消息匹配的唯一原因是因为StateActor正在将它们发送给自己!它甚至不能用于两个不同的StateActor个实例。

而不是

  

移动'案例对象Ping'从特质和伴侣对象出来

您应该Api object并通过导入消息来访问消息:import StateActor.Api._而不是extends StateActor.Api(或直接将其放入object StateActor