From 3ecab759d2bff7250367d6064d0a42194077b469 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 15 Sep 2020 13:00:01 -0400 Subject: [PATCH 1/3] - fixes a bug where the retry handler could leak responses --- src/main/java/com/microsoft/graph/httpcore/RetryHandler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java index 987f7bf7b..9478060e6 100644 --- a/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/RetryHandler.java @@ -147,6 +147,9 @@ public Response intercept(Chain chain) throws IOException { while(retryRequest(response, executionCount, request, retryOption)) { request = request.newBuilder().addHeader(RETRY_ATTEMPT_HEADER, String.valueOf(executionCount)).build(); executionCount++; + if(response != null && response.body() != null) { + response.body().close(); + } response = chain.proceed(request); } return response; From 4097367c0eb1c124661462b31ad93c3a6a47820d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 15 Sep 2020 15:13:58 -0400 Subject: [PATCH 2/3] - adds a chaos handler to ease up unit testing --- .../graph/httpcore/ChaosHttpHandler.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java diff --git a/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java b/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java new file mode 100644 index 000000000..ed80e4eff --- /dev/null +++ b/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java @@ -0,0 +1,52 @@ +package com.microsoft.graph.httpcore; + +import java.io.IOException; +import java.util.concurrent.ThreadLocalRandom; + +import com.microsoft.graph.httpcore.middlewareoption.MiddlewareType; +import com.microsoft.graph.httpcore.middlewareoption.TelemetryOptions; + +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class ChaosHttpHandler implements Interceptor { + + public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.RETRY; + + /* + * constant string being used + */ + private final String RETRY_AFTER = "Retry-After"; + + public static final int MSClientErrorCodeTooManyRequests = 429; + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + if(request.tag(TelemetryOptions.class) == null) + request = request.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); + request.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); + + final Integer dice = ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE); + + if(dice % 3 == 0) { + return new Response + .Builder() + .request(request) + .protocol(Protocol.HTTP_1_1) + .code(MSClientErrorCodeTooManyRequests) + .message("Too Many Requests") + .addHeader(RETRY_AFTER, "10") + .body(ResponseBody.create(MediaType.get("application/json"), "{\"error\": {\"code\": \"TooManyRequests\",\"innerError\": {\"code\": \"429\",\"date\": \"2020-08-18T12:51:51\",\"message\": \"Please retry after\",\"request-id\": \"94fb3b52-452a-4535-a601-69e0a90e3aa2\",\"status\": \"429\"},\"message\": \"Please retry again later.\"}}")) + .build(); + } else { + return chain.proceed(request); + } + } + +} \ No newline at end of file From d4314ee42ce0f704f42ff7306b7ce232b7a1363b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 16 Sep 2020 08:26:24 -0400 Subject: [PATCH 3/3] - applies code review suggestions --- .../graph/httpcore/ChaosHttpHandler.java | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java b/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java index ed80e4eff..69601d187 100644 --- a/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java +++ b/src/main/java/com/microsoft/graph/httpcore/ChaosHttpHandler.java @@ -13,17 +13,30 @@ import okhttp3.Response; import okhttp3.ResponseBody; +/** + * DO NOT USE IN PRODUCTION + * interceptor that randomly fails the responses for unit testing purposes + */ public class ChaosHttpHandler implements Interceptor { - public final MiddlewareType MIDDLEWARE_TYPE = MiddlewareType.RETRY; - - /* - * constant string being used - */ - private final String RETRY_AFTER = "Retry-After"; - - public static final int MSClientErrorCodeTooManyRequests = 429; - + /* + * constant string being used + */ + private final String RETRY_AFTER = "Retry-After"; + /** + * Denominator for the failure rate (i.e. 1/X) + */ + private final Integer failureRate = 3; + /** + * default value to return on retry after + */ + private final String retryAfterValue = "10"; + /** + * body to respond on failed requests + */ + private final String responseBody = "{\"error\": {\"code\": \"TooManyRequests\",\"innerError\": {\"code\": \"429\",\"date\": \"2020-08-18T12:51:51\",\"message\": \"Please retry after\",\"request-id\": \"94fb3b52-452a-4535-a601-69e0a90e3aa2\",\"status\": \"429\"},\"message\": \"Please retry again later.\"}}"; + public static final int MSClientErrorCodeTooManyRequests = 429; + @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); @@ -31,22 +44,22 @@ public Response intercept(Chain chain) throws IOException { if(request.tag(TelemetryOptions.class) == null) request = request.newBuilder().tag(TelemetryOptions.class, new TelemetryOptions()).build(); request.tag(TelemetryOptions.class).setFeatureUsage(TelemetryOptions.RETRY_HANDLER_ENABLED_FLAG); - - final Integer dice = ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE); + + final Integer dice = ThreadLocalRandom.current().nextInt(1, Integer.MAX_VALUE); - if(dice % 3 == 0) { - return new Response - .Builder() - .request(request) - .protocol(Protocol.HTTP_1_1) - .code(MSClientErrorCodeTooManyRequests) - .message("Too Many Requests") - .addHeader(RETRY_AFTER, "10") - .body(ResponseBody.create(MediaType.get("application/json"), "{\"error\": {\"code\": \"TooManyRequests\",\"innerError\": {\"code\": \"429\",\"date\": \"2020-08-18T12:51:51\",\"message\": \"Please retry after\",\"request-id\": \"94fb3b52-452a-4535-a601-69e0a90e3aa2\",\"status\": \"429\"},\"message\": \"Please retry again later.\"}}")) - .build(); - } else { - return chain.proceed(request); - } + if(dice % failureRate == 0) { + return new Response + .Builder() + .request(request) + .protocol(Protocol.HTTP_1_1) + .code(MSClientErrorCodeTooManyRequests) + .message("Too Many Requests") + .addHeader(RETRY_AFTER, retryAfterValue) + .body(ResponseBody.create(MediaType.get("application/json"), responseBody)) + .build(); + } else { + return chain.proceed(request); + } } } \ No newline at end of file