繁体   English   中英

演员上的scala.MatchError

[英]scala.MatchError on actor

在测试过程中,我收到以下错误消息:

[ERROR] [07/13/2019 14:25:39.659] [DetectorSystem3-akka.io.pinned-dispatcher-2] [akka://DetectorSystem3/user/DetectorSupervisor] SapActiveConfirmed (of class com.sweetsoft.detector.ServerMonitoring$SapActiveConfirmed$)
scala.MatchError: SapActiveConfirmed (of class com.sweetsoft.detector.ServerMonitoring$SapActiveConfirmed$)
    at com.sweetsoft.detector.DetectorStateMachine$.$anonfun$create$2(DetectorStateMachine.scala:20)
    at akka.actor.typed.internal.BehaviorImpl$ReceiveMessageBehavior.receive(BehaviorImpl.scala:53)
    at akka.actor.typed.Behavior$.interpret(Behavior.scala:437)
    at akka.actor.typed.Behavior$.interpretMessage(Behavior.scala:393)
    at akka.actor.typed.internal.adapter.ActorAdapter.handleMessage(ActorAdapter.scala:121)
    at akka.actor.typed.internal.adapter.ActorAdapter.aroundReceive(ActorAdapter.scala:102)
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:612)
    at akka.actor.ActorCell.invoke(ActorCell.scala:581)
    at akka.testkit.CallingThreadDispatcher.process$1(CallingThreadDispatcher.scala:280)
    at akka.testkit.CallingThreadDispatcher.runQueue(CallingThreadDispatcher.scala:313)
    at akka.testkit.CallingThreadDispatcher.dispatch(CallingThreadDispatcher.scala:234)
    at akka.actor.dungeon.Dispatch.sendMessage(Dispatch.scala:158)
    at akka.actor.dungeon.Dispatch.sendMessage$(Dispatch.scala:152)
    at akka.actor.ActorCell.sendMessage(ActorCell.scala:447)

我使用的是akka型,我认为它不应该这样。

参与者的实现如下:

object DetectorStateMachine {

  case class State(kafka: ServerHealthEvent, sap: ServerHealthEvent)

  def create(informant: ActorRef[InformantEvent]): Behavior[ServerHealthEvent] =
    Behaviors.setup { context =>

      context.log.info(s"=============> Start DetectorStateMachine <=============")

      def loop(state: State): Behavior[ServerHealthEvent] = {

        Behaviors.receiveMessage {
          case KafkaActiveConfirmed
            if state.kafka == KafkaActiveConfirmed || state.sap == SapActiveConfirmed =>
            informant ! ServerOnlineConfirmed
            loop(state)
          case k@KafkaActiveConfirmed if state.kafka == KafkaInactiveConfirmed =>
            loop(State(k, state.sap))
          case k@KafkaInactiveConfirmed =>
            informant ! ServerOfflineConfirmed
            loop(State(k, state.sap))
          case SapActiveConfirmed
            if state.sap == SapActiveConfirmed && state.kafka == KafkaActiveConfirmed =>
            informant ! ServerOnlineConfirmed
            loop(state)
          case s@SapActiveConfirmed if state.sap == SapInactiveConfirmed =>
            loop(State(state.kafka, s))
          case s@SapInactiveConfirmed =>
            informant ! ServerOfflineConfirmed
            loop(State(state.kafka, s))
        }

      }

      loop(State(KafkaInactiveConfirmed, SapInactiveConfirmed))


    }

}

测试实现为:

final class DetectorSpec extends BddSpec {

  private val sap = new SapMock()
    .withExposedPorts(8080)
    .waitingFor(Wait.forHttp("/"))

  private val kafka = new KafkaContainer("5.2.1")

  sap.start()
  kafka.start()

  override def afterAll(): Unit = {
    sap.stop()
    kafka.stop()
  }

  private def withKafkaOfflineSapOnline(testCode: TestProbe[ServerEvent] => Unit)
  : Unit = {

    val config = ConfigFactory.parseString(
      s"""akka.actor.default-dispatcher = {
            type = akka.testkit.CallingThreadDispatcherConfigurator
          }
          akka.actor.testkit.typed.single-expect-default = 0s
          kafka {
            servers = "PLAINTEXT://localhost:9092"
          }
          sap {
            server = "ws://${sap.getContainerIpAddress}:${sap.getMappedPort(8080)}"
          }""")

    val testKit = ActorTestKit("DetectorSystem3", config)
    val inbox = testKit.createTestProbe[ServerEvent]("Receiver")
    testKit.spawn(DetectorSupervisor.create(), "DetectorSupervisor")
    testKit.system.receptionist ! Receptionist.Register(ServerStateKey, inbox.ref)

    testCode(inbox)
    testKit.shutdownTestKit()
  }

    scenario("SAP is online and Kafka is offline") {
      withKafkaOfflineSapOnline { inbox =>
        Given("I am waiting for the current state message")
        When("I am receive the state message")
        val msg = inbox.receiveMessage(60.second)
        Then("it should contain `Kafka is offline`")
        msg should be(ServerOfflineApproved)
      }
    }

  }
} 

我究竟做错了什么?

好吧,您有两个具有SapActiveConfirmed分支:

case SapActiveConfirmed
  if state.sap == SapActiveConfirmed && state.kafka == KafkaActiveConfirmed =>
  ...
case s@SapActiveConfirmed if state.sap == SapInactiveConfirmed =>
  ...

因此,如果两个条件都不成立(例如, stateState(KafkaInactiveConfirmed, SapActiveConfirmed) ),那么您将得到MatchError 而且,使用withKafkaOfflineSapOnline听起来确实可以产生这种状态...

如果您以其他方式构造匹配项,则可能会有所帮助:

Behaviors.receiveMessage {
  case KafkaActiveConfirmed =>
    ...
  case KafkaInactiveConfirmed =>
    ...
  ...
}

条件在分支机构内部。

如果您想避免匹配错误-最好添加带有错误打印输出的后备空白案例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM