Skip to content

Commit

Permalink
Test RetryingChannel
Browse files Browse the repository at this point in the history
  • Loading branch information
carterkozak committed Oct 21, 2024
1 parent bc67cff commit fe237ad
Showing 1 changed file with 123 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import com.palantir.conjure.java.api.errors.QosReason;
import com.palantir.conjure.java.api.errors.QosReason.DueTo;
import com.palantir.conjure.java.api.errors.QosReason.RetryHint;
import com.palantir.conjure.java.api.errors.QosReasons;
import com.palantir.conjure.java.client.config.ClientConfiguration;
import com.palantir.dialogue.EndpointChannel;
import com.palantir.dialogue.Request;
import com.palantir.dialogue.RequestBody;
import com.palantir.dialogue.Response;
import com.palantir.dialogue.TestEndpoint;
import com.palantir.dialogue.TestResponse;
import com.palantir.dialogue.TestResponseQosEncoder;
import com.palantir.logsafe.exceptions.SafeIoException;
import com.palantir.logsafe.exceptions.SafeRuntimeException;
import java.io.ByteArrayOutputStream;
Expand Down Expand Up @@ -135,9 +140,8 @@ public void testRetriesMax() {

@Test
public void retries_429s() throws Exception {
Response mockResponse = mock(Response.class);
when(mockResponse.code()).thenReturn(429);
when(channel.execute(any())).thenReturn(Futures.immediateFuture(mockResponse));
when(channel.execute(any())).thenAnswer((Answer<ListenableFuture<Response>>)
_invocation -> Futures.immediateFuture(new TestResponse().code(429)));

EndpointChannel retryer = new RetryingChannel(
channel,
Expand All @@ -149,17 +153,50 @@ public void retries_429s() throws Exception {
ClientConfiguration.RetryOnTimeout.DISABLED);
ListenableFuture<Response> response = retryer.execute(REQUEST);
assertThat(response).isDone();
assertThat(response.get())
assertThat(response.get().code())
.as("After retries are exhausted the 429 response should be returned")
.isSameAs(mockResponse);
.isEqualTo(429);
verify(channel, times(4)).execute(REQUEST);
}

@Test
public void retries_503s() throws Exception {
Response mockResponse = mock(Response.class);
when(mockResponse.code()).thenReturn(503);
when(channel.execute(any())).thenReturn(Futures.immediateFuture(mockResponse));
public void retries_429s_dueTo_custom() throws Exception {
when(channel.execute(any())).thenAnswer((Answer<ListenableFuture<Response>>) _invocation -> {
TestResponse stubResponse = new TestResponse().code(429);
QosReasons.encodeToResponse(
QosReason.builder().reason("reason").dueTo(DueTo.CUSTOM).build(),
stubResponse,
TestResponseQosEncoder.INSTANCE);
return Futures.immediateFuture(stubResponse);
});

EndpointChannel retryer = new RetryingChannel(
channel,
TestEndpoint.POST,
"my-channel",
3,
Duration.ZERO,
ClientConfiguration.ServerQoS.AUTOMATIC_RETRY,
ClientConfiguration.RetryOnTimeout.DISABLED);
ListenableFuture<Response> response = retryer.execute(REQUEST);
assertThat(response).isDone();
assertThat(response.get().code())
.as("After retries are exhausted the 429 response should be returned")
.isEqualTo(429);
verify(channel, times(4)).execute(REQUEST);
}

@Test
public void does_not_retry_429_when_hinted() throws Exception {
TestResponse stubResponse = new TestResponse().code(429);
QosReasons.encodeToResponse(
QosReason.builder()
.reason("reason")
.retryHint(RetryHint.DO_NOT_RETRY)
.build(),
stubResponse,
TestResponseQosEncoder.INSTANCE);
when(channel.execute(any())).thenReturn(Futures.immediateFuture(stubResponse));

EndpointChannel retryer = new RetryingChannel(
channel,
Expand All @@ -172,11 +209,87 @@ public void retries_503s() throws Exception {
ListenableFuture<Response> response = retryer.execute(REQUEST);
assertThat(response).isDone();
assertThat(response.get())
.as("The 429 response should be returned without retrying due to RetryHint.DO_NOT_RETRY")
.isSameAs(stubResponse);
verify(channel, times(1)).execute(REQUEST);
}

@Test
public void retries_503s() throws Exception {
when(channel.execute(any())).thenAnswer((Answer<ListenableFuture<Response>>)
_invocation -> Futures.immediateFuture(new TestResponse().code(503)));

EndpointChannel retryer = new RetryingChannel(
channel,
TestEndpoint.POST,
"my-channel",
3,
Duration.ZERO,
ClientConfiguration.ServerQoS.AUTOMATIC_RETRY,
ClientConfiguration.RetryOnTimeout.DISABLED);
ListenableFuture<Response> response = retryer.execute(REQUEST);
assertThat(response).isDone();
assertThat(response.get().code())
.as("After retries are exhausted the 503 response should be returned")
.isSameAs(mockResponse);
.isEqualTo(503);
verify(channel, times(4)).execute(REQUEST);
}

@Test
public void retries_503s_dueTo_custom() throws Exception {
when(channel.execute(any())).thenAnswer((Answer<ListenableFuture<Response>>) _invocation -> {
TestResponse stubResponse = new TestResponse().code(503);
QosReasons.encodeToResponse(
QosReason.builder().reason("reason").dueTo(DueTo.CUSTOM).build(),
stubResponse,
TestResponseQosEncoder.INSTANCE);
return Futures.immediateFuture(stubResponse);
});

EndpointChannel retryer = new RetryingChannel(
channel,
TestEndpoint.POST,
"my-channel",
3,
Duration.ZERO,
ClientConfiguration.ServerQoS.AUTOMATIC_RETRY,
ClientConfiguration.RetryOnTimeout.DISABLED);
ListenableFuture<Response> response = retryer.execute(REQUEST);
assertThat(response).isDone();
assertThat(response.get().code())
.as("After retries are exhausted the 503 response should be returned")
.isEqualTo(503);
verify(channel, times(4)).execute(REQUEST);
}

@Test
public void does_not_retry_503_when_hinted() throws Exception {
TestResponse stubResponse = new TestResponse().code(503);
QosReasons.encodeToResponse(
QosReason.builder()
.reason("reason")
.retryHint(RetryHint.DO_NOT_RETRY)
.build(),
stubResponse,
TestResponseQosEncoder.INSTANCE);
when(channel.execute(any())).thenReturn(Futures.immediateFuture(stubResponse));

EndpointChannel retryer = new RetryingChannel(
channel,
TestEndpoint.POST,
"my-channel",
3,
Duration.ZERO,
ClientConfiguration.ServerQoS.AUTOMATIC_RETRY,
ClientConfiguration.RetryOnTimeout.DISABLED);
ListenableFuture<Response> response = retryer.execute(REQUEST);
assertThat(response).isDone();
assertThat(response.get())
.as("The 503 response should be returned without retrying due to RetryHint.DO_NOT_RETRY")
.isSameAs(stubResponse);
verify(channel, times(1)).execute(REQUEST);
}

@Test
public void retries_308s() throws Exception {
Response mockResponse = mock(Response.class);
Expand Down

0 comments on commit fe237ad

Please sign in to comment.