com.twitter.util.Duration Scala Examples

The following examples show how to use com.twitter.util.Duration. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: Settings.scala    From diffy   with GNU Affero General Public License v3.0 5 votes vote down vote up
package ai.diffy.proxy

import java.net.InetSocketAddress

import ai.diffy.util.ResourceMatcher
import ai.diffy.util.ServiceInstance
import com.twitter.util.{Duration, StorageUnit, Try}

case class Settings(
    datacenter: String,
    servicePort:InetSocketAddress,
    candidate: String,
    primary: String,
    secondary: String,
    protocol: String,
    clientId: String,
    pathToThriftJar: String,
    serviceClass: String,
    serviceName: String,
    apiRoot: String,
    enableThriftMux: Boolean,
    relativeThreshold: Double,
    absoluteThreshold: Double,
    teamEmail: String,
    emailDelay: Duration,
    rootUrl: String,
    allowHttpSideEffects: Boolean,
    excludeHttpHeadersComparison: Boolean,
    skipEmailsWhenNoErrors: Boolean,
    httpsPort: String,
    useFramedThriftTransport: Boolean,
    hostname: String = Try(java.lang.management.ManagementFactory.getRuntimeMXBean.getName.split("@")(1)).getOrElse("unknown"),
    user: String = Try(sys.env("USER")).getOrElse("unknown"),
    resourceMatcher: Option[ResourceMatcher] = None,
    responseMode: ServiceInstance = ServiceInstance.Primary,
    maxResponseSize: StorageUnit,
    maxHeaderSize: StorageUnit) 
Example 2
Source File: Server.scala    From typed-schema   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.tschema.example

import cats.effect.ExitCode
import cats.effect.concurrent.Ref
import cats.instances.list._
import cats.syntax.foldable._
import cats.syntax.semigroupk._
import com.twitter.finagle
import com.twitter.finagle.http.Response
import com.twitter.util.{Await, Duration}
import monix.eval.{Task, TaskApp}
import ru.tinkoff.tschema.example.sample.SampleModule
import ru.tinkoff.tschema.finagle.RunHttp
import tofu.Void

object Server extends TaskApp {
  def modules[H[_]]: List[ExampleModule[Http]] =
    List(
      new Greeting[Http, Example](),
      new SampleModule[Http, Example](),
      new FiltersModule(),
      new FormFieldsModule(),
      new MultiParameters(),
      new ProxyModule(),
      new VersionModule(),
      new Authorize
    )

  val svc: Http[Response] = modules.foldMapK(_.route) <+> ExampleSwagger.route

  val server = for {
    srv <- RunHttp.run[Example](svc)
    list <- Example.delay(finagle.Http.serve("0.0.0.0:9191", srv))
    _ <- Example.delay(println(s"started at ${list.boundAddress}"))
    _ <- Example.delay(Await.ready(list, Duration.Top)).fork
    res <- Example.fromTask(Task.never[Void])
  } yield res

  def run(args: List[String]): Task[ExitCode] =
    for {
      ref <- Ref[Task].of(0)
      _ <- server
        .onErrorHandle(ex => println(ex.getMessage))
        .run(ExampleEnv("lol", ref))
    } yield ExitCode.Success
} 
Example 3
Source File: Server.scala    From typed-schema   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.tschema.example

import Swagger._
import cats.effect.ExitCode
import cats.effect.concurrent.Ref
import cats.instances.list._
import cats.syntax.foldable._
import cats.syntax.semigroupk._
import com.twitter.finagle
import finagle.{Http, http}
import com.twitter.finagle.http.Response
import com.twitter.util.{Await, Duration}
import monix.eval.{Task, TaskApp}
import ru.tinkoff.tschema.finagle.Runnable
import tofu.Void

object Server extends TaskApp {
  implicit val greeting: Greeting[Example] = Greeting[Example]

  val modules: List[ExampleModule] =
    List(GreetingModule[Example, Http](),
         TestModule,
         FiltersModule,
         FormFieldsModule,
         MultiParameters,
         ProxyModule,
         VersionModule,
         Authorize)

  val svc: Http[Response] = modules.foldMapK(_.route) <+> Swagger.route

  val server = for {
    srv  <- Runnable.run[Example](svc)
    list <- Example.delay(finagle.Http.serve("0.0.0.0:9191", srv))
    _    <- Example.delay(println(s"started at ${list.boundAddress}"))
    _    <- Example.delay(Await.ready(list, Duration.Top)).fork
    res  <- Example.fromTask(Task.never[Void])
  } yield res

  def run(args: List[String]): Task[ExitCode] =
    for {
      ref <- Ref[Task].of(0)
      _ <- server
            .onErrorHandle(ex => println(ex.getMessage))
            .run(ExampleEnv("lol", ref))
    } yield ExitCode.Success
} 
Example 4
Source File: Server.scala    From typed-schema   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.tschema.example

