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

com.twitter.finagle.client.DefaultClient.scala Maven / Gradle / Ivy

The newest version!
package com.twitter.finagle.client

import com.twitter.conversions.time._
import com.twitter.finagle._
import com.twitter.finagle.factory.TimeoutFactory
import com.twitter.finagle.filter.{ExceptionSourceFilter, MonitorFilter}
import com.twitter.finagle.loadbalancer.{LoadBalancerFactory, DefaultBalancerFactory, WeightedLoadBalancerFactory}
import com.twitter.finagle.service.{ExpiringService, FailureAccrualFactory, FailFastFactory, TimeoutFilter}
import com.twitter.finagle.stats.{ClientStatsReceiver, NullStatsReceiver, StatsReceiver}
import com.twitter.finagle.tracing._
import com.twitter.finagle.util.{DefaultMonitor, DefaultTimer, LoadedReporterFactory, ReporterFactory}
import com.twitter.util.{Duration, Monitor, Timer, Var}
import java.net.{SocketAddress, InetSocketAddress}

object DefaultClient {
  private val defaultFailureAccrual: ServiceFactoryWrapper =
    FailureAccrualFactory.wrapper(5, 5.seconds)(DefaultTimer.twitter)
}

/**
 * A default client implementation that does load balancing and
 * connection pooling. The only required argument is a binder,
 * responsible for binding concrete endpoints (named by
 * SocketAddresses).
 *
 * @param name A name identifying the client.
 *
 * @param endpointer A function used to create a ServiceFactory
 * to a concrete endpoint.
 *
 * @param pool The pool used to cache idle service (connection).
 *
 * @param maxIdletime The maximum time for which any `Service` is
 * permitted to be idle.
 *
 * @param maxLifetime The maximum lifetime for any `Service`
 *
 * @param requestTimeout The maximum time that any request is allowed
 * to take.
 *
 * @param failFast When enabled, installs a fail-fast module. See
 * [[com.twitter.finagle.service.FailFastFactory]]
 *
 * @param failureAccrual A failure accruing mechanism. Used to
 * gauge the health of the ServiceFactory. By default this uses
 * [[com.twitter.finagle.client.DefaultClient.defaultFailureAccrual]]
 *
 * @param serviceTimeout The maximum amount of time allowed for
 * acquiring a service. Defaults to infinity.
 */
case class DefaultClient[Req, Rep](
  name: String,
  endpointer: (SocketAddress, StatsReceiver) => ServiceFactory[Req, Rep],
  pool: StatsReceiver => Transformer[Req, Rep] = DefaultPool[Req, Rep](),
  maxIdletime: Duration = Duration.Top,
  maxLifetime: Duration = Duration.Top,
  requestTimeout: Duration = Duration.Top,
  failFast: Boolean = true,
  failureAccrual: Transformer[Req, Rep] = { factory: ServiceFactory[Req, Rep] =>
    DefaultClient.defaultFailureAccrual andThen factory
  },
  serviceTimeout: Duration = Duration.Top,
  timer: Timer = DefaultTimer.twitter,
  statsReceiver: StatsReceiver = ClientStatsReceiver,
  hostStatsReceiver: StatsReceiver = NullStatsReceiver,
  tracer: Tracer  = DefaultTracer,
  monitor: Monitor = DefaultMonitor,
  reporter: ReporterFactory = LoadedReporterFactory,
  loadBalancer: WeightedLoadBalancerFactory = DefaultBalancerFactory
) extends Client[Req, Rep] { outer =>

  private[this] def transform(stack: Stack[ServiceFactory[Req, Rep]]) = {
    val stk = stack
      .replace(FailureAccrualFactory.role, failureAccrual)
      .replace(StackClient.Role.pool, pool(statsReceiver))

    if (!failFast) stk.remove(FailFastFactory.role) else stk
  }

  private[this] val clientStack = transform(StackClient.newStack[Req, Rep])
  private[this] val endpointStack = transform(StackClient.endpointStack[Req, Rep])

  private[this] val params = Stack.Params.empty +
    param.Label(name) +
    param.Timer(timer) +
    param.Monitor(monitor) +
    param.Stats(statsReceiver) +
    param.Tracer(tracer) +
    param.Reporter(reporter) +
    LoadBalancerFactory.HostStats(hostStatsReceiver) +
    LoadBalancerFactory.Param(loadBalancer) +
    TimeoutFactory.Param(serviceTimeout) +
    TimeoutFilter.Param(requestTimeout) +
    ExpiringService.Param(maxIdletime, maxLifetime)

  private[this] val underlying = new StackClient[Req, Rep](clientStack, params) {
    protected type In = Req
    protected type Out = Rep
    // The default client forces users to compose these two as part of
    // the `endpointer`. We ignore them and instead override the
    // endpointer directly.
    lazy val unimplemented = throw new Exception("unimplemented")
    val newTransporter = Function.const(unimplemented) _
    val newDispatcher = Function.const(unimplemented) _

    override protected val endpointer = new Stack.Simple[ServiceFactory[Req, Rep]] {
      val role = com.twitter.finagle.stack.Endpoint
      val description = "Send requests over the wire"
      def make(next: ServiceFactory[Req, Rep])(implicit params: Stack.Params) = {
        val param.Stats(sr) = get[param.Stats]
        val Transporter.EndpointAddr(addr) = get[Transporter.EndpointAddr]
        outer.endpointer(addr, sr)
      }
    }
  }

  def newClient(dest: Name, label: String) =
    underlying.newClient(dest, label)

  // These are kept around to not break the API. They probably should
  // have been private[finagle] to begin with.
  val newStack: Name => ServiceFactory[Req, Rep] = newClient(_, name)
  val newStack0: Var[Addr] => ServiceFactory[Req, Rep] = va => {
    clientStack.make(params + LoadBalancerFactory.Dest(va))
  }
  val bindStack: SocketAddress => ServiceFactory[Req, Rep] = sa => {
    endpointStack.make(params + Transporter.EndpointAddr(sa))
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy