Skip to content

Commit

Permalink
Fix gRPC Retry Mechanism for Unsuccessful HTTP Responses
Browse files Browse the repository at this point in the history
  • Loading branch information
JiwonKKang committed Oct 28, 2024
1 parent 74579aa commit 18637d9
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,15 @@ public CompletableResultCode shutdown() {

/** Whether response is retriable or not. */
public static boolean isRetryable(Response response) {
// Only retry on gRPC codes which will always come with an HTTP success
if (!response.isSuccessful()) {

String grpcStatus = grpcStatus(response);

if (grpcStatus == null) {
return false;
}

// We don't check trailers for retry since retryable error codes always come with response
// headers, not trailers, in practice.
String grpcStatus = response.header(GRPC_STATUS);
return RetryUtil.retryableGrpcStatusCodes().contains(grpcStatus);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.exporter.sender.okhttp.internal;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import io.opentelemetry.exporter.internal.RetryUtil;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.Response;
import org.junit.jupiter.api.Test;

public class OkHttpGrpcSenderTest {

@Test
public void isRetryable_SuccessfulResponse() {
Response response =
new Response.Builder()
.request(new Request.Builder().url("http://localhost/").build())
.protocol(Protocol.HTTP_2)
.code(200)
.message("OK")
.header("grpc-status", "0") // OK
.build();

boolean isRetryable = OkHttpGrpcSender.isRetryable(response);
assertFalse(isRetryable);
}

@Test
public void isRetryable_RetryableGrpcStatus() {
for (String grpcStatus : RetryUtil.retryableGrpcStatusCodes()) {
Response response =
new Response.Builder()
.request(new Request.Builder().url("http://localhost/").build())
.protocol(Protocol.HTTP_2)
.code(503)
.message("Service Unavailable")
.header("grpc-status", grpcStatus)
.build();

boolean isRetryable = OkHttpGrpcSender.isRetryable(response);
assertTrue(isRetryable);
}
}

@Test
public void isRetryable_NonRetryableGrpcStatus() {
Response response =
new Response.Builder()
.request(new Request.Builder().url("http://localhost/").build())
.protocol(Protocol.HTTP_2)
.code(400)
.message("Bad Request")
.header("grpc-status", "3") // INVALID_ARGUMENT
.build();

boolean isRetryable = OkHttpGrpcSender.isRetryable(response);
assertFalse(isRetryable);
}
}

0 comments on commit 18637d9

Please # to comment.