import ExampleSwagger._
import cats.instances.list._
import cats.syntax.foldable._
import cats.syntax.semigroupk._
import com.twitter.finagle.{Http => FHttp}
import com.twitter.finagle.http.Response
import com.twitter.util.{Await, Duration}
import ru.tinkoff.tschema.finagle.RunHttp
import zio.blocking.Blocking
import zio.console._
import zio.{blocking => _, _}

object Server extends App {
  val modules: List[ExampleModule] =
    List(
      Greeting,
      TestModule,
      FiltersModule,
      FormFieldsModule,
      MultiParameters,
      ProxyModule,
      VersionModule,
      Authorize,
      ReceiveModule
    )

  val svc: Http[Response] = modules.foldMapK(_.route) <+> ExampleSwagger.route

  val server = for {
    srv <- RunHttp.run[Example](svc)
    list <- ZIO.effect(FHttp.serve("0.0.0.0:9191", srv))
    _ <- putStr(s"started at ${list.boundAddress}")
    _ <- ZIO.effect(Await.ready(list, Duration.Top)).fork
    res <- ZIO.never
  } yield res

  val layer: URLayer[Blocking with Console, FullEnv] =
    ZLayer.identity[Blocking with Console] ++ ExampleEnv.live

  def run(args: List[String]): URIO[Blocking with Console, Int] =
    layer.build.use(r => server.catchAll(ex => putStr(ex.getMessage)).provide(r)) as 0
} 
Example 5
Source File: HttpFeatureTest.scala    From diffy   with GNU Affero General Public License v3.0 5 votes vote down vote up
package ai.diffy

import java.net.ServerSocket

import ai.diffy.examples.http.ExampleServers
import ai.diffy.proxy.DifferenceProxy
import com.google.common.collect.ImmutableMap
import com.google.inject.Stage
import com.twitter.finagle.Http
import com.twitter.finagle.http.Status
import com.twitter.finagle.util.DefaultTimer
import com.twitter.finatra.http.EmbeddedHttpServer
import com.twitter.inject.Test
import com.twitter.util.{Await, Duration, Future, FuturePool}

class HttpFeatureTest extends Test {
  def getPort(): Int = {
    val s  = new ServerSocket(0)
    val port = s.getLocalPort
    s.close()
    port
  }

  val env@Seq(p,s,c,d) = Seq.fill(4)(getPort())
  val environment = FuturePool.unboundedPool(ExampleServers.main(env.take(3).map(_.toString).toArray))

  val diffy = new MainService
  lazy val differenceProxy = diffy.injector.instance[DifferenceProxy]

  val server = new EmbeddedHttpServer(
    twitterServer = diffy,
    flags = Map(
      "proxy.port" -> s":$d",
      "candidate" -> s"localhost:$c",
      "master.primary" -> s"localhost:$p",
      "master.secondary" -> s"localhost:$s",
      "serviceName" -> "myHttpService",
      "service.protocol" -> "http",
      "summary.email" ->"test"
    ),
    stage = Stage.PRODUCTION
  )

  test("verify startup") {
    server.assertHealthy()
  }

  test("verify DifferenceCollector") {
    assert(differenceProxy.collector.fields.isEmpty)
    Await.result(Http.fetchUrl(s"http://localhost:$d/json?Twitter").liftToTry)
    var tries = 0
    while(differenceProxy.outstandingRequests.get() > 0 && tries < 10) {
      Await.result(Future.sleep(Duration.fromSeconds(1))(DefaultTimer.twitter))
      tries = tries + 1
    }
    assert(!differenceProxy.collector.fields.isEmpty)
  }

  test("verify present differences via API") {
    val response =
      Await.result(Http.fetchUrl(s"http://${server.externalHttpHostAndPort}/api/1/endpoints/undefined_endpoint/stats"))
    assertResult(Status.Ok)(response.status)
    assert(response.getContentString().contains(""""differences":1"""))
  }

  test("verify absent endpoint in API") {
    val response =
      Await.result(Http.fetchUrl(s"http://${server.externalHttpHostAndPort}/api/1/endpoints/json/stats"))
    assertResult(Status.Ok)(response.status)
    assertResult("""{"error":"key not found: json"}""")(response.getContentString())
  }
  Seq(
    "/api/1/overview",
    "/api/1/report",
    "/api/1/endpoints",
    "/api/1/endpoints/json/stats",
    "/api/1/endpoints/json/fields/result.200.values.value.name.PrimitiveDifference/results",
    "/api/1/endpoints/json/fields/result.200.values.value.name.PrimitiveDifference/results/0"
  ) foreach { endpoint =>
    test(s"ping ${endpoint}") {
      val response =
        Await.result(Http.fetchUrl(s"http://${server.externalHttpHostAndPort}${endpoint}"))
      assertResult(Status.Ok)(response.status)
    }
  }
} 
Example 6
Source File: DifferenceStatsMonitorSpec.scala    From diffy   with GNU Affero General Public License v3.0 5 votes vote down vote up
package ai.diffy.workflow

