Skip to content

Commit

Permalink
Merge pull request #45 from codef-io/develop
Browse files Browse the repository at this point in the history
release: v2.0.0-beta-005
  • Loading branch information
h-beeen authored Nov 29, 2024
2 parents dcbcb9d + 7fec056 commit 721f566
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 203 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<p align="center">
<a href="https://github.com/codef-io/easycodef-java-v2/actions?query=branch%3Amaster"><img align="center" src="https://img.shields.io/github/actions/workflow/status/codef-io/easycodef-java-v2/publish.yml?style=for-the-badge&logo=gradle&color=02303A" alt="Build Status"/></a>
<a href="https://github.com/codef-io/easycodef-java-v2"><img align="center" src="https://img.shields.io/github/last-commit/codef-io/easycodef-java-v2/master?style=for-the-badge&label=LAST%20BUILD&logo=Github&color=181717" alt="Last Commit"/></a>
<a href="https://central.sonatype.com/artifact/io.codef.api/easycodef-java-v2/2.0.0-beta-004"><img align="center" src="https://img.shields.io/maven-central/v/io.codef.api/easycodef-java-v2.svg?style=for-the-badge&label=Maven%20Central&logo=apache-maven&color=C71A36" alt="Maven Central"/></a>
<a href="https://central.sonatype.com/artifact/io.codef.api/easycodef-java-v2/2.0.0-beta-005"><img align="center" src="https://img.shields.io/maven-central/v/io.codef.api/easycodef-java-v2.svg?style=for-the-badge&label=Maven%20Central&logo=apache-maven&color=C71A36" alt="Maven Central"/></a>
</p>

<br><br>
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ plugins {


group = "io.codef.api"
version = "2.0.0-beta-004"
version = "2.0.0-beta-005"

signing {
useInMemoryPgpKeys(
Expand Down
43 changes: 5 additions & 38 deletions src/main/java/io/codef/api/CodefExecutorManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<EasyCodefResponse> scheduleRequest(
EasyCodefRequest request,
long delayMs,
SingleReqFacade facade
) {
return scheduleDelayedExecution(delayMs)
.thenComposeAsync(
ignored -> executeRequest(request, facade),
virtualThreadExecutor
);
}

private CompletableFuture<Void> scheduleDelayedExecution(long delayMs) {
CompletableFuture<Void> future = new CompletableFuture<>();
scheduler.schedule(
() -> future.complete(null),
delayMs,
TimeUnit.MILLISECONDS
);
return future;
Executors.newThreadPerTaskExecutor(Thread.ofVirtual().factory()));
}

private CompletableFuture<EasyCodefResponse> executeRequest(
public CompletableFuture<EasyCodefResponse> executeRequest(
EasyCodefRequest request,
SingleReqFacade facade
) {
Expand All @@ -57,9 +29,4 @@ private CompletableFuture<EasyCodefResponse> executeRequest(
virtualThreadExecutor
);
}

@Override
public void close() {
scheduler.shutdown();
}
}
7 changes: 4 additions & 3 deletions src/main/java/io/codef/api/EasyCodef.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
import io.codef.api.storage.MultipleRequestStorage;
import io.codef.api.storage.SimpleAuthStorage;
import io.codef.api.util.RsaUtil;
import java.security.PublicKey;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.PublicKey;
import java.util.List;

public class EasyCodef {

private static final Logger log = LoggerFactory.getLogger(EasyCodef.class);
Expand Down Expand Up @@ -83,7 +84,7 @@ private void logInitializeSuccessfully() {
| `---.\\ '-' |.-' `) \\ ' ' '--'\\' '-' '\\ `-' \\ --.| .-'\s
`------' `--`--'`----'.-' / `-----' `---' `---' `----'`--' \s
> EasyCodef v2.0.0-beta-004 Successfully Initialized! Hello worlds!
> EasyCodef v2.0.0-beta-005 Successfully Initialized! Hello worlds!
"""
);
}
Expand Down
105 changes: 74 additions & 31 deletions src/main/java/io/codef/api/ResponseHandler.java
Original file line number Diff line number Diff line change
@@ -1,62 +1,83 @@
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
);
}

/**
* 상품 응답 처리
*/
public EasyCodefResponse handleProductResponse(ClassicHttpResponse response) throws CodefException {
public EasyCodefResponse handleProductResponse(ClassicHttpResponse response)
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
);
}

/**
* 공통 HTTP 응답 처리 로직
*/
private <T> T handleHttpResponse(
ClassicHttpResponse response,
Function<String, T> parser,
CodefError unauthorizedError,
CodefError defaultError,
boolean requireUrlDecoding
ClassicHttpResponse response,
Function<String, T> parser,
CodefError unauthorizedError,
CodefError defaultError,
boolean requireUrlDecoding
) throws CodefException {
String responseBody = extractResponseBody(response, requireUrlDecoding);

Expand All @@ -70,7 +91,8 @@ private <T> 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;
Expand Down Expand Up @@ -99,17 +121,38 @@ private EasyCodefResponse parseProductResponse(String responseBody) throws Codef
try {
JSONObject jsonResponse = JSON.parseObject(responseBody);

EasyCodefResponse.Result result = Optional.ofNullable(jsonResponse.getJSONObject(RESULT))
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));
}

Object data = Optional.ofNullable(jsonResponse.getJSONObject(DATA))
private Object parseData(JSONObject jsonResponse) throws CodefException {
try {
return parseObjectData(jsonResponse);
} catch (Exception 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));
}

return new EasyCodefResponse(result, data);
} catch (Exception e) {
throw CodefException.of(CodefError.PARSE_ERROR, e);
}
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));
}
}
101 changes: 101 additions & 0 deletions src/main/java/io/codef/api/ResponseLogger.java
Original file line number Diff line number Diff line change
@@ -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<EasyCodefResponse> 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;
}
}
Loading

0 comments on commit 721f566

Please sign in to comment.