如何使此定期指标收集代码更具功能性(可变状态更少)?

时间:2018-08-21 14:39:30

标签: scala functional-programming akka

这是我的代码的轮廓

有多个工作角色,我正在从中收集一些延迟统计信息到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())
  }
}

1 个答案:

答案 0 :(得分:4)

一种实现方法是使用(?i) # Case insensitive matching ( # Start of matching group < # matches the < character [^<] # matches anything that's *not* < *? # matches zero-unlimited times where # matches the substring where [^>] # matches anything that's *not* > *? # matches zero-unlimited times > # matches > ) # end of matching group 和带有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 = { ... } } 上使用了withDefault来简化逻辑并消除了对Map的需求。