import ai.diffy.ParentSpec
import ai.diffy.analysis.{DifferenceCounter, EndpointMetadata, RawDifferenceCounter}
import com.twitter.finagle.stats.InMemoryStatsReceiver
import com.twitter.util.{Duration, Future, MockTimer, Time}
import org.junit.runner.RunWith
import org.mockito.Mockito._
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
class DifferenceStatsMonitorSpec extends ParentSpec {
  describe("DifferenceStatsMonitor"){
    val diffCounter = mock[DifferenceCounter]
    val metadata =
      new EndpointMetadata {
        override val differences = 0
        override val total = 0
      }

    val endpoints = Map("endpointName" -> metadata)
    when(diffCounter.endpoints) thenReturn Future.value(endpoints)

    val stats = new InMemoryStatsReceiver
    val timer = new MockTimer
    val monitor = new DifferenceStatsMonitor(RawDifferenceCounter(diffCounter), stats, timer)

    it("must add gauges after waiting a minute"){
      Time.withCurrentTimeFrozen { tc =>
        monitor.schedule()
        timer.tasks.size must be(1)
        stats.gauges.size must be(0)
        tc.advance(Duration.fromMinutes(1))
        timer.tick()
        timer.tasks.size must be(1)
        stats.gauges.size must be(2)
        stats.gauges.keySet map { _.takeRight(2) } must be(Set(Seq("endpointName", "total"), Seq("endpointName", "differences")))
      }
    }
  }
} 
Example 7
Source File: TestHelper.scala    From diffy   with GNU Affero General Public License v3.0 5 votes vote down vote up
package ai.diffy

import java.net.InetSocketAddress

import ai.diffy.analysis._
import ai.diffy.compare.Difference
import ai.diffy.proxy._
import ai.diffy.util.ServiceInstance
import com.twitter.util.{Duration, StorageUnit}
import org.scalatest.mock.MockitoSugar

object TestHelper extends MockitoSugar {
  lazy val testSettings = Settings(
    datacenter = "test",
    servicePort = new InetSocketAddress(9999),
    candidate = "candidate",
    primary = "primary",
    secondary = "secondary",
    protocol = "test",
    clientId = "test",
    pathToThriftJar = "test",
    serviceClass = "test",
    serviceName = "test",
    apiRoot = "test",
    enableThriftMux = false,
    relativeThreshold = 0.0,
    absoluteThreshold = 0.0,
    teamEmail = "test",
    emailDelay = Duration.fromSeconds(0),
    rootUrl = "test",
    allowHttpSideEffects = true,
    excludeHttpHeadersComparison = true,
    skipEmailsWhenNoErrors = false,
    httpsPort = "443",
    useFramedThriftTransport = false,
    responseMode = ServiceInstance.Primary,
    maxHeaderSize = StorageUnit.fromKilobytes(32),
    maxResponseSize = StorageUnit.fromMegabytes(5)
  )

  def makeEmptyJoinedDifferences = {
    val rawCounter = RawDifferenceCounter(new InMemoryDifferenceCounter())
    val noiseCounter = NoiseDifferenceCounter(new InMemoryDifferenceCounter())
    JoinedDifferences(rawCounter, noiseCounter)
  }

  def makePopulatedJoinedDifferences(endpoint : String, diffs : Map[String, Difference]) = {
    val rawCounter = RawDifferenceCounter(new InMemoryDifferenceCounter())
    val noiseCounter = NoiseDifferenceCounter(new InMemoryDifferenceCounter())
    val data = new InMemoryEndpointMetadata()
    data.add(diffs)
    rawCounter.counter.asInstanceOf[InMemoryDifferenceCounter].endpointsMap += (endpoint -> data)

    JoinedDifferences(rawCounter, noiseCounter)
  }
} 
Example 8
Source File: ThriftFeatureTest.scala    From diffy   with GNU Affero General Public License v3.0 5 votes vote down vote up
package ai.diffy

import java.io.{File, FileOutputStream}
import java.net.ServerSocket
import java.nio.file.Files
import java.util.zip.{ZipEntry, ZipOutputStream}

import ai.diffy.examples.thrift.ExampleServers
import ai.diffy.proxy.DifferenceProxy
import ai.diffy.thriftscala.Adder
import com.google.inject.Stage
import com.twitter.finagle.http.Status
import com.twitter.finagle.util.DefaultTimer
import com.twitter.finagle.{Http, ThriftMux}
import com.twitter.finatra.http.EmbeddedHttpServer
import com.twitter.inject.Test
import com.twitter.util.{Await, Duration, Future, FuturePool}

