All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.gfxmonk.backpressure.monix.BackpressureMonix.scala Maven / Gradle / Ivy

The newest version!
package net.gfxmonk.backpressure.monix

import _root_.monix.eval.Task
import _root_.monix.execution.{Ack, Scheduler}
import _root_.monix.reactive.Observable.Operator
import _root_.monix.reactive.observers.Subscriber
import com.timgroup.statsd.StatsDClient
import net.gfxmonk.backpressure.internal.{Clock, Logic, StatsClient}
import net.gfxmonk.backpressure.internal.statsd.StatsdImpl

import java.util.concurrent.TimeUnit
import scala.concurrent.Future

object BackpressureSensor {
  def apply(statsDClient: StatsDClient, sampleRate: Double = 1.0, baseTags: Map[String, String] = Map.empty): BackpressureSensor = {
    new BackpressureSensor(statsDClient, sampleRate, baseTags)
  }

  private [backpressure] def operator[T](stats: StatsClient) : Operator[T,T] = {
    subscriber => {
      val clock: Clock = new Clock {
        override def microsMonotonic(): Long = subscriber.scheduler.clockMonotonic(TimeUnit.MICROSECONDS)
      }
      new SubscriberImpl(subscriber, new Logic(clock, stats))
    }
  }

  private class SubscriberImpl[T](underlying: Subscriber[T], logic: Logic) extends Subscriber[T] {
    override def onNext(elem: T): Future[Ack] = {
      val task = for {
        upstreamDuration <- Task(logic.onWaitComplete())
        response <- Task.fromFuture(underlying.onNext(elem))
        _ <- Task(logic.onBusyComplete(upstreamDuration))
      } yield response
      task.runToFuture(scheduler)
    }

    override def onError(ex: Throwable): Unit = underlying.onError(ex)

    override def onComplete(): Unit = underlying.onComplete()

    override implicit def scheduler: Scheduler = underlying.scheduler
  }
}

class BackpressureSensor private(statsClient: StatsDClient, sampleRate: Double, baseTags: Map[String, String]) {

  def operator[T](metricPrefix: String, tags: Map[String,String] = Map.empty) : Operator[T,T] = {
    val stats = new StatsdImpl(statsClient,
      metricPrefix = metricPrefix,
      tags = baseTags ++ tags,
      sampleRate = sampleRate
    )
    BackpressureSensor.operator(stats)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy