Akka:如何确保收到邮件?

时间:2015-06-18 13:28:11

标签: multithreading scala akka actor

我有一个演员分配器。它的作用是什么

  1. 按要求分发一些物品
  2. 听取新来的
  3. 代码如下

    class Dispenser extends Actor {
        override def receive: Receive = {
            case Get =>
                context.sender ! getObj()
            case x: SomeType =>
                addObj(x)
        }
    }
    

    在实际处理过程中,自从发送新对象到分配器开始分配它之前是否经过1毫秒甚至几秒都没有关系,因此没有代码跟踪它。

    但现在我正在为分配器编写测试,我想确保首先接收到新对象,然后才会收到Get请求。

    这是我提出的测试代码:

    val dispenser = system.actorOf(Props.create(classOf[Dispenser]))
    dispenser ! obj
    Thread.sleep(100)
    val task = dispenser ? Get()
    val result = Await.result(task, timeout)
    check(result)
    

    它满足一个重要要求 - 不会更改原始代码。但它是

    1. 即使在非常高性能的盒子上也至少要慢100ms秒
    2. 不稳定并且有时失败,因为100毫秒或任何其他常数不提供任何保证。
    3. 问题是如何进行满足要求的测试,并且没有优点(没有任何其他明显的缺点)

2 个答案:

答案 0 :(得分:0)

您可以取出Thread.sleep(..),您的测试就可以了。 Akka保证您需要的订购。

使用代码

dispenser ! obj
val task = dispenser ? Get()

dispenser会在obj确定之前处理Get,因为

  1. 同一个帖子将obj然后Get放入演员的邮箱中,以便他们按照演员邮箱中的正确顺序排列
  2. 演员按顺序和一次一个地处理消息,因此演员将接收这两封消息,并按照他们在邮箱中排队的顺序进行处理。
  3. (..如果没有其他事情发生在您的示例代码中 - 路由器,getObj或addObj中的异步处理,存储,......)

答案 1 :(得分:0)

Akka FSM模块非常便于测试actor的基本状态和行为,并且不需要专门为测试更改其实现。 通过使用TestFSMRef,可以通过以下方式获取actor的当前状态和数据:

val testActor = TestFSMRef(<actors constructor or Props>)
testActor.stateName shouldBe <state name>
testActor.stateData shouldBe <state data>

http://doc.akka.io/docs/akka/2.4.1/scala/fsm.html