import scala.io.Source

class ThriftFeatureTest extends Test {

  def getPort(): Int = {
    val s  = new ServerSocket(0)
    val port = s.getLocalPort
    s.close()
    port
  }

  val env@Seq(p,s,c,d) = Seq.fill(4)(getPort())
  val environment = FuturePool.unboundedPool(ExampleServers.main(env.take(3).map(_.toString).toArray))

  val diffy = new MainService
  lazy val differenceProxy = diffy.injector.instance[DifferenceProxy]


  val thriftFile = new File("src/test/thrift/example.thrift")
  val data = Source.fromInputStream(Files.newInputStream(thriftFile.toPath), "UTF-8").mkString
  val thriftJar = Files.createTempFile("thrift", "jar")
  thriftJar.toFile.deleteOnExit()
  val out = new ZipOutputStream(new FileOutputStream(thriftJar.toFile))
  out.putNextEntry(new ZipEntry(thriftFile.getAbsolutePath))
  out.write(data.getBytes)
  out.closeEntry()
  out.close()

  val server = new EmbeddedHttpServer(
    twitterServer = diffy,
    flags = Map(
      "proxy.port" -> s":$d",
      "candidate" -> s"localhost:$c",
      "master.primary" -> s"localhost:$p",
      "master.secondary" -> s"localhost:$s",
      "serviceName" -> "myThriftService",
      "service.protocol" -> "thrift",
      "thrift.jar" -> thriftJar.toAbsolutePath.toString,
      "thrift.serviceClass" -> "Adder",
      "summary.email" -> "test"
    ),
    stage = Stage.PRODUCTION
  )

  val client = ThriftMux.client.build[Adder.MethodPerEndpoint](s"localhost:$d")

  test("verify startup") {
    server.assertHealthy()
  }

  test("verify DifferenceCollector") {
    assert(differenceProxy.collector.fields.isEmpty)
    Await.result(client.add(1, 1).liftToTry)
    var tries = 0
    while(differenceProxy.outstandingRequests.get() > 0 && tries < 10) {
      Await.result(Future.sleep(Duration.fromSeconds(1))(DefaultTimer))
      tries = tries + 1
    }
    assert(!differenceProxy.collector.fields.isEmpty)
  }

  test("verify present differences via API") {
    val response =
      Await.result(Http.fetchUrl(s"http://${server.externalHttpHostAndPort}/api/1/endpoints/add/stats"))
    assertResult(Status.Ok)(response.status)
    assert(response.getContentString().contains(""""differences":1"""))
  }

  test("verify absent endpoint in API") {
    val response =
      Await.result(Http.fetchUrl(s"http://${server.externalHttpHostAndPort}/api/1/endpoints/subtract/stats"))
    assertResult(Status.Ok)(response.status)
    assertResult("""{"error":"key not found: subtract"}""")(response.getContentString())
  }

} 
Example 9
Source File: Workflow.scala    From diffy   with GNU Affero General Public License v3.0 5 votes vote down vote up
package ai.diffy.workflow

import ai.diffy.analysis.{EndpointMetadata, RawDifferenceCounter}
import ai.diffy.util.EmailSender
import com.twitter.finagle.stats.StatsReceiver
import com.twitter.finagle.util.DefaultTimer
import com.twitter.logging.Logger
import com.twitter.util.{Duration, Memoize, Time, Timer}
import javax.inject.Inject

trait Workflow {
  val log: Logger = Logger(classOf[Workflow])
  val emailSender = new EmailSender(log)
  val delay: Duration

  val timer: Timer
  def run(start: Time): Unit

  def schedule(): Unit = {
    val start = Time.now
    log.info(s"Scheduling ${getClass.getName} at $start")

    timer.doLater(delay) {
      run(start)
    }
  }
}

class DifferenceStatsMonitor @Inject()(
     diffCounter: RawDifferenceCounter,
     stats: StatsReceiver,
     override val timer: Timer = DefaultTimer.twitter)
  extends Workflow
{
  val delay = Duration.fromMinutes(1)
  val scope = stats.scope("raw").scope("endpoints")
  private[this] val addGauges = Memoize[(String, EndpointMetadata), Unit] { case (endpoint, meta) =>
    scope.scope(endpoint).provideGauge("total"){ meta.total }
    scope.scope(endpoint).provideGauge("differences"){ meta.differences }
  }

  override def run(start: Time) = {
    diffCounter.counter.endpoints foreach { endPoints =>
      endPoints map { addGauges }
    }
  }

  override def schedule() = {
    val start = Time.now
    timer.schedule(delay) { run(start) }
  }
} 
Example 10
Source File: ConstFuture.scala    From arrows   with Apache License 2.0 5 votes vote down vote up
package arrows.twitter

import com.twitter.util.Future
import com.twitter.util.Try
import com.twitter.util.Awaitable
import com.twitter.util.Duration
import com.twitter.util.Return
import scala.runtime.NonLocalReturnControl
import com.twitter.concurrent.Scheduler
import com.twitter.util.FutureNonLocalReturnControl
import com.twitter.util.Local
import com.twitter.util.Monitor
import scala.util.control.NonFatal
import com.twitter.util.Promise
import com.twitter.util.Throw

trait ConstFuture[T] extends Future[T] {
  final def isReady(implicit permit: Awaitable.CanAwait): Boolean = true

  override final def ready(timeout: Duration)(implicit permit: Awaitable.CanAwait) = this
  final def poll: Option[com.twitter.util.Try[T]] = Some(toTry)

  protected def toTry: Try[T]

  final def respond(k: Try[T] => Unit): Future[T] = {
    val saved = Local.save()
    Scheduler.submit(new Runnable {
      def run(): Unit = {
        val current = Local.save()
        Local.restore(saved)
        try k(toTry)
        catch Monitor.catcher
        finally Local.restore(current)
      }
    })
    this
  }

  final def raise(interrupt: Throwable): Unit = ()

  final def transform[B](f: Try[T] => Future[B]): Future[B] = {
    val p = new Promise[B]
    // see the note on `respond` for an explanation of why `Scheduler` is used.
    val saved = Local.save()
    Scheduler.submit(new Runnable {
      def run(): Unit = {
        val current = Local.save()
        Local.restore(saved)
        val computed = try f(toTry)
        catch {
          case e: NonLocalReturnControl[_] => Future.exception(new FutureNonLocalReturnControl(e))
          case NonFatal(e)                 => Future.exception(e)
          case t: Throwable =>
            Monitor.handle(t)
            throw t
        } finally Local.restore(current)
        p.become(computed)
      }
    })
    p
  }
}

class ReturnFuture[T](r: T) extends ConstFuture[T] {
  override final def result(timeout: Duration)(implicit permit: Awaitable.CanAwait): T = r
  override final def toTry = Return(r)
}

class ThrowFuture[T](ex: Throwable) extends ConstFuture[T] {
  override final def result(timeout: Duration)(implicit permit: Awaitable.CanAwait): T = throw ex
  override final def toTry = Throw(ex)
} 
Example 11
Source File: TimeoutError.scala    From cosmos   with Apache License 2.0 5 votes vote down vote up
package com.mesosphere.cosmos.error


import com.twitter.util.Duration
import io.circe.Encoder
import io.circe.JsonObject
import io.circe.generic.semiauto.deriveEncoder
import com.mesosphere.cosmos.circe.Encoders._

final case class TimeoutError(
  operation: String,
  destination: String,
  timeout: Duration
) extends CosmosError {
  override def data: Option[JsonObject] = CosmosError.deriveData(this)
  override def message: String = s"$operation timed out on $destination" +
    s" after ${timeout.inSeconds} seconds"
}

object TimeoutError {
  implicit val encoder: Encoder[TimeoutError] = deriveEncoder
} 
Example 12
Source File: RpcChannelImpl.scala    From finagle-protobuf   with Apache License 2.0 5 votes vote down vote up
package com.twitter.finagle.protobuf.rpc.impl

import java.net.InetSocketAddress
import com.google.protobuf.Descriptors.MethodDescriptor
import com.google.protobuf.RpcCallback
import com.google.protobuf.Message
import com.google.protobuf.RpcChannel
import com.google.protobuf.RpcController
import com.google.protobuf.Service
import java.util.logging.Logger
import com.twitter.util.Duration
import com.twitter.util.FuturePool
import com.twitter.finagle.builder.ClientBuilder
import java.util.concurrent.ExecutorService
import com.twitter.finagle.protobuf.rpc.RpcControllerWithOnFailureCallback
import com.twitter.finagle.protobuf.rpc.channel.ProtoBufCodec
import com.twitter.finagle.ChannelClosedException
import com.twitter.finagle.protobuf.rpc.Util
import com.twitter.finagle.protobuf.rpc.ExceptionResponseHandler

class RpcChannelImpl(cb: ClientBuilder[(String, Message), (String, Message), Any, Any, Any], s: Service, handler: ExceptionResponseHandler[Message], executorService: ExecutorService) extends RpcChannel {

  private val log = Logger.getLogger(getClass.toString)

  private val futurePool = FuturePool(executorService)

  private val client: com.twitter.finagle.Service[(String, Message), (String, Message)] = cb
    .codec(new ProtoBufCodec(s))
    .unsafeBuild()

  def callMethod(m: MethodDescriptor, controller: RpcController,
                 request: Message, responsePrototype: Message,
                 done: RpcCallback[Message]): Unit = {
    // retries is a workaround for ChannelClosedException raised when servers shut down.
    val retries = 3

    callMethod(m, controller, request, responsePrototype, done, retries)
  }

