Skip to content
Snippets Groups Projects
Commit d496d6a2 authored by Neelesh Thakur's avatar Neelesh Thakur
Browse files

Merge branch 'retry' into 'master'

add retries for schema service and all other service calls

See merge request !201
parents 5a02fe9c 070abe68
No related branches found
No related tags found
1 merge request!201add retries for schema service and all other service calls
Pipeline #67309 failed
...@@ -544,7 +544,7 @@ The following software have components provided under the terms of this license: ...@@ -544,7 +544,7 @@ The following software have components provided under the terms of this license:
- Proton-J (from https://repo1.maven.org/maven2/org/apache/qpid/proton-j) - Proton-J (from https://repo1.maven.org/maven2/org/apache/qpid/proton-j)
- QpidJMS Client (from ) - QpidJMS Client (from )
- RabbitMQ Java Client (from https://www.rabbitmq.com) - RabbitMQ Java Client (from https://www.rabbitmq.com)
- Reactive Streams Netty driver (from https://github.com/reactor/reactor-netty) - Reactor Netty with all modules (from https://github.com/reactor/reactor-netty)
- Retrofit (from https://repo1.maven.org/maven2/com/squareup/retrofit2/retrofit) - Retrofit (from https://repo1.maven.org/maven2/com/squareup/retrofit2/retrofit)
- Servlet Specification 2.5 API (from http://jetty.mortbay.org) - Servlet Specification 2.5 API (from http://jetty.mortbay.org)
- SnakeYAML (from http://www.snakeyaml.org) - SnakeYAML (from http://www.snakeyaml.org)
...@@ -552,6 +552,7 @@ The following software have components provided under the terms of this license: ...@@ -552,6 +552,7 @@ The following software have components provided under the terms of this license:
- Spring AMQP Core (from https://projects.spring.io/spring-amqp) - Spring AMQP Core (from https://projects.spring.io/spring-amqp)
- Spring AOP (from https://github.com/spring-projects/spring-framework) - Spring AOP (from https://github.com/spring-projects/spring-framework)
- Spring Beans (from https://github.com/spring-projects/spring-framework) - Spring Beans (from https://github.com/spring-projects/spring-framework)
- Spring Boot AOP Starter (from http://projects.spring.io/spring-boot/)
- Spring Boot Actuator (from http://projects.spring.io/spring-boot/) - Spring Boot Actuator (from http://projects.spring.io/spring-boot/)
- Spring Boot Actuator Starter (from http://projects.spring.io/spring-boot/) - Spring Boot Actuator Starter (from http://projects.spring.io/spring-boot/)
- Spring Boot Log4j 2 Starter (from https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-log4j2) - Spring Boot Log4j 2 Starter (from https://projects.spring.io/spring-boot/#/spring-boot-parent/spring-boot-starters/spring-boot-starter-log4j2)
...@@ -593,12 +594,12 @@ The following software have components provided under the terms of this license: ...@@ -593,12 +594,12 @@ The following software have components provided under the terms of this license:
- aggs-matrix-stats (from https://github.com/elastic/elasticsearch) - aggs-matrix-stats (from https://github.com/elastic/elasticsearch)
- asm (from http://asm.ow2.io/) - asm (from http://asm.ow2.io/)
- asm (from http://asm.ow2.io/) - asm (from http://asm.ow2.io/)
- cli (from https://github.com/elastic/elasticsearch)
- compiler (from http://github.com/spullara/mustache.java) - compiler (from http://github.com/spullara/mustache.java)
- datastore-v1-proto-client (from https://repo1.maven.org/maven2/com/google/cloud/datastore/datastore-v1-proto-client) - datastore-v1-proto-client (from https://repo1.maven.org/maven2/com/google/cloud/datastore/datastore-v1-proto-client)
- elasticsearch (from https://repo1.maven.org/maven2/org/elasticsearch/elasticsearch) - elasticsearch-cli (from https://github.com/elastic/elasticsearch)
- elasticsearch-core (from https://github.com/elastic/elasticsearch) - elasticsearch-core (from https://github.com/elastic/elasticsearch)
- elasticsearch-geo (from https://github.com/elastic/elasticsearch) - elasticsearch-geo (from https://github.com/elastic/elasticsearch)
- elasticsearch-secure-sm (from https://github.com/elastic/elasticsearch)
- elasticsearch-x-content (from https://github.com/elastic/elasticsearch) - elasticsearch-x-content (from https://github.com/elastic/elasticsearch)
- error-prone annotations (from https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations) - error-prone annotations (from https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations)
- error-prone annotations (from https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations) - error-prone annotations (from https://repo1.maven.org/maven2/com/google/errorprone/error_prone_annotations)
...@@ -701,14 +702,13 @@ The following software have components provided under the terms of this license: ...@@ -701,14 +702,13 @@ The following software have components provided under the terms of this license:
- rest (from https://github.com/elastic/elasticsearch) - rest (from https://github.com/elastic/elasticsearch)
- rest-high-level (from https://github.com/elastic/elasticsearch) - rest-high-level (from https://github.com/elastic/elasticsearch)
- rxjava (from https://github.com/ReactiveX/RxJava) - rxjava (from https://github.com/ReactiveX/RxJava)
- secure-sm (from https://github.com/elastic/elasticsearch) - server (from https://github.com/elastic/elasticsearch)
- spring-boot (from https://spring.io/projects/spring-boot) - spring-boot (from https://spring.io/projects/spring-boot)
- spring-boot-actuator-autoconfigure (from https://spring.io/projects/spring-boot) - spring-boot-actuator-autoconfigure (from https://spring.io/projects/spring-boot)
- spring-boot-autoconfigure (from https://spring.io/projects/spring-boot) - spring-boot-autoconfigure (from https://spring.io/projects/spring-boot)
- spring-boot-configuration-processor (from https://spring.io/projects/spring-boot) - spring-boot-configuration-processor (from https://spring.io/projects/spring-boot)
- spring-boot-dependencies (from https://spring.io/projects/spring-boot) - spring-boot-dependencies (from https://spring.io/projects/spring-boot)
- spring-boot-starter-amqp (from https://spring.io/projects/spring-boot) - spring-boot-starter-amqp (from https://spring.io/projects/spring-boot)
- spring-boot-starter-aop (from https://spring.io/projects/spring-boot)
- spring-boot-starter-data-mongodb (from https://spring.io/projects/spring-boot) - spring-boot-starter-data-mongodb (from https://spring.io/projects/spring-boot)
- spring-boot-starter-jersey (from https://spring.io/projects/spring-boot) - spring-boot-starter-jersey (from https://spring.io/projects/spring-boot)
- spring-boot-starter-json (from https://spring.io/projects/spring-boot) - spring-boot-starter-json (from https://spring.io/projects/spring-boot)
...@@ -1101,7 +1101,6 @@ The following software have components provided under the terms of this license: ...@@ -1101,7 +1101,6 @@ The following software have components provided under the terms of this license:
- JOpt Simple (from http://pholser.github.com/jopt-simple) - JOpt Simple (from http://pholser.github.com/jopt-simple)
- JUL to SLF4J bridge (from http://www.slf4j.org) - JUL to SLF4J bridge (from http://www.slf4j.org)
- Java Client Runtime for AutoRest (from https://github.com/Azure/autorest-clientruntime-for-java) - Java Client Runtime for AutoRest (from https://github.com/Azure/autorest-clientruntime-for-java)
- Java JWT (from http://www.jwt.io)
- Lucene Core (from https://repo1.maven.org/maven2/org/apache/lucene/lucene-core) - Lucene Core (from https://repo1.maven.org/maven2/org/apache/lucene/lucene-core)
- Microsoft Application Insights Java SDK Core (from https://github.com/Microsoft/ApplicationInsights-Java) - Microsoft Application Insights Java SDK Core (from https://github.com/Microsoft/ApplicationInsights-Java)
- Microsoft Application Insights Java SDK Spring Boot starter (from https://github.com/Microsoft/ApplicationInsights-Java) - Microsoft Application Insights Java SDK Spring Boot starter (from https://github.com/Microsoft/ApplicationInsights-Java)
...@@ -1134,6 +1133,7 @@ The following software have components provided under the terms of this license: ...@@ -1134,6 +1133,7 @@ The following software have components provided under the terms of this license:
- adal4j (from https://github.com/AzureAD/azure-activedirectory-library-for-java) - adal4j (from https://github.com/AzureAD/azure-activedirectory-library-for-java)
- azure-documentdb (from https://azure.microsoft.com/en-us/services/cosmos-db/) - azure-documentdb (from https://azure.microsoft.com/en-us/services/cosmos-db/)
- documentdb-bulkexecutor (from http://azure.microsoft.com/en-us/services/documentdb/) - documentdb-bulkexecutor (from http://azure.microsoft.com/en-us/services/documentdb/)
- java jwt (from https://github.com/auth0/java-jwt)
- micrometer-core (from https://github.com/micrometer-metrics/micrometer) - micrometer-core (from https://github.com/micrometer-metrics/micrometer)
- mockito-core (from https://github.com/mockito/mockito) - mockito-core (from https://github.com/mockito/mockito)
- mockito-core (from https://github.com/mockito/mockito) - mockito-core (from https://github.com/mockito/mockito)
......
...@@ -28,6 +28,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; ...@@ -28,6 +28,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.Duration; import java.time.Duration;
import java.util.function.Predicate;
/** /**
* This class handles retry configuration logic for calls made to <prefix>/storage/v2/query/records:batch * This class handles retry configuration logic for calls made to <prefix>/storage/v2/query/records:batch
...@@ -50,23 +51,25 @@ public class RetryPolicy { ...@@ -50,23 +51,25 @@ public class RetryPolicy {
/** /**
* @return RetryConfig with 3 attempts and 1 sec wait time * @return RetryConfig with 3 attempts and 1 sec wait time
*/ */
public RetryConfig retryConfig() { public RetryConfig retryConfig(Predicate<HttpResponse> predicate) {
return RetryConfig.<HttpResponse>custom() return RetryConfig.<HttpResponse>custom()
.maxAttempts(attempts) .maxAttempts(attempts)
.waitDuration(Duration.ofMillis(waitDuration)) .waitDuration(Duration.ofMillis(waitDuration))
.retryOnResult(response -> isRetryRequired(response)) .retryOnResult(predicate)
.build(); .build();
} }
/** /**
* Unfound records get listed under a JsonArray "notFound" in the http json response * Unfound records get listed under a JsonArray "notFound" in the http json response
*
* @param response * @param response
* @return if there are elements in "notFound" returns true, else false * @return if there are elements in "notFound" returns true, else false
*/ */
private boolean isRetryRequired(HttpResponse response) { public boolean batchRetryPolicy(HttpResponse response) {
if (response == null || response.getBody().isEmpty()) { if (retryOnEmptyResponse(response)) return false;
return false;
} if (defaultResponseRetry(response)) return true;
JsonObject jsonObject = new JsonParser().parse(response.getBody()).getAsJsonObject(); JsonObject jsonObject = new JsonParser().parse(response.getBody()).getAsJsonObject();
JsonElement notFoundElement = (JsonArray) jsonObject.get(RECORD_NOT_FOUND); JsonElement notFoundElement = (JsonArray) jsonObject.get(RECORD_NOT_FOUND);
if (notFoundElement == null || if (notFoundElement == null ||
...@@ -75,7 +78,37 @@ public class RetryPolicy { ...@@ -75,7 +78,37 @@ public class RetryPolicy {
notFoundElement.getAsJsonArray().isJsonNull()) { notFoundElement.getAsJsonArray().isJsonNull()) {
return false; return false;
} }
log.info("Retry is set true"); log.info("Storage batch API retry");
return true;
}
public boolean schemaRetryPolicy(HttpResponse response) {
if (retryOnEmptyResponse(response)) return false;
if (defaultResponseRetry(response)) return true;
if (response.getResponseCode() == 404) {
log.info("Schema API retry");
return true;
}
return false;
}
public boolean defaultRetryPolicy(HttpResponse response) {
if (retryOnEmptyResponse(response)) return false;
return defaultResponseRetry(response);
}
private boolean retryOnEmptyResponse(HttpResponse response) {
return response == null || response.getBody().isEmpty();
}
private boolean defaultResponseRetry(HttpResponse response) {
if (response.getResponseCode() <= 501) return false;
log.info(String.format("Default retry, response code: %s", response.getResponseCode()));
return true; return true;
} }
} }
...@@ -41,6 +41,7 @@ import java.util.function.Supplier; ...@@ -41,6 +41,7 @@ import java.util.function.Supplier;
public class UrlFetchServiceAzureImpl implements IUrlFetchService { public class UrlFetchServiceAzureImpl implements IUrlFetchService {
public static final String STORAGE_QUERY_RECORD_FOR_CONVERSION_HOST_URL = "storage/v2/query/records:batch"; public static final String STORAGE_QUERY_RECORD_FOR_CONVERSION_HOST_URL = "storage/v2/query/records:batch";
public static final String SCHEMA_SERVICE_HOST_URL = "api/schema-service/v1/schema";
@Autowired @Autowired
private RetryPolicy policy; private RetryPolicy policy;
...@@ -50,6 +51,7 @@ public class UrlFetchServiceAzureImpl implements IUrlFetchService { ...@@ -50,6 +51,7 @@ public class UrlFetchServiceAzureImpl implements IUrlFetchService {
@Autowired @Autowired
private JaxRsDpsLog logger; private JaxRsDpsLog logger;
/** /**
* this method invokes retryFunction only for <prefix>/storage/v2/query/records:batch * this method invokes retryFunction only for <prefix>/storage/v2/query/records:batch
* calls otherwise invokes UrlFetchService.sendRequest(FetchServiceHttpRequest request) * calls otherwise invokes UrlFetchService.sendRequest(FetchServiceHttpRequest request)
...@@ -60,14 +62,7 @@ public class UrlFetchServiceAzureImpl implements IUrlFetchService { ...@@ -60,14 +62,7 @@ public class UrlFetchServiceAzureImpl implements IUrlFetchService {
*/ */
@Override @Override
public HttpResponse sendRequest(FetchServiceHttpRequest httpRequest) throws URISyntaxException { public HttpResponse sendRequest(FetchServiceHttpRequest httpRequest) throws URISyntaxException {
HttpResponse output; return this.retryFunction(httpRequest);
if (httpRequest.getUrl().contains(STORAGE_QUERY_RECORD_FOR_CONVERSION_HOST_URL)) {
output = this.retryFunction(httpRequest);
if (output != null) {
return output;
}
}
return this.urlFetchService.sendRequest(httpRequest);
} }
/** /**
...@@ -78,7 +73,15 @@ public class UrlFetchServiceAzureImpl implements IUrlFetchService { ...@@ -78,7 +73,15 @@ public class UrlFetchServiceAzureImpl implements IUrlFetchService {
* @return null if URISyntaxException is caught else returns HttpResponse * @return null if URISyntaxException is caught else returns HttpResponse
*/ */
private HttpResponse retryFunction(FetchServiceHttpRequest request) { private HttpResponse retryFunction(FetchServiceHttpRequest request) {
RetryConfig config = this.policy.retryConfig(); RetryConfig config;
if (request.getUrl().contains(STORAGE_QUERY_RECORD_FOR_CONVERSION_HOST_URL)) {
config = this.policy.retryConfig(response -> this.policy.batchRetryPolicy(response));
} else if (request.getUrl().contains(SCHEMA_SERVICE_HOST_URL)) {
config = this.policy.retryConfig(response -> this.policy.schemaRetryPolicy(response));
} else {
config = this.policy.retryConfig(response -> this.policy.defaultRetryPolicy(response));
}
RetryRegistry registry = RetryRegistry.of(config); RetryRegistry registry = RetryRegistry.of(config);
Retry retry = registry.retry("retryPolicy", config); Retry retry = registry.retry("retryPolicy", config);
......
...@@ -131,7 +131,7 @@ public class RetryPolicyTest { ...@@ -131,7 +131,7 @@ public class RetryPolicyTest {
@Test @Test
public void retry_should_be_true_for_jsonResponseWithNotFound() { public void retry_should_be_true_for_jsonResponseWithNotFound() {
RetryConfig config = this.retryPolicy.retryConfig(); RetryConfig config = this.retryPolicy.retryConfig(response -> this.retryPolicy.batchRetryPolicy(response));
Predicate<HttpResponse> retry = config.getResultPredicate(); Predicate<HttpResponse> retry = config.getResultPredicate();
response.setBody(JSON_RESPONSE_WITH_NOT_FOUND); response.setBody(JSON_RESPONSE_WITH_NOT_FOUND);
assert retry != null; assert retry != null;
...@@ -142,7 +142,7 @@ public class RetryPolicyTest { ...@@ -142,7 +142,7 @@ public class RetryPolicyTest {
@Test @Test
public void retry_should_be_false_for_jsonResponse1WithOut_NotFound() { public void retry_should_be_false_for_jsonResponse1WithOut_NotFound() {
RetryConfig config = this.retryPolicy.retryConfig(); RetryConfig config = this.retryPolicy.retryConfig(response -> this.retryPolicy.batchRetryPolicy(response));
Predicate<HttpResponse> retry = config.getResultPredicate(); Predicate<HttpResponse> retry = config.getResultPredicate();
response.setBody(JSON_RESPONSE1_WITHOUT_NOT_FOUND); response.setBody(JSON_RESPONSE1_WITHOUT_NOT_FOUND);
boolean value = retry.test(response); boolean value = retry.test(response);
...@@ -152,7 +152,7 @@ public class RetryPolicyTest { ...@@ -152,7 +152,7 @@ public class RetryPolicyTest {
@Test @Test
public void retry_should_be_false_for_jsonResponse2WithOut_NotFound() { public void retry_should_be_false_for_jsonResponse2WithOut_NotFound() {
RetryConfig config = this.retryPolicy.retryConfig(); RetryConfig config = this.retryPolicy.retryConfig(response -> this.retryPolicy.batchRetryPolicy(response));
Predicate<HttpResponse> retry = config.getResultPredicate(); Predicate<HttpResponse> retry = config.getResultPredicate();
response.setBody(JSON_RESPONSE2_WITHOUT_NOT_FOUND); response.setBody(JSON_RESPONSE2_WITHOUT_NOT_FOUND);
boolean value = retry.test(response); boolean value = retry.test(response);
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
package org.opengroup.osdu.indexer.azure.service; package org.opengroup.osdu.indexer.azure.service;
import io.github.resilience4j.retry.RetryConfig;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
...@@ -26,12 +24,8 @@ import org.opengroup.osdu.core.common.http.UrlFetchServiceImpl; ...@@ -26,12 +24,8 @@ import org.opengroup.osdu.core.common.http.UrlFetchServiceImpl;
import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
import org.opengroup.osdu.core.common.model.http.HttpResponse; import org.opengroup.osdu.core.common.model.http.HttpResponse;
import java.time.Duration; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
...@@ -95,45 +89,43 @@ public class UrlFetchServiceAzureImplTest { ...@@ -95,45 +89,43 @@ public class UrlFetchServiceAzureImplTest {
" \"conversionStatuses\":[]\n" + " \"conversionStatuses\":[]\n" +
"}"; "}";
private static final String url = "https://demo/api/storage/v2/query/records:batch"; private static final String BATCH_API_URL = "https://demo/api/storage/v2/query/records:batch";
private static final String url2 = "https://demo/api/storage/v2/schemas"; private static final String STORAGE_API_URL = "https://demo/api/storage/v2/schemas";
private static final String SCHEMA_API_URL = "https://demo/api/schema-service/v1/schema/osdu:file:gom:1.0.0";
@Before
public void setUp() {
when(this.retryPolicy.retryConfig()).thenReturn(new RetryPolicy().retryConfig());
}
@Test @Test
public void shouldRetry_ForJSON1_when_storageQueryRecordCallIsMade() throws Exception { public void shouldRetry_ForJSON1_when_storageQueryRecordCallIsMade() throws Exception {
response.setBody(JSON1); response.setBody(JSON1);
httpRequest.setUrl(url); httpRequest.setUrl(BATCH_API_URL);
when(this.retryPolicy.retryConfig(any())).thenReturn(new RetryPolicy().retryConfig(response -> this.retryPolicy.batchRetryPolicy(response)));
when(urlFetchServiceAzure.sendRequest(httpRequest)).thenReturn(response); when(urlFetchService.sendRequest(httpRequest)).thenReturn(response);
urlFetchServiceAzure.sendRequest(httpRequest); urlFetchServiceAzure.sendRequest(httpRequest);
verify(urlFetchService, atMost(4)).sendRequest(httpRequest); verify(urlFetchService, atMost(4)).sendRequest(httpRequest);
} }
@Test @Test
public void shouldNotRetry_ForJSON2_when_storageQueryRecordCallIsMade() throws Exception { public void shouldRetry_ForJSON1_when_schemaRecordCallIsMade() throws Exception {
response.setBody(JSON2); response.setBody(JSON1);
httpRequest.setUrl(url); httpRequest.setUrl(SCHEMA_API_URL);
when(this.retryPolicy.retryConfig(any())).thenReturn(new RetryPolicy().retryConfig(response -> this.retryPolicy.schemaRetryPolicy(response)));
when(urlFetchServiceAzure.sendRequest(httpRequest)).thenReturn(response); when(urlFetchService.sendRequest(httpRequest)).thenReturn(response);
urlFetchServiceAzure.sendRequest(httpRequest); urlFetchServiceAzure.sendRequest(httpRequest);
verify(urlFetchService, atMost(2)).sendRequest(httpRequest);
}
verify(urlFetchService, atMost(4)).sendRequest(httpRequest);
}
@Test @Test
public void retryFunction_shouldNotBeCalled() throws Exception { public void shouldRetry_when_anyOtherCallIsMade() throws Exception {
httpRequest.setUrl(url2); response.setBody(JSON2);
httpRequest.setUrl(STORAGE_API_URL);
when(this.retryPolicy.retryConfig(any())).thenReturn(new RetryPolicy().retryConfig(response -> this.retryPolicy.defaultRetryPolicy(response)));
when(urlFetchService.sendRequest(httpRequest)).thenReturn(response); when(urlFetchService.sendRequest(httpRequest)).thenReturn(response);
urlFetchServiceAzure.sendRequest(httpRequest); urlFetchServiceAzure.sendRequest(httpRequest);
verify(urlFetchService, times(1)).sendRequest(httpRequest);
}
verify(urlFetchService, atMost(4)).sendRequest(httpRequest);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment