diff --git a/src/main/java/com/uci/utils/BotService.java b/src/main/java/com/uci/utils/BotService.java index 2c36dea..11d37a1 100644 --- a/src/main/java/com/uci/utils/BotService.java +++ b/src/main/java/com/uci/utils/BotService.java @@ -6,26 +6,33 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.inversoft.rest.ClientResponse; import com.uci.utils.bot.util.BotUtil; +import com.uci.utils.common.CommonUtil; import io.fusionauth.client.FusionAuthClient; import io.fusionauth.domain.Application; import io.fusionauth.domain.api.ApplicationResponse; +import io.netty.handler.timeout.ReadTimeoutException; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.util.UriBuilder; import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClientRequest; import java.net.URI; +import java.net.http.HttpTimeoutException; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.TimeoutException; import java.util.function.Function; @SuppressWarnings("ALL") @@ -57,7 +64,7 @@ public Mono getCampaignFromStartingMessage(String startingMessage) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { JsonNode name = root.path("result").path("data").path("name"); return name.asText(); } @@ -70,7 +77,8 @@ public Mono getCampaignFromStartingMessage(String startingMessage) { return ""; } }) - .doOnError(throwable -> log.info("Error in getting campaign: " + throwable.getMessage())) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .doOnError(throwable -> log.error("Error in getting campaign: " + throwable.getMessage())) .onErrorReturn(""); } @@ -85,7 +93,7 @@ public Mono getCurrentAdapter(String botName) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode)) { JsonNode name = root.path("result").path("data"); if (name.has("name") && name.get("name").asText().equals(botName)) { return (((JsonNode) ((ArrayNode) name.path("logic"))).get(0).path("adapter")).asText(); @@ -100,7 +108,8 @@ public Mono getCurrentAdapter(String botName) { } return null; }) - .doOnError(throwable -> log.info("Error in getting adpater: " + throwable.getMessage())) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .doOnError(throwable -> log.error("Error in getting adpater: " + throwable.getMessage())) .onErrorReturn(""); } @@ -123,7 +132,7 @@ public String apply(String response) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { JsonNode name = root.path("result").path("data"); if (name.has("name") && name.get("name").asText().equals(botName)) { return ((JsonNode) ((JsonNode) name.path("id"))).asText(); @@ -140,7 +149,8 @@ public String apply(String response) { return null; } }) - .doOnError(throwable -> log.info("Error in getting bot: " + throwable.getMessage())) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .doOnError(throwable -> log.error("Error in getting bot id from bot name: " + throwable.getMessage())) .onErrorReturn(""); } @@ -230,7 +240,7 @@ public URI apply(UriBuilder builder) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode)) { Boolean status = root.path("result").path("status").asText().equalsIgnoreCase("Success"); String userID = root.path("result").path("userID").asText(); return Pair.of(status, userID); @@ -243,19 +253,10 @@ public URI apply(UriBuilder builder) { return Pair.of(false, ""); } }) - .doOnError(throwable -> log.info("Error in updating user: " + throwable.getMessage())) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .doOnError(throwable -> log.error("Error in updating user: " + throwable.getMessage())) .onErrorReturn(Pair.of(false, "")); } }); } - - /** - * Check if response code sent in api response is ok - * - * @param responseCode - * @return Boolean - */ - private Boolean isApiResponseOk(String responseCode) { - return responseCode.equals("OK"); - } } diff --git a/src/main/java/com/uci/utils/CampaignService.java b/src/main/java/com/uci/utils/CampaignService.java index 856dbb3..a8549d1 100644 --- a/src/main/java/com/uci/utils/CampaignService.java +++ b/src/main/java/com/uci/utils/CampaignService.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.inversoft.rest.ClientResponse; import com.uci.utils.bot.util.BotUtil; +import com.uci.utils.common.CommonUtil; import io.fusionauth.client.FusionAuthClient; import io.fusionauth.domain.Application; @@ -17,8 +18,10 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; +import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; import java.util.function.Function; @SuppressWarnings("ReactiveStreamsUnusedPublisher") @@ -47,7 +50,7 @@ public Mono getCampaignFromID(String campaignID) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { return root.path("result"); } return null; @@ -58,7 +61,10 @@ public Mono getCampaignFromID(String campaignID) { } return null; } - ); + ) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .doOnError(throwable -> log.error("Error in getting campaign: " + throwable.getMessage())) + .onErrorReturn(null); } /** @@ -109,7 +115,7 @@ public JsonNode apply(String response) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { return root.path("result").path("data").get(0); }else{ log.error("API response not okay"); @@ -124,7 +130,9 @@ public JsonNode apply(String response) { return null; } } - ).doOnError(throwable -> { + ) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .doOnError(throwable -> { log.error("Error in fetching Campaign Information from Name when invoked by transformer >>> " + throwable.getMessage()); }).onErrorReturn(null); @@ -150,7 +158,7 @@ public String apply(String response) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { return root.path("result").findValue("formID").asText(); } return null; @@ -162,7 +170,9 @@ public String apply(String response) { return null; } } - ).onErrorReturn(null).doOnError(throwable -> log.error("Error in getFirstFormByBotID >>> " + throwable.getMessage())); + ) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .onErrorReturn(null).doOnError(throwable -> log.error("Error in getting first form by bot id >>> " + throwable.getMessage())); } public Mono getBotNameByBotID(String botID) { @@ -178,7 +188,7 @@ public String apply(String response) { try { JsonNode root = mapper.readTree(response); String responseCode = root.path("responseCode").asText(); - if(isApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { + if(CommonUtil.isWebClientApiResponseOk(responseCode) && BotUtil.checkBotValidFromJsonNode(root)) { return root.path("result").get("data").get("name").asText(); } return null; @@ -190,7 +200,9 @@ public String apply(String response) { return null; } } - ).onErrorReturn(null).doOnError(throwable -> log.error("Error in getFirstFormByBotID >>> " + throwable.getMessage())); + ) + .timeout(CommonUtil.getWebClientTimeoutDuration()) + .onErrorReturn(null).doOnError(throwable -> log.error("Error in getting bot name from bot id >>> " + throwable.getMessage())); } @@ -251,16 +263,6 @@ public Application getCampaignFromNameESamwad(String campaignName) { } } return currentApplication; - } - - /** - * Check if response code sent in api response is ok - * - * @param responseCode - * @return Boolean - */ - private Boolean isApiResponseOk(String responseCode) { - return responseCode.equals("OK"); - } + } } diff --git a/src/main/java/com/uci/utils/UtilAppConfiguration.java b/src/main/java/com/uci/utils/UtilAppConfiguration.java index 8daf17d..72fef9c 100644 --- a/src/main/java/com/uci/utils/UtilAppConfiguration.java +++ b/src/main/java/com/uci/utils/UtilAppConfiguration.java @@ -1,11 +1,16 @@ package com.uci.utils; +import java.time.Duration; + import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.http.client.HttpClient; + @Configuration @EnableAutoConfiguration @@ -20,7 +25,10 @@ public class UtilAppConfiguration { @Bean public WebClient getWebClient() { +// HttpClient httpClient = HttpClient.create() +// .responseTimeout(Duration.ofSeconds(1)); return WebClient.builder() +// .clientConnector(new ReactorClientHttpConnector(httpClient)) .baseUrl(CAMPAIGN_URL) .defaultHeader("admin-token", CAMPAIGN_ADMIN_TOKEN) .build(); diff --git a/src/main/java/com/uci/utils/common/CommonUtil.java b/src/main/java/com/uci/utils/common/CommonUtil.java new file mode 100644 index 0000000..3c97d09 --- /dev/null +++ b/src/main/java/com/uci/utils/common/CommonUtil.java @@ -0,0 +1,43 @@ +package com.uci.utils.common; + +import java.time.Duration; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class CommonUtil { + + + /** + * Check if response code sent in api response is ok + * + * @param responseCode + * @return Boolean + */ + public static Boolean isWebClientApiResponseOk(String responseCode) { + return responseCode.equals("OK"); + } + + /** + * Get Timeout Duration for Web Client + * @return Duration + */ + public static Duration getWebClientTimeoutDuration() { + return Duration.ofSeconds(getWebClientTimeoutSeconds()); + } + + /** + * Get Timeout in seconds from env variables, default value 5 + * @return Long + */ + public static Long getWebClientTimeoutSeconds() { + Long timeout = null; + try { + timeout = Long.parseLong(System.getenv("WEBCLIENT_HTTP_REQUEST_TIMEOUT")); + } catch (Exception e) { + log.error("Exception in conversion of webclient http request timeout."); + } + + return timeout != null ? timeout : 5; + } +}