  def callMethod(m: MethodDescriptor, controller: RpcController,
                 request: Message, responsePrototype: Message,
                 done: RpcCallback[Message], retries: Int): Unit = {

    Util.log("Request", m.getName(), request)
    val req = (m.getName(), request)

    client(req) onSuccess {
      result =>
        Util.log("Response", m.getName(), result._2)
        futurePool({
          handle(done, controller, result._2)
        })
    } onFailure {
      e =>
        log.warning("#callMethod# Failed. "+ e.getMessage)
        e match {
          case cc: ChannelClosedException => if (retries > 1) {
            log.warning("#callMethod# Retrying.")
            callMethod(m, controller, request, responsePrototype, done, retries - 1);
          } else {
            controller.asInstanceOf[RpcControllerWithOnFailureCallback].setFailed(e)
          }
          case _ => controller.asInstanceOf[RpcControllerWithOnFailureCallback].setFailed(e)
        }
    }
  }

  def handle(done: RpcCallback[Message], controller: RpcController, m: Message) {
    if (handler.canHandle(m)) {
      controller.asInstanceOf[RpcControllerWithOnFailureCallback].setFailed(handler.handle(m))
    } else {
      done.run(m)
    }
  }

  def release() {
     client.close()
  }
} 
Example 13
Source File: RpcFactoryImpl.scala    From finagle-protobuf   with Apache License 2.0 5 votes vote down vote up
package com.twitter.finagle.protobuf.rpc.impl

import com.twitter.finagle.protobuf.rpc.RpcFactory
import com.twitter.finagle.protobuf.rpc.RpcControllerWithOnFailureCallback
import com.twitter.finagle.protobuf.rpc.RpcServer
import com.twitter.finagle.builder.ServerBuilder
import com.twitter.finagle.builder.ClientBuilder
import com.twitter.util.Duration
import com.google.protobuf.RpcController
import com.google.protobuf.RpcChannel
import com.google.protobuf.Message
import com.google.protobuf.Service
import java.util.concurrent.ExecutorService
import com.twitter.finagle.protobuf.rpc.ServiceExceptionHandler
import com.twitter.finagle.protobuf.rpc.ExceptionResponseHandler

class RpcFactoryImpl extends RpcFactory {

  def createServer(sb: ServerBuilder[(String, Message), (String, Message), Any, Any, Any], port: Int, service: Service, handler: ServiceExceptionHandler[Message], executorService: ExecutorService): RpcServer = new RpcServerImpl(sb, port, service, handler, executorService)

  def createStub[T <: Service](cb: ClientBuilder[(String, Message), (String, Message), Any, Any, Any], service: {def newStub(c: RpcChannel): T}, handler: ExceptionResponseHandler[Message], executorService: ExecutorService): T = {
    service.newStub(new RpcChannelImpl(cb, service.asInstanceOf[T], handler, executorService))
  }

  def createController(): RpcController = {
    new RpcControllerWithOnFailureCallback()
  }

  def release(stub: {def getChannel(): RpcChannel}) {
    stub.getChannel().asInstanceOf[RpcChannelImpl].release()
  }
} 
Example 14
Source File: RpcServerImpl.scala    From finagle-protobuf   with Apache License 2.0 5 votes vote down vote up
package com.twitter.finagle.protobuf.rpc.impl

import com.twitter.finagle.protobuf.rpc.channel.ProtoBufCodec
import com.twitter.finagle.protobuf.rpc.{RpcServer, Util}
import com.twitter.util._
import com.twitter.util.Duration
import com.twitter.util.FuturePool
import com.twitter.finagle.builder.{Server, ServerBuilder, ServerConfig}
import java.net.InetSocketAddress
import java.util.logging.Logger
import scala.None
import java.util.concurrent.Executors
import java.util.concurrent.ExecutorService
import com.google.common.base.Preconditions
import com.twitter.finagle.protobuf.rpc.ServiceExceptionHandler
import com.google.protobuf.DynamicMessage
import com.google.protobuf.DynamicMessage.Builder
import com.google.protobuf._
import com.google.protobuf.Descriptors._
import com.twitter.util.Promise

class RpcServerImpl(sb: ServerBuilder[(String, Message), (String, Message), Any, Any, Any], port: Int, service: Service, handler: ServiceExceptionHandler[Message], executorService: ExecutorService) extends RpcServer {

  private val log = Logger.getLogger(getClass.toString)

  Preconditions.checkNotNull(executorService)
  Preconditions.checkNotNull(handler)

  private val execFuturePool = new ExecutorServiceFuturePool(executorService)

  private val server: Server = ServerBuilder.safeBuild(ServiceDispatcher(service, handler, execFuturePool),
    sb
      .codec(new ProtoBufCodec(service))
      .name(getClass().getName())
      .bindTo(new InetSocketAddress(port)))

