首页 > 解决方案 > 如何使此定期指标收集代码更具功能性(不可变状态)?

问题描述

这是我的代码的大纲

有多个工人演员,我正在从他们httpActorLatencies那里收集一些延迟统计信息到地图中,其中每个工人演员的延迟被单独跟踪,然后登录接收LogQueueLatency消息。此时,里面的所有队列httpActorLatencies也都被清空了。

有没有办法以合理的方式摆脱可变 Map ?

class StatsActor(workerCount: Int) extends Actor {
  val httpActorLatencies = scala.collection.mutable.Map[Int, scala.collection.mutable.MutableList[Long]]()

  override def preStart(): Unit = {
    Range(0, workerCount).foreach(i => httpActorLatencies.put(i, scala.collection.mutable.MutableList()))
  }

  override def receive = {
    case shardLatency: QueuingLatency =>
      httpActorLatencies(shardLatency.shardNumber) += shardLatency.latency

    case LogQueueLatency =>
      outputCollectedStats()
  }

  private def outputCollectedStats(): Unit = {
    output(StatsActor.computePerShardMeanLatencies(httpActorLatencies))
    httpActorLatencies.foreach(x => x._2.clear())
  }
}

标签: scalafunctional-programmingakka

解决方案


一种方法是使用context.become一个带有它的接收函数Map,如下所示:

class StatsActor extends Actor {
  def newMap() = Map[Int, List[Long]]().withDefault(Nil)

  def receive: Receive = countingReceive(newMap())

  def countingReceive(httpActorLatencies: Map[Int, List[Long]]): Receive = {
    case shardLatency: QueuingLatency =>
      val newList = httpActorLatencies(shardLatency.shardNumber) :+ shardLatency.latency
      val newMap = httpActorLatencies.updated(shardLatency.shardNumber, newList)

      context.become(countingReceive(newMap))

    case LogQueueLatency =>
      outputCollectedStats(httpActorLatencies)

      context.become(receive)
  }


  private def outputCollectedStats(httpActorLatencies: Map[Int, List[Long]]): Unit = {
    ...
  }
}

这是未经测试的并且可能已损坏,但它应该给出如何完成的想法。

另请注意,我已使用withDefaultMap简化逻辑并消除对workerCount.


推荐阅读