Skip to content

Commit

Permalink
Fix intermittently failing ChunkedDownloadSpec (ExpediaGroup#256)
Browse files Browse the repository at this point in the history
Fix "Proxies long lasting HTTP Chunked downloads without triggering gateway read timeout."
test by adding a separate origin whose metrics are not influenced by the
preceding two tests.

(cherry picked from commit 8bed0dc)
  • Loading branch information
mikkokar committed Oct 3, 2018
1 parent e8aa787 commit d63754f
Showing 1 changed file with 18 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package com.hotels.styx.proxy
import com.google.common.base.Charsets
import com.google.common.base.Charsets._
import com.hotels.styx._
import com.hotels.styx.api.client.Origin
import com.hotels.styx.api.messages.HttpResponseStatus._
import com.hotels.styx.support.configuration.{HttpBackend, Origins}
import com.hotels.styx.support.{NettyOrigins, TestClientSupport}
import com.hotels.styx.utils.HttpTestClient
Expand All @@ -27,7 +29,6 @@ import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.http.HttpHeaders.Names._
import io.netty.handler.codec.http.HttpHeaders.Values._
import io.netty.handler.codec.http.HttpMethod.GET
import com.hotels.styx.api.messages.HttpResponseStatus._
import io.netty.handler.codec.http.HttpVersion._
import io.netty.handler.codec.http.LastHttpContent.EMPTY_LAST_CONTENT
import io.netty.handler.codec.http._
Expand All @@ -44,12 +45,14 @@ class ChunkedDownloadSpec extends FunSpec
with TestClientSupport
with Eventually {

val (originOne, originOneServer) = originAndCustomResponseWebServer("NettyOrigin")
val (originOne, originOneServer) = originAndCustomResponseWebServer("NettyOrigin-01")
val (originTwo, originTwoServer) = originAndCustomResponseWebServer("NettyOrigin-02")

override protected def beforeAll(): Unit = {
super.beforeAll()
styxServer.setBackends(
"/chunkedDownloadSpec/" -> HttpBackend("appOne", Origins(originOneServer))
"/chunkedDownloadSpec/a/" -> HttpBackend("appOne", Origins(originOneServer)),
"/chunkedDownloadSpec/b/" -> HttpBackend("appTwo", Origins(originTwoServer))
)
}

Expand All @@ -63,7 +66,7 @@ class ChunkedDownloadSpec extends FunSpec
it("Proxies a response with chunked HTTP content.") {
originRespondingWith(response200OkWithThreeChunks("a" * 10, "b" * 20, "c" * 30))

val request = api.HttpRequest.Builder.get(styxServer.routerURL("/chunkedDownloadSpec/1")).build()
val request = api.HttpRequest.Builder.get(styxServer.routerURL("/chunkedDownloadSpec/a/1")).build()
val response = decodedRequest(request)

response.status() should be(OK)
Expand All @@ -76,7 +79,7 @@ class ChunkedDownloadSpec extends FunSpec
val messageBody = "Foo bar 0123456789012345678901234567890123456789\\n" * 100
originRespondingWith(response200OkWithSlowChunkedMessageBody(messageBody))

val request = api.HttpRequest.Builder.get(styxServer.routerURL("/chunkedDownloadSpec/2")).build()
val request = api.HttpRequest.Builder.get(styxServer.routerURL("/chunkedDownloadSpec/a/2")).build()
val response = decodedRequest(request)

response.status() should be(OK)
Expand All @@ -85,10 +88,13 @@ class ChunkedDownloadSpec extends FunSpec
}

it("Cancels the HTTP download request when browser closes the connection.") {
assert(noBusyConnectionsToOrigin(originTwo), "Connection remains busy.")
assert(noAvailableConnectionsInPool(originTwo), "Connection was not closed.")

val messageBody = "Foo bar 0123456789012345678901234567890123456789\\n" * 100
originRespondingWith(response200OkWithSlowChunkedMessageBody(messageBody))

val request: DefaultFullHttpRequest = nettyGetRequest("/chunkedDownloadSpec/3")
val request: DefaultFullHttpRequest = nettyGetRequest("/chunkedDownloadSpec/b/3")

val client = newTestClientInstance("localhost", styxServer.httpPort)
client.write(request)
Expand All @@ -97,18 +103,18 @@ class ChunkedDownloadSpec extends FunSpec
client.disconnect()

eventually(timeout(5 seconds)) {
assert(noBusyConnectionsToOrigin, "Connection remains busy.")
assert(noAvailableConnectionsInPool, "Connection was not closed.")
assert(noBusyConnectionsToOrigin(originTwo), "Connection remains busy.")
assert(noAvailableConnectionsInPool(originTwo), "Connection was not closed.")
}
}
}

def noBusyConnectionsToOrigin = {
styxServer.metricsSnapshot.gauge(s"origins.appOne.localhost:${originOne.host.getPort}.connectionspool.busy-connections").get == 0
def noBusyConnectionsToOrigin(origin: Origin) = {
styxServer.metricsSnapshot.gauge(s"origins.appTwo.localhost:${origin.host.getPort}.connectionspool.busy-connections").get == 0
}

def noAvailableConnectionsInPool = {
styxServer.metricsSnapshot.gauge(s"origins.appOne.localhost:${originOne.host.getPort}.connectionspool.available-connections").get == 0
def noAvailableConnectionsInPool(origin: Origin) = {
styxServer.metricsSnapshot.gauge(s"origins.appTwo.localhost:${origin.host.getPort}.connectionspool.available-connections").get == 0
}

def ensureResponseDidNotArrive(client: HttpTestClient) = {
Expand Down

0 comments on commit d63754f

Please sign in to comment.