从未来

时间:2016-08-15 10:24:38

标签: scala akka actor

请考虑以下代码示例:

class MyActor (httpClient: HttpClient) {

  var canSendMore = true

  override def receive: Receive = {
    case PayloadA(name: String) => send(urlA) 
    case PayloadB(name: String) => send(urlB)

    def send(url: String){
       if (canSendMore) 
          httpClient.post(url).map(response => canSendMore = response.canSendMore)
       else { 
          Thread.sleep(5000) //this will be done in a more elegant way, it's just for the example.
          httpClient.post(url).map(response => canSendMore = response.canSendMore)
       }
    }
}

每个消息处理都将导致异步http请求。 (回复后的价值是未来[回应]) 我的问题是我想安全地更新计数器(目前存在竞争条件)

顺便说一下,我必须以某种方式在同一个线程中更新计数器,或至少在此actor处理任何其他消息之前。

这可能吗?

1 个答案:

答案 0 :(得分:4)

当http请求未来正在进行时,您可以使用“成为+存储”组合来继续存储消息。

object FreeToProcess

case PayloadA(name: String)

class MyActor (httpClient: HttpClient) extends Actor with Stash {

  def canProcessReceive: Receive = {
    case PayloadA(name: String) => {
      // become an actor which just stashes messages
      context.become(canNotProcessReceive, discardOld = false)

      httpClient.post(urlA).onComplete({
        case Success(x) => {
          // Use your result
          self ! FreeToProcess
        }
        case Failure(e) => {
          // Use your failure
          self ! FreeToProcess
        }
      })
    }
  }

  def canNotProcessReceive: Receive = {
    case CanProcess => {
      // replay stash to mailbox
      unstashAll()
      // start processing messages
      context.unbecome()
    }

    case msg => {
      stash()
    }
  }

}