  def close(d: Duration) = {
    server.close(d)
  }
}

class ServiceDispatcher(service: com.google.protobuf.Service, handler: ServiceExceptionHandler[Message], futurePool: FuturePool) extends com.twitter.finagle.Service[(String, Message), (String, Message)] {

  private val log = Logger.getLogger(getClass.toString)

  def apply(request: (String, Message)) = {

    val methodName = request._1
    val reqMessage = request._2

    Util.log("Request", methodName, reqMessage)
    val m = service.getDescriptorForType().findMethodByName(methodName);
    if (m == null) {
      throw new java.lang.AssertionError("Should never happen, we already decoded " + methodName)
    }

    val promise = new Promise[(String, Message)]()

    // dispatch to the service method
    val task = () => {
      try {
        service.callMethod(m, null, reqMessage, new RpcCallback[Message]() {

          def run(msg: Message) = {
            Util.log("Response", methodName, msg)
            promise.setValue((methodName, msg))
          }

        })
      } catch {
        case e: RuntimeException => {
          log.warning("#apply# Exception: "+e.getMessage)
          if (handler.canHandle(e)) {
            promise.setValue((methodName, handler.handle(e, constructEmptyResponseMessage(m))))
          }
        }
      }
    }
    futurePool(task())
    promise
  }

  def constructEmptyResponseMessage(m: MethodDescriptor): Message = {
    val outputType = m.getOutputType();
    DynamicMessage.newBuilder(outputType).build()
  }
}

object ServiceDispatcher {
  def apply(service: com.google.protobuf.Service, handler: ServiceExceptionHandler[Message], futurePool: FuturePool): ServiceDispatcher = {
    new ServiceDispatcher(service, handler, futurePool)
  }
} 
Example 15
Source File: HttpLatencyMonitoringFilterSpec.scala    From finagle-prometheus   with MIT License 5 votes vote down vote up
package com.samstarling.prometheusfinagle.filter

import com.samstarling.prometheusfinagle.UnitTest
import com.samstarling.prometheusfinagle.helper.{CollectorHelper, CollectorRegistryHelper}
import com.samstarling.prometheusfinagle.metrics.Telemetry
import com.twitter.finagle.Service
import com.twitter.finagle.http.{Method, Request, Response, Status}
import com.twitter.finagle.util.DefaultTimer
import com.twitter.util.{Await, Duration, Future, Timer}
import io.prometheus.client.CollectorRegistry
import org.specs2.specification.Scope

class HttpLatencyMonitoringFilterSpec extends UnitTest {

  class SlowService extends Service[Request, Response] {
    implicit val timer = DefaultTimer.twitter

    override def apply(request: Request): Future[Response] = {
      Future
        .value(Response(request.version, Status.Ok))
        .delayed(Duration.fromMilliseconds(1500))
    }
  }

  trait Context extends Scope {
    val registry = new CollectorRegistry(true)
    val registryHelper = CollectorRegistryHelper(registry)
    val telemetry = new Telemetry(registry, "test")
    val buckets = Seq(1.0, 2.0)
    val labeller = new TestLabeller
    val filter = new HttpLatencyMonitoringFilter(telemetry, buckets, labeller)
    val service = mock[Service[Request, Response]]
    val slowService = new SlowService
    val request = Request(Method.Get, "/foo/bar")
    val serviceResponse = Response(Status.Created)
    val histogram =
      telemetry.histogram(name = "incoming_http_request_latency_seconds")
    service.apply(request) returns Future.value(serviceResponse)
  }

  "HttpLatencyMonitoringFilter" >> {
    "passes requests on to the next service" in new Context {
      Await.result(filter.apply(request, service))
      there was one(service).apply(request)
    }

    "returns the Response from the next service" in new Context {
      val actualResponse = Await.result(filter.apply(request, service))
      actualResponse ==== serviceResponse
    }

    "counts the request" in new Context {
      Await.result(filter.apply(request, slowService))

      registryHelper.samples
        .get("test_incoming_http_request_latency_seconds_count")
        .map(_.map(_.value).sum) must beSome(1.0).eventually
    }

    "increments the counter with the labels from the labeller" in new Context {
      Await.result(filter.apply(request, service))

      registryHelper.samples
        .get("test_incoming_http_request_latency_seconds_count")
        .map(_.head.dimensions.get("foo").get) must beSome("bar").eventually
    }

    "categorises requests into the correct bucket" in new Context {
      Await.result(filter.apply(request, slowService))

      // Our request takes ~1500ms, so it should NOT fall into the "less than or equal to 1 second" bucket (le=0.5)
      registryHelper.samples
        .get("test_incoming_http_request_latency_seconds_bucket")
        .flatMap(_.find(_.dimensions.get("le").contains("1.0")))
        .map(_.value) must beSome(0.0).eventually

      // However, it should fall into the "less than or equal to 2 seconds" bucket (le=0.5)
      registryHelper.samples
        .get("test_incoming_http_request_latency_seconds_bucket")
        .flatMap(_.find(_.dimensions.get("le").contains("2.0")))
        .map(_.value) must beSome(1.0).eventually

      // It should also fall into the "+Inf" bucket
      registryHelper.samples
        .get("test_incoming_http_request_latency_seconds_bucket")
        .flatMap(_.find(_.dimensions.get("le").contains("+Inf")))
        .map(_.value) must beSome(1.0).eventually
    }
  }
} 
Example 16
Source File: PrometheusStatsReceiverTest.scala    From finagle-prometheus   with MIT License 5 votes vote down vote up
package com.samstarling.prometheusfinagle

