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

com.twitter.finagle.http.codec.HttpClientDispatcher.scala Maven / Gradle / Ivy

package com.twitter.finagle.http.codec

import com.twitter.finagle.dispatch.GenSerialClientDispatcher
import com.twitter.finagle.http.Multi
import com.twitter.finagle.http.Request
import com.twitter.finagle.http.Response
import com.twitter.finagle.http.StreamTransport
import com.twitter.finagle.stats.CategorizingExceptionStatsHandler
import com.twitter.finagle.stats.StatsReceiver
import com.twitter.logging.Logger
import com.twitter.util.Future
import com.twitter.util.Promise
import com.twitter.util.Return

private[finagle] object HttpClientDispatcher {
  private[this] val logger = Logger.get(getClass())
  private[this] val unit: (Unit, Unit) => Unit = (_, _) => ()
  private[this] val exceptionStatsHandler = new CategorizingExceptionStatsHandler()

  def dispatch(
    trans: StreamTransport[Request, Response],
    statsReceiver: StatsReceiver,
    req: Request,
    p: Promise[Response]
  ): Future[Unit] = {
    // wait on these concurrently:
    trans
      .write(req).joinWith(
        // Drain the Transport into Response body.
        trans.read().flatMap {
          case Multi(res, readFinished) =>
            p.updateIfEmpty(Return(res))
            readFinished
        } // we don't need to satisfy p when we fail because GenSerialClientDispatcher does already
      )(unit).onFailure { t =>
        // This Future represents the totality of the exchange;
        // thus failure represents *any* failure that can happen
        // during the exchange.
        logger.debug(t, "Failed mid-stream. Terminating stream, closing connection")
        exceptionStatsHandler.record(statsReceiver.scope("stream"), t)
        req.reader.discard()
        trans.close()
      }
  }
}

/**
 * Client dispatcher for HTTP.
 *
 * @param statsReceiver typically scoped to `clientName/dispatcher`
 */
private[finagle] class HttpClientDispatcher(
  trans: StreamTransport[Request, Response],
  statsReceiver: StatsReceiver)
    extends GenSerialClientDispatcher[Request, Response, Request, Multi[Response]](
      trans,
      statsReceiver
    ) {

  protected def dispatch(req: Request, p: Promise[Response]): Future[Unit] =
    HttpClientDispatcher.dispatch(trans, statsReceiver, req, p)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy