From 2f5d97b99fb4f99d2ac9b19581ee0bf45442d65a Mon Sep 17 00:00:00 2001 From: h-beeen Date: Wed, 27 Nov 2024 16:16:29 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20Codef=20API=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=91=EB=8B=B5=20=EA=B0=9D=EC=B2=B4=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=20=EC=98=A4=EB=A5=98=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/codef/api/CodefExecutorManager.java | 43 ++------------- .../java/io/codef/api/ResponseHandler.java | 48 ++++++++++++---- .../codef/api/facade/MultipleReqFacade.java | 55 +++++++++++-------- .../api/facade/SimpleAuthCertFacade.java | 2 +- .../api/storage/MultipleRequestStorage.java | 5 +- .../codef/api/storage/SimpleAuthStorage.java | 8 +-- 6 files changed, 81 insertions(+), 80 deletions(-) diff --git a/src/main/java/io/codef/api/CodefExecutorManager.java b/src/main/java/io/codef/api/CodefExecutorManager.java index 5ac77ce..5a83736 100644 --- a/src/main/java/io/codef/api/CodefExecutorManager.java +++ b/src/main/java/io/codef/api/CodefExecutorManager.java @@ -6,49 +6,21 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -// 실행기 관리를 위한 클래스 -public class CodefExecutorManager implements AutoCloseable { - private final ScheduledExecutorService scheduler; +public class CodefExecutorManager { + private final Executor virtualThreadExecutor; - private CodefExecutorManager(ScheduledExecutorService scheduler, Executor virtualThreadExecutor) { - this.scheduler = scheduler; + private CodefExecutorManager(Executor virtualThreadExecutor) { this.virtualThreadExecutor = virtualThreadExecutor; } public static CodefExecutorManager create() { return new CodefExecutorManager( - Executors.newScheduledThreadPool(1), - Executors.newThreadPerTaskExecutor(Thread.ofVirtual().factory()) - ); - } - - public CompletableFuture scheduleRequest( - EasyCodefRequest request, - long delayMs, - SingleReqFacade facade - ) { - return scheduleDelayedExecution(delayMs) - .thenComposeAsync( - ignored -> executeRequest(request, facade), - virtualThreadExecutor - ); - } - - private CompletableFuture scheduleDelayedExecution(long delayMs) { - CompletableFuture future = new CompletableFuture<>(); - scheduler.schedule( - () -> future.complete(null), - delayMs, - TimeUnit.MILLISECONDS - ); - return future; + Executors.newThreadPerTaskExecutor(Thread.ofVirtual().factory())); } - private CompletableFuture executeRequest( + public CompletableFuture executeRequest( EasyCodefRequest request, SingleReqFacade facade ) { @@ -57,9 +29,4 @@ private CompletableFuture executeRequest( virtualThreadExecutor ); } - - @Override - public void close() { - scheduler.shutdown(); - } } \ No newline at end of file diff --git a/src/main/java/io/codef/api/ResponseHandler.java b/src/main/java/io/codef/api/ResponseHandler.java index a65fec0..d830fb7 100644 --- a/src/main/java/io/codef/api/ResponseHandler.java +++ b/src/main/java/io/codef/api/ResponseHandler.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.util.List; import java.util.Optional; import java.util.function.Function; import org.apache.hc.core5.http.ClassicHttpResponse; @@ -20,6 +21,7 @@ import org.apache.hc.core5.http.io.entity.EntityUtils; public class ResponseHandler { + private static final String UTF_8 = StandardCharsets.UTF_8.toString(); /** @@ -38,7 +40,8 @@ public String handleTokenResponse(ClassicHttpResponse response) throws CodefExce /** * 상품 응답 처리 */ - public EasyCodefResponse handleProductResponse(ClassicHttpResponse response) throws CodefException { + public EasyCodefResponse handleProductResponse(ClassicHttpResponse response) + throws CodefException { return handleHttpResponse( response, this::parseProductResponse, @@ -62,7 +65,8 @@ private T handleHttpResponse( return switch (response.getCode()) { case HttpStatus.SC_OK -> parser.apply(responseBody); - case HttpStatus.SC_UNAUTHORIZED -> throw CodefException.of(unauthorizedError, responseBody); + case HttpStatus.SC_UNAUTHORIZED -> + throw CodefException.of(unauthorizedError, responseBody); default -> throw CodefException.of(defaultError, responseBody); }; } @@ -70,7 +74,8 @@ private T handleHttpResponse( /** * HTTP 응답 본문 추출 */ - private String extractResponseBody(ClassicHttpResponse response, boolean requiresDecoding) throws CodefException { + private String extractResponseBody(ClassicHttpResponse response, boolean requiresDecoding) + throws CodefException { try { String responseBody = EntityUtils.toString(response.getEntity()); return requiresDecoding ? URLDecoder.decode(responseBody, UTF_8) : responseBody; @@ -99,17 +104,38 @@ private EasyCodefResponse parseProductResponse(String responseBody) throws Codef try { JSONObject jsonResponse = JSON.parseObject(responseBody); - EasyCodefResponse.Result result = Optional.ofNullable(jsonResponse.getJSONObject(RESULT)) - .map(object -> object.to(EasyCodefResponse.Result.class)) - .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); - - Object data = Optional.ofNullable(jsonResponse.getJSONObject(DATA)) - .map(obj -> obj.to(Object.class)) - .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); + EasyCodefResponse.Result result = parseResult(jsonResponse); + Object data = parseData(jsonResponse); return new EasyCodefResponse(result, data); + } catch (Exception exception) { + throw CodefException.of(CodefError.PARSE_ERROR, exception); + } + } + + private EasyCodefResponse.Result parseResult(JSONObject jsonResponse) throws CodefException { + return Optional.ofNullable(jsonResponse.getJSONObject(RESULT)) + .map(object -> object.to(EasyCodefResponse.Result.class)) + .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); + } + + private Object parseData(JSONObject jsonResponse) throws CodefException { + try { + return parseObjectData(jsonResponse); } catch (Exception e) { - throw CodefException.of(CodefError.PARSE_ERROR, e); + return parseArrayData(jsonResponse); } } + + private Object parseObjectData(JSONObject jsonResponse) throws CodefException { + return Optional.ofNullable(jsonResponse.getJSONObject(DATA)) + .map(obj -> obj.to(Object.class)) + .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); + } + + private List parseArrayData(JSONObject jsonResponse) throws CodefException { + return Optional.ofNullable(jsonResponse.getJSONArray(DATA)) + .map(obj -> obj.to(List.class)) + .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); + } } \ No newline at end of file diff --git a/src/main/java/io/codef/api/facade/MultipleReqFacade.java b/src/main/java/io/codef/api/facade/MultipleReqFacade.java index 91ad38d..0b05527 100644 --- a/src/main/java/io/codef/api/facade/MultipleReqFacade.java +++ b/src/main/java/io/codef/api/facade/MultipleReqFacade.java @@ -12,11 +12,13 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; // 다중 요청 처리기 public class MultipleReqFacade { - private static final long REQUEST_DELAY_MS = 700L; + + private static final long REQUEST_DELAY_INTERVAL = 700L; private final SingleReqFacade singleReqFacade; private final MultipleRequestStorage multipleRequestStorage; @@ -37,19 +39,38 @@ public EasyCodefResponse requestMultipleProduct(List requests) validateRequests(requests); assignSsoId(requests, UUID.randomUUID().toString()); - try { - List> futures = scheduleRequests(requests); + List> futures = scheduleRequests(requests); + + CompletableFuture firstCompleted = + CompletableFuture.anyOf(futures.toArray(new CompletableFuture[0])) + .thenApply(result -> (EasyCodefResponse) result); + + EasyCodefResponse result = firstCompleted.join(); + multipleRequestStorage.store(result.transactionId(), futures); + + return result; + } - CompletableFuture firstCompleted = - CompletableFuture.anyOf(futures.toArray(new CompletableFuture[0])) - .thenApply(result -> (EasyCodefResponse) result); - EasyCodefResponse result = firstCompleted.join(); - multipleRequestStorage.store(result.transactionId(), futures); + private List> scheduleRequests( + List requests + ) { + return IntStream.range(0, requests.size()) + .mapToObj(i -> { + applyDelay(i); + return executorManager.executeRequest(requests.get(i), singleReqFacade); + }) + .toList(); + } - return result; - } finally { - executorManager.close(); + private void applyDelay(int index) { + if (index > 0) { + try { + TimeUnit.MILLISECONDS.sleep(index * REQUEST_DELAY_INTERVAL); + } catch (InterruptedException exception) { + Thread.currentThread().interrupt(); + throw CodefException.of(CodefError.IO_ERROR, exception); + } } } @@ -61,16 +82,4 @@ private void validateRequests(List requests) { private void assignSsoId(List requests, String uuid) { requests.forEach(request -> request.requestBody().put(SSO_ID, uuid)); } - - private List> scheduleRequests( - List requests - ) { - return IntStream.range(0, requests.size()) - .mapToObj(i -> executorManager.scheduleRequest( - requests.get(i), - i * REQUEST_DELAY_MS, - singleReqFacade - )) - .toList(); - } } diff --git a/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java b/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java index e4e6253..d897586 100644 --- a/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java +++ b/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java @@ -140,7 +140,7 @@ private List combineWithRemainingResponses(EasyCodefResponse log.info("Success Response Status [CF-00000] Count : {}", successCount); log.info("AddAuth Response Status [CF-03002] Count : {}", addAuthCount); - log.warn("Failure Response Status [ Else ] Count : {}", failureCount); + log.warn("Failure Response Status [ Else ] Count : {}\n", failureCount); if (failureCount > 0) { responses.stream() diff --git a/src/main/java/io/codef/api/storage/MultipleRequestStorage.java b/src/main/java/io/codef/api/storage/MultipleRequestStorage.java index 069b14b..94f8d62 100644 --- a/src/main/java/io/codef/api/storage/MultipleRequestStorage.java +++ b/src/main/java/io/codef/api/storage/MultipleRequestStorage.java @@ -5,16 +5,15 @@ import io.codef.api.error.CodefError; import io.codef.api.error.CodefException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class MultipleRequestStorage { - private final Map>> storage = new HashMap<>(); + private final ConcurrentHashMap>> storage = new ConcurrentHashMap<>(); public List getRemainingResponses( String transactionId diff --git a/src/main/java/io/codef/api/storage/SimpleAuthStorage.java b/src/main/java/io/codef/api/storage/SimpleAuthStorage.java index edaaf9e..3a767dc 100644 --- a/src/main/java/io/codef/api/storage/SimpleAuthStorage.java +++ b/src/main/java/io/codef/api/storage/SimpleAuthStorage.java @@ -6,13 +6,12 @@ import io.codef.api.error.CodefError; import io.codef.api.error.CodefException; import io.codef.api.vo.CodefSimpleAuth; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; public class SimpleAuthStorage { - private final Map storage = new HashMap<>(); + private final ConcurrentHashMap storage = new ConcurrentHashMap<>(); public void storeIfRequired( EasyCodefRequest request, @@ -35,7 +34,8 @@ public CodefSimpleAuth get(String transactionId) throws CodefException { public void updateIfRequired( String path, EasyCodefRequest request, - EasyCodefResponse response, String transactionId + EasyCodefResponse response, + String transactionId ) { Optional.ofNullable(response.code()) .filter(code -> code.equals(CodefResponseCode.CF_03002)) From 3f78c0688831baa8cfa4b9522ef41cc870a69b27 Mon Sep 17 00:00:00 2001 From: h-beeen Date: Wed, 27 Nov 2024 16:21:01 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B0=8F=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java b/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java index d897586..669576e 100644 --- a/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java +++ b/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java @@ -64,7 +64,6 @@ public List requestMultipleSimpleAuthCertification( private void logAddAuthResponseStatus( EasyCodefResponse response, - String transactionId, String resultStatusCode ) { if (resultStatusCode.equals(CF_03002)) { @@ -92,7 +91,7 @@ private void logResponseStatus( String resultStatusCode = response.code(); logDefaultResponseStatus(transactionId, resultStatusCode); - logAddAuthResponseStatus(response, transactionId, resultStatusCode); + logAddAuthResponseStatus(response, resultStatusCode); } private List returnFirstResponse(EasyCodefResponse firstErrorResponse) { @@ -131,7 +130,6 @@ private List combineWithRemainingResponses(EasyCodefResponse log.info("Await Responses Count = {}", responses.size()); responses.add(firstResponse); - List allResponseCodes = responses.stream().map(EasyCodefResponse::code).toList(); log.info("Total Responses Count = {}\n", responses.size()); long successCount = responses.stream().filter(this::isSuccessResponse).count(); From a397876b1517dd543e158af5ff0949928b2dfae3 Mon Sep 17 00:00:00 2001 From: h-beeen Date: Fri, 29 Nov 2024 11:24:11 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B9=85=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/codef/api/ResponseHandler.java | 83 ++++++++----- .../java/io/codef/api/ResponseLogger.java | 101 +++++++++++++++ .../api/facade/SimpleAuthCertFacade.java | 117 ++++-------------- .../io/codef/api/facade/SingleReqFacade.java | 4 +- .../api/storage/MultipleRequestStorage.java | 8 ++ .../codef/api/storage/SimpleAuthStorage.java | 8 +- 6 files changed, 189 insertions(+), 132 deletions(-) create mode 100644 src/main/java/io/codef/api/ResponseLogger.java diff --git a/src/main/java/io/codef/api/ResponseHandler.java b/src/main/java/io/codef/api/ResponseHandler.java index d830fb7..be176a1 100644 --- a/src/main/java/io/codef/api/ResponseHandler.java +++ b/src/main/java/io/codef/api/ResponseHandler.java @@ -1,39 +1,57 @@ package io.codef.api; -import static io.codef.api.dto.EasyCodefRequest.ACCESS_TOKEN; -import static io.codef.api.dto.EasyCodefResponse.DATA; -import static io.codef.api.dto.EasyCodefResponse.RESULT; - import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import io.codef.api.constants.CodefResponseCode; import io.codef.api.dto.EasyCodefResponse; import io.codef.api.error.CodefError; import io.codef.api.error.CodefException; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.EntityUtils; + import java.io.IOException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Optional; import java.util.function.Function; -import org.apache.hc.core5.http.ClassicHttpResponse; -import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.ParseException; -import org.apache.hc.core5.http.io.entity.EntityUtils; + +import static io.codef.api.dto.EasyCodefRequest.ACCESS_TOKEN; +import static io.codef.api.dto.EasyCodefResponse.DATA; +import static io.codef.api.dto.EasyCodefResponse.RESULT; public class ResponseHandler { private static final String UTF_8 = StandardCharsets.UTF_8.toString(); + public static boolean isSuccessResponse(EasyCodefResponse response) { + return CodefResponseCode.CF_00000.equals(response.code()); + } + + public static boolean isAddAuthResponse(EasyCodefResponse response) { + return CodefResponseCode.CF_03002.equals(response.code()); + } + + public static boolean isAddAuthExceedResponse(EasyCodefResponse response) { + return CodefResponseCode.CF_12872.equals(response.code()); + } + + public static boolean isFailureResponse(EasyCodefResponse response) { + return !isSuccessResponse(response) && !isAddAuthResponse(response); + } + /** * 토큰 응답 처리 */ public String handleTokenResponse(ClassicHttpResponse response) throws CodefException { return handleHttpResponse( - response, - this::parseAccessToken, - CodefError.OAUTH_UNAUTHORIZED, - CodefError.OAUTH_INTERNAL_ERROR, - false + response, + this::parseAccessToken, + CodefError.OAUTH_UNAUTHORIZED, + CodefError.OAUTH_INTERNAL_ERROR, + false ); } @@ -41,13 +59,13 @@ public String handleTokenResponse(ClassicHttpResponse response) throws CodefExce * 상품 응답 처리 */ public EasyCodefResponse handleProductResponse(ClassicHttpResponse response) - throws CodefException { + throws CodefException { return handleHttpResponse( - response, - this::parseProductResponse, - CodefError.CODEF_API_UNAUTHORIZED, - CodefError.CODEF_API_SERVER_ERROR, - true + response, + this::parseProductResponse, + CodefError.CODEF_API_UNAUTHORIZED, + CodefError.CODEF_API_SERVER_ERROR, + true ); } @@ -55,18 +73,17 @@ public EasyCodefResponse handleProductResponse(ClassicHttpResponse response) * 공통 HTTP 응답 처리 로직 */ private T handleHttpResponse( - ClassicHttpResponse response, - Function parser, - CodefError unauthorizedError, - CodefError defaultError, - boolean requireUrlDecoding + ClassicHttpResponse response, + Function parser, + CodefError unauthorizedError, + CodefError defaultError, + boolean requireUrlDecoding ) throws CodefException { String responseBody = extractResponseBody(response, requireUrlDecoding); return switch (response.getCode()) { case HttpStatus.SC_OK -> parser.apply(responseBody); - case HttpStatus.SC_UNAUTHORIZED -> - throw CodefException.of(unauthorizedError, responseBody); + case HttpStatus.SC_UNAUTHORIZED -> throw CodefException.of(unauthorizedError, responseBody); default -> throw CodefException.of(defaultError, responseBody); }; } @@ -75,7 +92,7 @@ private T handleHttpResponse( * HTTP 응답 본문 추출 */ private String extractResponseBody(ClassicHttpResponse response, boolean requiresDecoding) - throws CodefException { + throws CodefException { try { String responseBody = EntityUtils.toString(response.getEntity()); return requiresDecoding ? URLDecoder.decode(responseBody, UTF_8) : responseBody; @@ -115,8 +132,8 @@ private EasyCodefResponse parseProductResponse(String responseBody) throws Codef private EasyCodefResponse.Result parseResult(JSONObject jsonResponse) throws CodefException { return Optional.ofNullable(jsonResponse.getJSONObject(RESULT)) - .map(object -> object.to(EasyCodefResponse.Result.class)) - .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); + .map(object -> object.to(EasyCodefResponse.Result.class)) + .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); } private Object parseData(JSONObject jsonResponse) throws CodefException { @@ -129,13 +146,13 @@ private Object parseData(JSONObject jsonResponse) throws CodefException { private Object parseObjectData(JSONObject jsonResponse) throws CodefException { return Optional.ofNullable(jsonResponse.getJSONObject(DATA)) - .map(obj -> obj.to(Object.class)) - .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); + .map(obj -> obj.to(Object.class)) + .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); } private List parseArrayData(JSONObject jsonResponse) throws CodefException { return Optional.ofNullable(jsonResponse.getJSONArray(DATA)) - .map(obj -> obj.to(List.class)) - .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); + .map(obj -> obj.to(List.class)) + .orElseThrow(() -> CodefException.from(CodefError.PARSE_ERROR)); } } \ No newline at end of file diff --git a/src/main/java/io/codef/api/ResponseLogger.java b/src/main/java/io/codef/api/ResponseLogger.java new file mode 100644 index 0000000..c4c7718 --- /dev/null +++ b/src/main/java/io/codef/api/ResponseLogger.java @@ -0,0 +1,101 @@ +package io.codef.api; + +import com.alibaba.fastjson2.JSON; +import io.codef.api.dto.EasyCodefResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Optional; + +import static io.codef.api.constants.CodefResponseCode.*; + +public class ResponseLogger { + private static final Logger log = LoggerFactory.getLogger(ResponseLogger.class); + + private ResponseLogger() { + } + + + public static void logResponseStatus(EasyCodefResponse response) { + logBasicInfo(response); + + switch (response.code()) { + case CF_00000: + logSuccessResponse(); + break; + + case CF_03002: + logAddAuthRequired(response); + break; + + case CF_12872: + logAuthExceeded(); + break; + + default: + logError(response); + break; + } + } + + public static void logStatusSummary(List responses) { + long successCount = responses.stream().filter(ResponseHandler::isSuccessResponse).count(); + long addAuthCount = responses.stream().filter(ResponseHandler::isAddAuthResponse).count(); + long failureCount = responses.stream().filter(ResponseHandler::isFailureResponse).count(); + + log.info("Total Responses Count = {}\n", responses.size()); + logStatus(successCount, addAuthCount, failureCount); + } + + private static void logBasicInfo(EasyCodefResponse response) { + log.info("Response Status Code : {}", response.code()); + log.info("Transaction Id : {}", response.transactionId()); + } + + private static void logSuccessResponse() { + log.info("Successfully returned Value from Codef API\n"); + } + + private static void logAddAuthRequired(EasyCodefResponse response) { + Object data = response.data(); + String addAuthMethod = JSON.parseObject(data.toString()).getString("method"); + log.warn("Additional authentication required | method : {}\n", addAuthMethod); + } + + private static void logAuthExceeded() { + log.error("Retry limit for additional authentication exceeded. " + + "Please restart the process from the initial request.\n"); + } + + private static void logError(EasyCodefResponse response) { + log.error("Failed to get proper scrapping response. Check the Error errorMessage And StatusCode"); + log.error("> message : {}", response.result().message()); + log.error("> extraMessage : {}", response.result().extraMessage()); + } + + private static void logStatus( + long successCount, + long addAuthCount, + long failureCount + ) { + Optional.of(successCount) + .filter(ResponseLogger::isExist) + .ifPresent(count -> log.info("Success Response Status [ {} ] Count : {}", CF_00000, count)); + + Optional.of(addAuthCount) + .filter(ResponseLogger::isExist) + .ifPresent(count -> log.info("AddAuth Response Status [ {} ] Count : {}", CF_03002, count)); + + Optional.of(failureCount) + .filter(ResponseLogger::isExist) + .ifPresentOrElse( + count -> log.warn("Failure Response Status [ Else ] Count : {}\n", count), + () -> log.info("No Failure Responses\n") + ); + } + + private static boolean isExist(Long count) { + return count > 0; + } +} diff --git a/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java b/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java index 669576e..775218f 100644 --- a/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java +++ b/src/main/java/io/codef/api/facade/SimpleAuthCertFacade.java @@ -1,23 +1,21 @@ package io.codef.api.facade; -import static io.codef.api.constants.CodefResponseCode.CF_03002; -import static io.codef.api.constants.CodefResponseCode.CF_12872; -import static io.codef.api.dto.EasyCodefRequest.TRUE; - -import com.alibaba.fastjson2.JSON; -import io.codef.api.constants.CodefResponseCode; +import io.codef.api.ResponseHandler; +import io.codef.api.ResponseLogger; import io.codef.api.dto.EasyCodefRequest; import io.codef.api.dto.EasyCodefResponse; import io.codef.api.error.CodefException; import io.codef.api.storage.MultipleRequestStorage; import io.codef.api.storage.SimpleAuthStorage; import io.codef.api.vo.CodefSimpleAuth; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; +import java.util.Map; + +import static io.codef.api.dto.EasyCodefRequest.TRUE; + public class SimpleAuthCertFacade { private static final Logger log = LoggerFactory.getLogger(SimpleAuthCertFacade.class); @@ -26,90 +24,38 @@ public class SimpleAuthCertFacade { private final SimpleAuthStorage simpleAuthStorage; private final MultipleRequestStorage multipleRequestStorage; - public SimpleAuthCertFacade( - SingleReqFacade singleReqFacade, - SimpleAuthStorage simpleAuthStorage, - MultipleRequestStorage multipleRequestStorage - ) { + public SimpleAuthCertFacade(SingleReqFacade singleReqFacade, + SimpleAuthStorage simpleAuthStorage, MultipleRequestStorage multipleRequestStorage) { this.singleReqFacade = singleReqFacade; this.simpleAuthStorage = simpleAuthStorage; this.multipleRequestStorage = multipleRequestStorage; } - public EasyCodefResponse requestSimpleAuthCertification(String transactionId) throws CodefException { + public EasyCodefResponse requestSimpleAuthCertification(String transactionId) + throws CodefException { CodefSimpleAuth simpleAuth = simpleAuthStorage.get(transactionId); EasyCodefRequest enrichedRequest = enrichRequestWithTwoWayInfo(simpleAuth); EasyCodefResponse response = singleReqFacade.requestProduct(enrichedRequest); - simpleAuthStorage.updateIfRequired( - simpleAuth.requestUrl(), - enrichedRequest, - response, - transactionId - ); + simpleAuthStorage.updateIfRequired(simpleAuth.requestUrl(), enrichedRequest, response); - logResponseStatus(response, transactionId); + ResponseLogger.logResponseStatus(response); return response; } - public List requestMultipleSimpleAuthCertification( - String transactionId - ) throws CodefException { + public List requestMultipleSimpleAuthCertification(String transactionId) + throws CodefException { EasyCodefResponse firstResponse = requestSimpleAuthCertification(transactionId); - return isSuccessResponse(firstResponse) + return ResponseHandler.isSuccessResponse(firstResponse) ? combineWithRemainingResponses(firstResponse, transactionId) : returnFirstResponse(firstResponse); } - private void logAddAuthResponseStatus( - EasyCodefResponse response, - String resultStatusCode - ) { - if (resultStatusCode.equals(CF_03002)) { - Object data = response.data(); - String addAuthMethod = JSON.parseObject(data.toString()).getString("method"); - - log.warn("Additional authentication required | method : {}\n", addAuthMethod); - } else if (resultStatusCode.equals(CF_12872)) { - log.warn( - "Retry limit for additional authentication exceeded. " - + "Please restart the process from the initial request.\n" - ); - } - } - - private void logDefaultResponseStatus(String transactionId, String resultStatusCode) { - log.info("Result Status Code : {}", resultStatusCode); - log.info("Transaction Id : {}", transactionId); - } - - private void logResponseStatus( - EasyCodefResponse response, - String transactionId - ) { - String resultStatusCode = response.code(); - logDefaultResponseStatus(transactionId, resultStatusCode); - - logAddAuthResponseStatus(response, resultStatusCode); - } - private List returnFirstResponse(EasyCodefResponse firstErrorResponse) { return List.of(firstErrorResponse); } - private boolean isSuccessResponse(EasyCodefResponse response) { - return CodefResponseCode.CF_00000.equals(response.code()); - } - - private boolean isAddAuthResponse(EasyCodefResponse response) { - return CodefResponseCode.CF_03002.equals(response.code()); - } - - private boolean isFailureResponse(EasyCodefResponse response) { - return !isSuccessResponse(response) && !isAddAuthResponse(response); - } - private EasyCodefRequest enrichRequestWithTwoWayInfo(CodefSimpleAuth simpleAuth) { EasyCodefRequest request = simpleAuth.request(); Map body = request.requestBody(); @@ -121,32 +67,13 @@ private EasyCodefRequest enrichRequestWithTwoWayInfo(CodefSimpleAuth simpleAuth) return request; } - private List combineWithRemainingResponses(EasyCodefResponse firstResponse, - String transactionId) throws CodefException { - - log.info("Await Responses called By transactionId `{}`", transactionId); - List responses = multipleRequestStorage.getRemainingResponses( - transactionId); - log.info("Await Responses Count = {}", responses.size()); - + private List combineWithRemainingResponses( + EasyCodefResponse firstResponse, + String transactionId + ) throws CodefException { + List responses = multipleRequestStorage.getRemainingResponses(transactionId); responses.add(firstResponse); - log.info("Total Responses Count = {}\n", responses.size()); - - long successCount = responses.stream().filter(this::isSuccessResponse).count(); - long addAuthCount = responses.stream().filter(this::isAddAuthResponse).count(); - long failureCount = responses.stream().filter(this::isFailureResponse).count(); - - log.info("Success Response Status [CF-00000] Count : {}", successCount); - log.info("AddAuth Response Status [CF-03002] Count : {}", addAuthCount); - log.warn("Failure Response Status [ Else ] Count : {}\n", failureCount); - - if (failureCount > 0) { - responses.stream() - .filter(this::isFailureResponse) - .map(EasyCodefResponse::code) - .collect(Collectors.groupingBy(code -> code, Collectors.counting())) - .forEach((code, count) -> log.warn("> Error code : {}, Count: {}", code, count)); - } + ResponseLogger.logStatusSummary(responses); return responses; } diff --git a/src/main/java/io/codef/api/facade/SingleReqFacade.java b/src/main/java/io/codef/api/facade/SingleReqFacade.java index c0d1ebf..007802d 100644 --- a/src/main/java/io/codef/api/facade/SingleReqFacade.java +++ b/src/main/java/io/codef/api/facade/SingleReqFacade.java @@ -2,6 +2,7 @@ import io.codef.api.EasyCodefConnector; import io.codef.api.EasyCodefToken; +import io.codef.api.ResponseLogger; import io.codef.api.constants.CodefClientType; import io.codef.api.dto.EasyCodefRequest; import io.codef.api.dto.EasyCodefResponse; @@ -31,7 +32,8 @@ public EasyCodefResponse requestProduct(EasyCodefRequest request) throws CodefEx EasyCodefResponse response = EasyCodefConnector.requestProduct(request, validToken, requestUrl); - simpleAuthStorage.storeIfRequired(request, response, requestUrl); + simpleAuthStorage.storeIfAddAuthResponse(request, response, requestUrl); + ResponseLogger.logResponseStatus(response); return response; } diff --git a/src/main/java/io/codef/api/storage/MultipleRequestStorage.java b/src/main/java/io/codef/api/storage/MultipleRequestStorage.java index 94f8d62..c3aa144 100644 --- a/src/main/java/io/codef/api/storage/MultipleRequestStorage.java +++ b/src/main/java/io/codef/api/storage/MultipleRequestStorage.java @@ -4,6 +4,9 @@ import io.codef.api.dto.EasyCodefResponse; import io.codef.api.error.CodefError; import io.codef.api.error.CodefException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -13,11 +16,14 @@ public class MultipleRequestStorage { + private static final Logger log = LoggerFactory.getLogger(MultipleRequestStorage.class); private final ConcurrentHashMap>> storage = new ConcurrentHashMap<>(); public List getRemainingResponses( String transactionId ) throws CodefException { + log.info("Await Responses called By transactionId `{}`", transactionId); + final List> futures = storage.get(transactionId); CodefValidator.requireNonNullElseThrow(futures, CodefError.SIMPLE_AUTH_FAILED); @@ -34,6 +40,8 @@ public List getRemainingResponses( .collect(Collectors.toCollection(ArrayList::new)); storage.remove(transactionId); + + log.info("Await Responses Count = {}", results.size()); return results; } catch (Exception e) { throw CodefException.from(CodefError.SIMPLE_AUTH_FAILED); diff --git a/src/main/java/io/codef/api/storage/SimpleAuthStorage.java b/src/main/java/io/codef/api/storage/SimpleAuthStorage.java index 3a767dc..e297653 100644 --- a/src/main/java/io/codef/api/storage/SimpleAuthStorage.java +++ b/src/main/java/io/codef/api/storage/SimpleAuthStorage.java @@ -6,6 +6,7 @@ import io.codef.api.error.CodefError; import io.codef.api.error.CodefException; import io.codef.api.vo.CodefSimpleAuth; + import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -13,7 +14,7 @@ public class SimpleAuthStorage { private final ConcurrentHashMap storage = new ConcurrentHashMap<>(); - public void storeIfRequired( + public void storeIfAddAuthResponse( EasyCodefRequest request, EasyCodefResponse response, String requestUrl @@ -34,9 +35,10 @@ public CodefSimpleAuth get(String transactionId) throws CodefException { public void updateIfRequired( String path, EasyCodefRequest request, - EasyCodefResponse response, - String transactionId + EasyCodefResponse response ) { + String transactionId = response.transactionId(); + Optional.ofNullable(response.code()) .filter(code -> code.equals(CodefResponseCode.CF_03002)) .ifPresentOrElse(