import com.twitter.app.LoadService
import com.twitter.finagle.stats.{StatsReceiver, Verbosity}
import com.twitter.finagle.util.DefaultTimer
import com.twitter.util.Duration
import io.prometheus.client.CollectorRegistry

class PrometheusStatsReceiverTest extends UnitTest {

  "PrometheusStatsReceiverTest" should {
    "have a zero-argument constructor" in {
      new PrometheusStatsReceiver() must not(throwA[RuntimeException])
    }

    // This depends on content in test/resources/META-INF/services
    "be loaded as a StatsReceiver by LoadService" in {
      val classes: Seq[Class[_]] = LoadService[StatsReceiver]().map(_.getClass)
      classes.contains(classOf[PrometheusStatsReceiver]) ==== true
    }

    "be able to be instantiated by newInstance" in {
      classOf[PrometheusStatsReceiver].newInstance() must not(
        throwA[NoSuchMethodException])
    }

    "allow a registry to be passed" in {
      val registry = CollectorRegistry.defaultRegistry
      new PrometheusStatsReceiver(registry) must not(throwA[RuntimeException])
    }

    "allow a registry, namespace, and a Timer to be passed" in {
      val registry = CollectorRegistry.defaultRegistry
      val namespace = "testnamespace"
      new PrometheusStatsReceiver(registry,
                                  namespace,
                                  DefaultTimer.twitter,
                                  Duration.fromSeconds(1)) must not(
        throwA[RuntimeException])
    }

    "allow metrics and labels with unsafe characters" in {
      val registry = CollectorRegistry.defaultRegistry
      val namespace = "test_metric_names_and_labels"
      val statsReceiver = new PrometheusStatsReceiver(registry,
                                                      namespace,
                                                      DefaultTimer.twitter,
                                                      Duration.fromSeconds(1))
      val metrics = Seq(
        Seq("finagle", "build/revision"),
        Seq("foo/bar", "baz"),
        Seq("foo/bar", "build/revision"),
        Seq("foo-bar", "baz"),
        Seq("finagle", "build-revsion"),
      )
      metrics foreach { name =>
        statsReceiver.stat(Verbosity.Default, name: _*)
      } must not(throwA[IllegalArgumentException])
    }
  }
} 
Example 17
Source File: Http_03_Client.scala    From airframe   with Apache License 2.0 5 votes vote down vote up
package wvlet.airframe.examples.http

import java.util.concurrent.TimeUnit

import com.twitter.finagle.Http
import com.twitter.finagle.http.Request
import com.twitter.util.Duration
import wvlet.airframe.http.finagle.{Finagle, FinagleSyncClient}
import wvlet.airframe.http.{Endpoint, HttpMethod, Router}
import wvlet.log.LogSupport


object Http_03_Client extends App with LogSupport {
  case class User(id: String, name: String)
  trait MyApp extends LogSupport {
    @Endpoint(method = HttpMethod.GET, path = "/user/:id")
    def getUser(id: String): User = {
      User(id, "xxx")
    }
  }

  val router = Router.add[MyApp]

  val serverDesign = Finagle.server
    .withName("myapp")
    .withRouter(router)
    .design

  val clietnDesign =
    Finagle.client
    // Max retry attempts
      .withMaxRetry(3)
      // Use backoff (or jittering)
      .withBackOff(1)
      // Set request timeout
      .withTimeout(Duration(90, TimeUnit.SECONDS))
      // Add Finagle specific configuration
      .withInitializer { client: Http.Client => client.withHttp2 } // optional
      // Create a new http client to access the server.
      .syncClientDesign

  val design = serverDesign + clietnDesign

  design.build[FinagleSyncClient] { client =>
    // FinagleServer will be started here
    // Read the JSON response as an object
    val user = client.get[User]("/user/1")
    debug(user)

    // Read the response as is
    val request = client.send(Request("/user/2"))
    val content = request.contentString
    debug(content)
  }
}