diff --git a/src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java b/src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java index 25227bb3..b4e5ccb1 100644 --- a/src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java +++ b/src/main/java/com/interplug/qcast/batch/master/MaterialConfiguration.java @@ -4,8 +4,11 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.interplug.qcast.biz.displayItem.DisplayItemService; import com.interplug.qcast.biz.displayItem.dto.ItemSyncResponse; import com.interplug.qcast.util.InterfaceQsp; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecutionListener; import org.springframework.batch.core.Step; @@ -34,6 +37,9 @@ public class MaterialConfiguration implements JobExecutionListener { @Value("${qsp.master-material-batch-url}") private String qspInterfaceUrl; + @Value("${qsp.master-material-batch-page-size:1000}") + private int pageSize; + public MaterialConfiguration(DisplayItemService displayItemService, InterfaceQsp interfaceQsp) { this.displayItemService = displayItemService; this.interfaceQsp = interfaceQsp; @@ -58,12 +64,32 @@ public class MaterialConfiguration implements JobExecutionListener { @Bean @StepScope public ListItemReader materialReader() throws Exception { - this.itemSyncList = - interfaceQsp.callApiData( - HttpMethod.GET, - qspInterfaceUrl + "?allYn=N", - null, - new TypeReference>() {}); + List aggregated = new ArrayList<>(); + int page = 1; + while (true) { + Map params = new HashMap<>(); + params.put("allYn", "N"); + params.put("page", page); + params.put("size", pageSize); + + List pageItems = + interfaceQsp.callApiData( + HttpMethod.GET, + qspInterfaceUrl, + params, + new TypeReference>() {}); + + if (pageItems == null || pageItems.isEmpty()) { + break; + } + + aggregated.addAll(pageItems); + if (pageItems.size() < pageSize) { + break; + } + page++; + } + this.itemSyncList = aggregated; return (itemSyncList != null) ? new ListItemReader<>(itemSyncList) : new ListItemReader<>(Collections.emptyList()); diff --git a/src/main/java/com/interplug/qcast/util/InterfaceQsp.java b/src/main/java/com/interplug/qcast/util/InterfaceQsp.java index ce6a40a1..f813a461 100644 --- a/src/main/java/com/interplug/qcast/util/InterfaceQsp.java +++ b/src/main/java/com/interplug/qcast/util/InterfaceQsp.java @@ -37,34 +37,41 @@ public class InterfaceQsp { * @return String * @throws Exception */ - public String callApi(HttpMethod httpMethod, String apiPath, Object requestObject) - throws Exception { - - URL url = null; - HttpURLConnection con = null; + public String callApi(HttpMethod httpMethod, String apiPath, Object requestObject) + throws Exception { + + URL url = null; + HttpURLConnection con = null; OutputStreamWriter osw = null; - BufferedReader br = null; - StringBuilder sb = null; - - try { - - // GET 요청 시 requestObject를 쿼리 스트링으로 변환 - if (HttpMethod.GET.equals(httpMethod) && requestObject != null) { + BufferedReader br = null; + StringBuilder sb = null; + long startAt = System.currentTimeMillis(); + String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); + + try { + + // GET 요청 시 requestObject를 쿼리 스트링으로 변환 + if (HttpMethod.GET.equals(httpMethod) && requestObject != null) { ObjectMapper om = new ObjectMapper(); Map params = om.convertValue(requestObject, Map.class); // Object -> Map 변환 String queryString = params.entrySet().stream() .map(entry -> entry.getKey() + "=" + entry.getValue()) - .reduce((p1, p2) -> p1 + "&" + p2) - .orElse(""); - apiPath += "?" + queryString; // 쿼리 스트링 추가 - } - - url = new URL(apiPath); - con = (HttpURLConnection) url.openConnection(); - con.setConnectTimeout(120000); // 서버에 연결되는 Timeout 시간 설정 - con.setReadTimeout(120000); // InputStream 읽어 오는 Timeout 시간 설정 - con.setRequestMethod(httpMethod.toString()); + .reduce((p1, p2) -> p1 + "&" + p2) + .orElse(""); + apiPath += "?" + queryString; // 쿼리 스트링 추가 + } + + log.debug( + "QSP API call start: method={}, url={}, requestType={}", + httpMethod, + apiPath, + requestType); + url = new URL(apiPath); + con = (HttpURLConnection) url.openConnection(); + con.setConnectTimeout(120000); // 서버에 연결되는 Timeout 시간 설정 + con.setReadTimeout(120000); // InputStream 읽어 오는 Timeout 시간 설정 + con.setRequestMethod(httpMethod.toString()); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Referer", frontUrl); con.setDoInput(true); @@ -84,20 +91,33 @@ public class InterfaceQsp { } sb = new StringBuilder(); - if (con.getResponseCode() == HttpURLConnection.HTTP_OK) { - br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); - - String line; - while ((line = br.readLine()) != null) { - sb.append(line); - } - } - } catch (Exception e) { - throw e; - } finally { - try { - if (osw != null) osw.close(); - if (br != null) br.close(); + int status = con.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); + + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + } + log.debug( + "QSP API call end: method={}, url={}, status={}, durationMs={}", + httpMethod, + apiPath, + status, + System.currentTimeMillis() - startAt); + } catch (Exception e) { + log.error( + "QSP API call failed: method={}, url={}, durationMs={}", + httpMethod, + apiPath, + System.currentTimeMillis() - startAt, + e); + throw e; + } finally { + try { + if (osw != null) osw.close(); + if (br != null) br.close(); } catch (Exception e) { throw e; } @@ -156,23 +176,30 @@ public class InterfaceQsp { * @return String * @throws Exception */ - public byte[] callApi( - HttpMethod httpMethod, String apiPath, Object requestObject, Map result) - throws Exception { - - URL url = null; + public byte[] callApi( + HttpMethod httpMethod, String apiPath, Object requestObject, Map result) + throws Exception { + + URL url = null; HttpURLConnection con = null; OutputStreamWriter osw = null; - BufferedReader br = null; - - byte[] bt = null; - - try { - url = new URL(apiPath); - con = (HttpURLConnection) url.openConnection(); - con.setConnectTimeout(30000); // 서버에 연결되는 Timeout 시간 설정 - con.setReadTimeout(30000); // InputStream 읽어 오는 Timeout 시간 설정 - con.setRequestMethod(httpMethod.toString()); + BufferedReader br = null; + + byte[] bt = null; + long startAt = System.currentTimeMillis(); + String requestType = requestObject == null ? "none" : requestObject.getClass().getSimpleName(); + + try { + log.debug( + "QSP API call start: method={}, url={}, requestType={}", + httpMethod, + apiPath, + requestType); + url = new URL(apiPath); + con = (HttpURLConnection) url.openConnection(); + con.setConnectTimeout(30000); // 서버에 연결되는 Timeout 시간 설정 + con.setReadTimeout(30000); // InputStream 읽어 오는 Timeout 시간 설정 + con.setRequestMethod(httpMethod.toString()); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Referer", frontUrl); con.setDoInput(true); @@ -190,27 +217,40 @@ public class InterfaceQsp { osw.flush(); } } - if (con.getResponseCode() == HttpURLConnection.HTTP_OK) { - // response 헤더 값 결과 셋팅 - result.put("type", con.getHeaderField("Content-Type")); - result.put("disposition", con.getHeaderField("Content-Disposition")); - - InputStream inputStream = con.getInputStream(); + int status = con.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + // response 헤더 값 결과 셋팅 + result.put("type", con.getHeaderField("Content-Type")); + result.put("disposition", con.getHeaderField("Content-Disposition")); + + InputStream inputStream = con.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); - } - bt = outputStream.toByteArray(); // 파일 데이터 반환 - } - } catch (Exception e) { - throw e; - } finally { - try { - if (osw != null) osw.close(); - if (br != null) br.close(); + } + bt = outputStream.toByteArray(); // 파일 데이터 반환 + } + log.debug( + "QSP API call end: method={}, url={}, status={}, durationMs={}", + httpMethod, + apiPath, + status, + System.currentTimeMillis() - startAt); + } catch (Exception e) { + log.error( + "QSP API call failed: method={}, url={}, durationMs={}", + httpMethod, + apiPath, + System.currentTimeMillis() - startAt, + e); + throw e; + } finally { + try { + if (osw != null) osw.close(); + if (br != null) br.close(); } catch (Exception e) { throw e; }