diff --git a/src/main/java/com/worker/scheduler/smg/schedule/SinmungoInOutScheduler.java b/src/main/java/com/worker/scheduler/smg/schedule/SinmungoInOutScheduler.java index 342ba4e..10ce1cf 100644 --- a/src/main/java/com/worker/scheduler/smg/schedule/SinmungoInOutScheduler.java +++ b/src/main/java/com/worker/scheduler/smg/schedule/SinmungoInOutScheduler.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.worker.scheduler.smg.dto.SinmungoDto; import com.worker.scheduler.smg.service.DbPolling; +import com.worker.scheduler.smg.service.SetInfoService; import com.worker.scheduler.smg.service.XmlSend; import com.worker.util.common.commEnum.StateEnum; import com.worker.util.fileReader.FileParserInterface; @@ -15,7 +16,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import java.io.IOException; import java.nio.file.Paths; import java.util.List; import java.util.Map; @@ -30,6 +30,7 @@ public class SinmungoInOutScheduler { private final FileReader fileReader; private final XmlSend xmlSend; + private final SetInfoService setInfoService; private final DbPolling dbPolling; @@ -41,7 +42,7 @@ public class SinmungoInOutScheduler { try{ log.info("신문고 신고 폴링 스케쥴러 시작!"); //setinfo 테이블에서 esb에이전트 정보 조회 - SinmungoDto.SetInfo setInfo = dbPolling.findSetInfo(); + SinmungoDto.SetInfo setInfo = setInfoService.findSetInfo(); String filePath = null; if(setInfo.getCpSetinfo().getStrValue2().equals("")) filePath = setInfo.getCpSetinfo().getStrValue2(); else filePath = setInfo.getCpSetinfo().getStrValue2(); @@ -120,7 +121,7 @@ public class SinmungoInOutScheduler { public void sinmungoOver90DaysXmlFileRemoveScheduler() { log.info("90일 초과 파일 삭제 스케쥴러 시작!"); //setinfo 테이블에서 esb에이전트 정보 조회 - SinmungoDto.SetInfo setInfo = dbPolling.findSetInfo(); + SinmungoDto.SetInfo setInfo = setInfoService.findSetInfo(); fileReader.xmlFileRemove(Paths.get(setInfo.getCpSetinfo().getStrValue4())); fileReader.xmlFileRemove(Paths.get(setInfo.getEpSetinfo().getStrValue4())); @@ -133,7 +134,7 @@ public class SinmungoInOutScheduler { log.info("답변생성 스케쥴러 시작!"); //setinfo 테이블에서 esb에이전트 정보 조회 - SinmungoDto.SetInfo setInfo = dbPolling.findSetInfo(); + SinmungoDto.SetInfo setInfo = setInfoService.findSetInfo(); //대상 답변 조회 SinmungoDto.Send.Answers answers = xmlSend.findAnswersByStatus(StateEnum.ANSWER_STATE_ANSWER_WAIT.getCode()); diff --git a/src/main/java/com/worker/scheduler/smg/service/DbPolling.java b/src/main/java/com/worker/scheduler/smg/service/DbPolling.java index 1a06eba..8d3982d 100644 --- a/src/main/java/com/worker/scheduler/smg/service/DbPolling.java +++ b/src/main/java/com/worker/scheduler/smg/service/DbPolling.java @@ -36,10 +36,10 @@ public class DbPolling { private final Environment env; private final FileReader fileReader; - private final CpSetinfoRepository cpSetinfoRepository; - private final EpSetinfoRepository epSetinfoRepository; - private final CpBdongRepository cpBdongRepository; - private final EpBdongRepository epBdongRepository; +// private final CpSetinfoRepository cpSetinfoRepository; +// private final EpSetinfoRepository epSetinfoRepository; +// private final CpBdongRepository cpBdongRepository; +// private final EpBdongRepository epBdongRepository; private final CpMainRepository cpMainRepository; private final EpMainRepository epMainRepository; @@ -52,35 +52,35 @@ public class DbPolling { private final CpImagesizeRepository cpImagesizeRepository; private final EpImagesizeRepository epImagesizeRepository; - public SinmungoDto.SetInfo findSetInfo() { - - // setInfo는 폴링 작업에 필요한 모든정보를 여기서 전부 조회하고 객체로 리턴 - CpSetinfo cpSetinfo = cpSetinfoRepository.findById( - CpSetinfoId.builder() - .codeName(env.getProperty("esb.info.cp.codeName")) - .groupCode(env.getProperty("esb.info.cp.groupCode")) - .detailCode(env.getProperty("esb.info.cp.detailCode")) - .build() - ).orElse(null); - List cpBdongList = cpBdongRepository.findAll(); - - - CpSetinfo epSetInfo = epSetinfoRepository.findById( - CpSetinfoId.builder() - .codeName(env.getProperty("esb.info.ep.codeName")) - .groupCode(env.getProperty("esb.info.ep.groupCode")) - .detailCode(env.getProperty("esb.info.ep.detailCode")) - .build() - ).orElse(null); - List epBdongList = epBdongRepository.findAll(); - - return SinmungoDto.SetInfo.builder() - .cpSetinfo(cpSetinfo) - .epSetinfo(epSetInfo) - .cpBdongList(cpBdongList) - .epBdongList(epBdongList) - .build(); - } +// public SinmungoDto.SetInfo findSetInfo() { +// +// // setInfo는 폴링 작업에 필요한 모든정보를 여기서 전부 조회하고 객체로 리턴 +// CpSetinfo cpSetinfo = cpSetinfoRepository.findById( +// CpSetinfoId.builder() +// .codeName(env.getProperty("esb.info.cp.codeName")) +// .groupCode(env.getProperty("esb.info.cp.groupCode")) +// .detailCode(env.getProperty("esb.info.cp.detailCode")) +// .build() +// ).orElse(null); +// List cpBdongList = cpBdongRepository.findAll(); +// +// +// CpSetinfo epSetInfo = epSetinfoRepository.findById( +// CpSetinfoId.builder() +// .codeName(env.getProperty("esb.info.ep.codeName")) +// .groupCode(env.getProperty("esb.info.ep.groupCode")) +// .detailCode(env.getProperty("esb.info.ep.detailCode")) +// .build() +// ).orElse(null); +// List epBdongList = epBdongRepository.findAll(); +// +// return SinmungoDto.SetInfo.builder() +// .cpSetinfo(cpSetinfo) +// .epSetinfo(epSetInfo) +// .cpBdongList(cpBdongList) +// .epBdongList(epBdongList) +// .build(); +// } @Transactional public void saveCP(List cpList, SinmungoDto.SetInfo setInfo) { @@ -425,7 +425,7 @@ public class DbPolling { } else if (peti_reason_l.contains(LawGBEnum.SIGN.getCodeNm())) { return LawGBEnum.SIGN; } - return LawGBEnum.UNKNOWN; + return LawGBEnum.PARKING; } //비디오 파일 여부를 체크하고, 코드값을 리턴한다. diff --git a/src/main/java/com/worker/scheduler/smg/service/SetInfoService.java b/src/main/java/com/worker/scheduler/smg/service/SetInfoService.java new file mode 100644 index 0000000..a7c057d --- /dev/null +++ b/src/main/java/com/worker/scheduler/smg/service/SetInfoService.java @@ -0,0 +1,111 @@ +package com.worker.scheduler.smg.service; + + +import com.worker.domain.entity.CpBdong; +import com.worker.domain.entity.CpSetinfo; +import com.worker.domain.entity.CpSetinfoId; +import com.worker.domain.repo.cp.CpBdongRepository; +import com.worker.domain.repo.cp.CpSetinfoRepository; +import com.worker.domain.repo.ep.EpBdongRepository; +import com.worker.domain.repo.ep.EpSetinfoRepository; +import com.worker.scheduler.smg.dto.SinmungoDto; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.util.Collections; +import java.util.List; +import java.util.function.Supplier; + +@Service +@RequiredArgsConstructor +@Slf4j +public class SetInfoService { + + private final Environment env; + + // CP + private final CpSetinfoRepository cpSetinfoRepository; + private final CpBdongRepository cpBdongRepository; + @Qualifier("cpDataSource") + private final DataSource cpDataSource; + + // EP + private final EpSetinfoRepository epSetinfoRepository; + private final EpBdongRepository epBdongRepository; + @Qualifier("epDataSource") + private final DataSource epDataSource; + + public SinmungoDto.SetInfo findSetInfo() { + // 공통 ID 빌더 + CpSetinfoId cpId = CpSetinfoId.builder() + .codeName(env.getProperty("esb.info.cp.codeName")) + .groupCode(env.getProperty("esb.info.cp.groupCode")) + .detailCode(env.getProperty("esb.info.cp.detailCode")) + .build(); + + CpSetinfoId epId = CpSetinfoId.builder() + .codeName(env.getProperty("esb.info.ep.codeName")) + .groupCode(env.getProperty("esb.info.ep.groupCode")) + .detailCode(env.getProperty("esb.info.ep.detailCode")) + .build(); + + // CP 쪽 + CpSetinfo cpSetinfo = null; + List cpBdongList = Collections.emptyList(); + if (isDsAvailable(cpDataSource)) { + try { + cpSetinfo = cpSetinfoRepository.findById(cpId).orElse(null); + cpBdongList = safeList(cpBdongRepository::findAll); + } catch (Exception e) { + log.warn("[CP] 조회 실패. CP는 스킵: {}", e.getMessage()); + } + } else { + log.info("[CP] DB 비가용. CP 스킵."); + } + + // EP 쪽 + CpSetinfo epSetinfo = null; + List epBdongList = Collections.emptyList(); + if (isDsAvailable(epDataSource)) { + try { + epSetinfo = epSetinfoRepository.findById(epId).orElse(null); + epBdongList = safeList(epBdongRepository::findAll); + } catch (Exception e) { + log.warn("[EP] 조회 실패. EP 스킵: {}", e.getMessage()); + } + } else { + log.info("[EP] DB 비가용. EP 스킵."); + } + + return SinmungoDto.SetInfo.builder() + .cpSetinfo(cpSetinfo) // 없으면 null + .epSetinfo(epSetinfo) // 없으면 null + .cpBdongList(cpBdongList) // 없으면 empty + .epBdongList(epBdongList) // 없으면 empty + .build(); + } + + private boolean isDsAvailable(DataSource ds) { + if (ds == null) return false; // 데이터소스 빈 자체가 없을 수도 있음 + try (Connection c = ds.getConnection()) { + return true; + } catch (Exception e) { + return false; + } + } + + // 레포 호출을 안전하게 감싸 빈 리스트로 대체 + private List safeList(Supplier> supplier) { + try { + List list = supplier.get(); + return list != null ? list : Collections.emptyList(); + } catch (Exception e) { + return Collections.emptyList(); + } + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index f052c90..21805b0 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -9,11 +9,22 @@ spring: username: root password: xit5811807 driver-class-name: org.mariadb.jdbc.Driver + hikari: + initialization-fail-timeout: -1 # DB 없어도 부팅 계속 + validation-timeout: 2000 # ms + connection-timeout: 3000 # ms + maximum-pool-size: 5 ep: url: jdbc:mariadb://211.119.124.122:53306/demon_test_ep?useUnicode=true&characterEncoding=utf8 username: root password: xit5811807 driver-class-name: org.mariadb.jdbc.Driver + hikari: + initialization-fail-timeout: -1 # DB 없어도 부팅 계속 + validation-timeout: 2000 # ms + connection-timeout: 3000 # ms + maximum-pool-size: 5 + # 이미 운영되고있는 서버들 많고 디비 구성 변경시 영향도 파악 어려움. # ddl은 무조건 수동으로 해줄것. @@ -26,6 +37,8 @@ spring: properties: hibernate: format_sql: true + # 부팅 시 DB 메타데이터 조회 방지 + 방언 명시 (매우 중요) + temp.use_jdbc_metadata_defaults: false dialect: org.hibernate.dialect.MySQLDialect scheduler: diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 7f2c620..21805b0 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -1,8 +1,6 @@ server: port: 8011 - - spring: datasource: # 122번 서버 보면 클린파킹 많은데 cp1이 최신임. cp1기준으로 작업. @@ -11,11 +9,22 @@ spring: username: root password: xit5811807 driver-class-name: org.mariadb.jdbc.Driver + hikari: + initialization-fail-timeout: -1 # DB 없어도 부팅 계속 + validation-timeout: 2000 # ms + connection-timeout: 3000 # ms + maximum-pool-size: 5 ep: url: jdbc:mariadb://211.119.124.122:53306/demon_test_ep?useUnicode=true&characterEncoding=utf8 username: root password: xit5811807 driver-class-name: org.mariadb.jdbc.Driver + hikari: + initialization-fail-timeout: -1 # DB 없어도 부팅 계속 + validation-timeout: 2000 # ms + connection-timeout: 3000 # ms + maximum-pool-size: 5 + # 이미 운영되고있는 서버들 많고 디비 구성 변경시 영향도 파악 어려움. # ddl은 무조건 수동으로 해줄것. @@ -28,13 +37,15 @@ spring: properties: hibernate: format_sql: true + # 부팅 시 DB 메타데이터 조회 방지 + 방언 명시 (매우 중요) + temp.use_jdbc_metadata_defaults: false dialect: org.hibernate.dialect.MySQLDialect scheduler: smg: enabled: true epost: - enabled: true + enabled: false tax-sunap: enabled: false update: @@ -45,11 +56,11 @@ esb: cp: codeName: WORKER groupCode: INFO - detailCode: LOCAL + detailCode: DEV ep: codeName: WORKER groupCode: INFO - detailCode: LOCAL + detailCode: DEV tax-else: protocol: http:// @@ -58,26 +69,26 @@ tax-else: path: sunap: /mediate/ltis - e-post: info: cp: codeName: EPOST_INFO groupCode: INFO_1 - detailCode: LOCAL + detailCode: DEV ep: codeName: EPOST_INFO groupCode: INFO_1 - detailCode: LOCAL + detailCode: DEV docCode: cp: codeName: EPOST_INFO groupCode: DOC_CODE - detailCode: LOCAL + detailCode: DEV ep: codeName: EPOST_INFO groupCode: DOC_CODE - detailCode: LOCAL + detailCode: DEV + logging: