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

com.twitter.finatra.http.routing.HttpWarmup.scala Maven / Gradle / Ivy

package com.twitter.finatra.http.routing

import com.twitter.finagle.http
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finatra.json.FinatraObjectMapper
import com.twitter.finatra.utils.FuturePools
import com.twitter.inject.Logging
import com.twitter.util.{Await, Future}
import javax.inject.Inject

class HttpWarmup @Inject()(
  router: HttpRouter,
  mapper: FinatraObjectMapper)
  extends Logging {

  private val userAgent = "http-warmup-client"

  /* Use a FuturePool to avoid getting a ConstFuture from Future.apply(...) */
  private val pool = FuturePools.fixedPool("HTTP Warmup", 1)

  /* Public */

  /**
   * Send a request to warmup services that are not yet externally receiving traffic.
   *
   * @param request - [[com.twitter.finagle.http.Request]] to send
   * @param forceRouteToAdminHttpMuxers - route the request to the HttpMuxer (e.g. needed for twitter-server admin
   *                                    endpoints that do not start with /admin)
   * @param times - number of times to send the request
   * @param responseCallback - callback called for every response where assertions can be made. NOTE: be aware that
   *                         failed assertions that throws Exceptions could prevent a server from restarting. This is
   *                         generally when dependent services are unresponsive causing the warm-up request(s) to fail.
   *                         As such, you should wrap your warm-up calls in these situations in a try/catch {}.
   */
  def send(
    request: => Request,
    forceRouteToAdminHttpMuxers: Boolean = false,
    times: Int = 1,
    responseCallback: Response => Unit = identity _) {

    for (i <- 1 to times) {
      val response = executeRequest(request, forceRouteToAdminHttpMuxers)
      responseCallback(response)
      info("Warmup " + request + " complete with " + response.status)
    }
  }

  def close() = {
    pool.executor.shutdownNow()
  }

  /* Private */

  private def executeRequest(request: Request, forceRouteToHttpMuxer: Boolean): Response = {
    val response = pool {
      info("Warmup " + request)
      routeRequest(request, forceRouteToHttpMuxer)
    }.flatten

    Await.result(response)
  }

  private def routeRequest(request: Request, forceRouteToHttpMuxer: Boolean): Future[Response] = {
    /* Mutation */
    request.headerMap.set("Host", "127.0.0.1")
    request.headerMap.set("User-Agent", userAgent)

    if (forceRouteToHttpMuxer)
      http.HttpMuxer(request)
    else if (request.uri.startsWith("/admin/finatra/"))
      router.services.adminService(request)
    else if (request.uri.startsWith("/admin"))
      http.HttpMuxer(request)
    else
      router.services.externalService(request)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy