From 81b29765a16ab712f1aab9c1f6b3117a9e3924fc Mon Sep 17 00:00:00 2001 From: HYOJIN Date: Mon, 16 Mar 2026 16:42:49 +0900 Subject: [PATCH] =?UTF-8?q?fix(=EB=B0=B0=EC=B9=98):=20RECOLLECT=20?= =?UTF-8?q?=EB=AA=A8=EB=93=9C=EC=97=90=EC=84=9C=20Tasklet=20=EC=9E=90?= =?UTF-8?q?=EC=B2=B4=20=EC=8A=A4=ED=82=B5=EC=9C=BC=EB=A1=9C=20last=5Fsucce?= =?UTF-8?q?ss=5Fdate=20=EB=B3=B5=EC=9B=90=20=EB=A1=9C=EC=A7=81=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 14개 LastExecutionUpdateTasklet에 executionMode 체크 추가 - ShipDetailUpdateJobConfig: retryModeDecider → emptyResponseDecider 변경 - RecollectionJobExecutionListener: last_success_date 저장/복원 로직 제거 - RecollectionHistoryService: 미사용 메서드 제거 Co-Authored-By: Claude Opus 4.6 --- .../RecollectionJobExecutionListener.java | 51 +------------------ ...CompanyComplianceImportRangeJobConfig.java | 8 +++ .../ComplianceImportRangeJobConfig.java | 8 +++ .../batch/config/EventImportJobConfig.java | 8 +++ .../config/AnchorageCallsRangeJobConfig.java | 8 +++ .../batch/config/BerthCallsRangJobConfig.java | 8 +++ .../config/CurrentlyAtRangeJobConfig.java | 8 +++ .../config/DestinationsRangeJobConfig.java | 8 +++ .../config/ShipPortCallsRangeJobConfig.java | 8 +++ .../config/StsOperationRangeJobConfig.java | 8 +++ .../config/TerminalCallsRangeJobConfig.java | 8 +++ .../batch/config/TransitsRangeJobConfig.java | 8 +++ .../batch/config/PscInspectionJobConfig.java | 8 +++ .../config/RiskImportRangeJobConfig.java | 8 +++ .../config/ShipDetailUpdateJobConfig.java | 29 +++++------ .../reader/ShipDetailUpdateDataReader.java | 2 - .../snp/batch/service/BatchDateService.java | 28 ++++++++-- .../service/RecollectionHistoryService.java | 28 ---------- 18 files changed, 144 insertions(+), 98 deletions(-) diff --git a/src/main/java/com/snp/batch/common/batch/listener/RecollectionJobExecutionListener.java b/src/main/java/com/snp/batch/common/batch/listener/RecollectionJobExecutionListener.java index da5ed39..814ccf7 100644 --- a/src/main/java/com/snp/batch/common/batch/listener/RecollectionJobExecutionListener.java +++ b/src/main/java/com/snp/batch/common/batch/listener/RecollectionJobExecutionListener.java @@ -8,15 +8,11 @@ import org.springframework.batch.core.JobExecutionListener; import org.springframework.batch.core.StepExecution; import org.springframework.stereotype.Component; -import java.time.LocalDateTime; - @Slf4j @Component @RequiredArgsConstructor public class RecollectionJobExecutionListener implements JobExecutionListener { - private static final String ORIGINAL_LAST_SUCCESS_DATE_KEY = "originalLastSuccessDate"; - private final RecollectionHistoryService recollectionHistoryService; @Override @@ -35,18 +31,7 @@ public class RecollectionJobExecutionListener implements JobExecutionListener { String reason = jobExecution.getJobParameters().getString("reason"); try { - // 1. 현재 last_success_date를 JobExecutionContext에 저장 (afterJob에서 복원용) - if (apiKey != null) { - LocalDateTime originalDate = recollectionHistoryService.getLastSuccessDate(apiKey); - if (originalDate != null) { - jobExecution.getExecutionContext() - .putString(ORIGINAL_LAST_SUCCESS_DATE_KEY, originalDate.toString()); - log.info("[RecollectionListener] 원본 last_success_date 저장: apiKey={}, date={}", - apiKey, originalDate); - } - } - - // 2. 재수집 이력 기록 + // 재수집 이력 기록 recollectionHistoryService.recordStart( jobName, jobExecutionId, apiKey, executor, reason); } catch (Exception e) { @@ -65,7 +50,6 @@ public class RecollectionJobExecutionListener implements JobExecutionListener { Long jobExecutionId = jobExecution.getId(); String status = jobExecution.getStatus().name(); - String apiKey = resolveApiKey(jobExecution); // Step별 통계 집계 long totalRead = 0; @@ -102,7 +86,7 @@ public class RecollectionJobExecutionListener implements JobExecutionListener { } } - // 1. 재수집 이력 완료 기록 + // 재수집 이력 완료 기록 try { recollectionHistoryService.recordCompletion( jobExecutionId, status, @@ -112,37 +96,6 @@ public class RecollectionJobExecutionListener implements JobExecutionListener { } catch (Exception e) { log.error("[RecollectionListener] 재수집 이력 완료 기록 실패: jobExecutionId={}", jobExecutionId, e); } - - // 2. last_success_date 복원 (Tasklet이 NOW()로 업데이트한 것을 되돌림) - // 재수집은 과거 데이터 재처리이므로 last_success_date를 변경하면 안 됨 - // recordCompletion 실패와 무관하게 반드시 실행되어야 함 - try { - if (apiKey != null) { - String originalDateStr = jobExecution.getExecutionContext() - .getString(ORIGINAL_LAST_SUCCESS_DATE_KEY, null); - log.info("[RecollectionListener] last_success_date 복원 시도: apiKey={}, originalDateStr={}", - apiKey, originalDateStr); - if (originalDateStr != null) { - LocalDateTime originalDate = LocalDateTime.parse(originalDateStr); - // 현재 DB 값이 원본보다 미래면(정상 수집 발생) 복원 스킵 - LocalDateTime currentDate = recollectionHistoryService.getLastSuccessDate(apiKey); - if (currentDate != null && currentDate.isAfter(originalDate)) { - log.info("[RecollectionListener] last_success_date가 이미 갱신됨 (정상 수집 발생), 복원 스킵: apiKey={}, original={}, current={}", - apiKey, originalDate, currentDate); - } else { - recollectionHistoryService.restoreLastSuccessDate(apiKey, originalDate); - log.info("[RecollectionListener] last_success_date 복원 완료: apiKey={}, date={}", - apiKey, originalDate); - } - } else { - log.warn("[RecollectionListener] originalLastSuccessDate가 ExecutionContext에 없음: apiKey={}", - apiKey); - } - } - } catch (Exception e) { - log.error("[RecollectionListener] last_success_date 복원 실패: apiKey={}, jobExecutionId={}", - apiKey, jobExecutionId, e); - } } /** diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/config/CompanyComplianceImportRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/compliance/batch/config/CompanyComplianceImportRangeJobConfig.java index c0d5958..329a683 100644 --- a/src/main/java/com/snp/batch/jobs/compliance/batch/config/CompanyComplianceImportRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/compliance/batch/config/CompanyComplianceImportRangeJobConfig.java @@ -212,6 +212,14 @@ public class CompanyComplianceImportRangeJobConfig extends BaseMultiStepJobConfi @Bean public Tasklet companyComplianceLastExecutionUpdateTasklet() { return (contribution, chunkContext) -> { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/compliance/batch/config/ComplianceImportRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/compliance/batch/config/ComplianceImportRangeJobConfig.java index 01462c2..d4a9444 100644 --- a/src/main/java/com/snp/batch/jobs/compliance/batch/config/ComplianceImportRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/compliance/batch/config/ComplianceImportRangeJobConfig.java @@ -214,6 +214,14 @@ public class ComplianceImportRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/event/batch/config/EventImportJobConfig.java b/src/main/java/com/snp/batch/jobs/event/batch/config/EventImportJobConfig.java index cae4046..e31900f 100644 --- a/src/main/java/com/snp/batch/jobs/event/batch/config/EventImportJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/event/batch/config/EventImportJobConfig.java @@ -160,6 +160,14 @@ public class EventImportJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/AnchorageCallsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/AnchorageCallsRangeJobConfig.java index eafc25b..60ea633 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/AnchorageCallsRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/AnchorageCallsRangeJobConfig.java @@ -150,6 +150,14 @@ public class AnchorageCallsRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/BerthCallsRangJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/BerthCallsRangJobConfig.java index 344407a..dc705b1 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/BerthCallsRangJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/BerthCallsRangJobConfig.java @@ -144,6 +144,14 @@ public class BerthCallsRangJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/CurrentlyAtRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/CurrentlyAtRangeJobConfig.java index 31b0aed..e958995 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/CurrentlyAtRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/CurrentlyAtRangeJobConfig.java @@ -142,6 +142,14 @@ public class CurrentlyAtRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/DestinationsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/DestinationsRangeJobConfig.java index 2e47c7d..169d1d1 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/DestinationsRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/DestinationsRangeJobConfig.java @@ -145,6 +145,14 @@ public class DestinationsRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/ShipPortCallsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/ShipPortCallsRangeJobConfig.java index f2cb4c6..d638f27 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/ShipPortCallsRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/ShipPortCallsRangeJobConfig.java @@ -146,6 +146,14 @@ public class ShipPortCallsRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/StsOperationRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/StsOperationRangeJobConfig.java index 8b29f82..acbbcdb 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/StsOperationRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/StsOperationRangeJobConfig.java @@ -144,6 +144,14 @@ public class StsOperationRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/TerminalCallsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/TerminalCallsRangeJobConfig.java index ea0bfe0..1eff291 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/TerminalCallsRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/TerminalCallsRangeJobConfig.java @@ -144,6 +144,14 @@ public class TerminalCallsRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/movement/batch/config/TransitsRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/movement/batch/config/TransitsRangeJobConfig.java index 6f9e510..53be31a 100644 --- a/src/main/java/com/snp/batch/jobs/movement/batch/config/TransitsRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/movement/batch/config/TransitsRangeJobConfig.java @@ -142,6 +142,14 @@ public class TransitsRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/pscInspection/batch/config/PscInspectionJobConfig.java b/src/main/java/com/snp/batch/jobs/pscInspection/batch/config/PscInspectionJobConfig.java index 86cd988..1d27a4b 100644 --- a/src/main/java/com/snp/batch/jobs/pscInspection/batch/config/PscInspectionJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/pscInspection/batch/config/PscInspectionJobConfig.java @@ -166,6 +166,14 @@ public class PscInspectionJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskImportRangeJobConfig.java b/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskImportRangeJobConfig.java index abcd22a..e2e2d37 100644 --- a/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskImportRangeJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/risk/batch/config/RiskImportRangeJobConfig.java @@ -158,6 +158,14 @@ public class RiskImportRangeJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailUpdateJobConfig.java b/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailUpdateJobConfig.java index 8a189b4..cd9cedf 100644 --- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailUpdateJobConfig.java +++ b/src/main/java/com/snp/batch/jobs/shipdetail/batch/config/ShipDetailUpdateJobConfig.java @@ -16,9 +16,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.core.job.builder.FlowBuilder; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.job.flow.Flow; import org.springframework.batch.core.job.flow.FlowExecutionStatus; import org.springframework.batch.core.job.flow.JobExecutionDecider; import org.springframework.batch.core.repository.JobRepository; @@ -127,27 +125,20 @@ public class ShipDetailUpdateJobConfig extends BaseMultiStepJobConfig { - String executionMode = jobExecution.getJobParameters().getString("executionMode"); - if ("RECOLLECT".equals(executionMode)) { - log.info("[ShipDetailUpdateJob] Decider: RETRY 모드 - LAST_EXECUTION 업데이트 스킵"); - return new FlowExecutionStatus("RETRY"); - } - if (stepExecution != null && stepExecution.getReadCount() == 0) { log.info("[ShipDetailUpdateJob] Decider: EMPTY_RESPONSE - 응답 데이터 0건으로 LAST_EXECUTION 업데이트 스킵 (다음 실행 시 동일 범위 재조회)"); return new FlowExecutionStatus("EMPTY_RESPONSE"); @@ -236,6 +227,14 @@ public class ShipDetailUpdateJobConfig extends BaseMultiStepJobConfig { + String executionMode = chunkContext.getStepContext() + .getStepExecution().getJobExecution() + .getJobParameters().getString("executionMode", "NORMAL"); + if ("RECOLLECT".equals(executionMode)) { + log.info(">>>>> RECOLLECT 모드 - LAST_EXECUTION 업데이트 스킵"); + return RepeatStatus.FINISHED; + } + String toDateStr = chunkContext.getStepContext() .getStepExecution().getJobExecution() .getExecutionContext().getString("batchToDate", null); diff --git a/src/main/java/com/snp/batch/jobs/shipdetail/batch/reader/ShipDetailUpdateDataReader.java b/src/main/java/com/snp/batch/jobs/shipdetail/batch/reader/ShipDetailUpdateDataReader.java index d6fa3ef..076648c 100644 --- a/src/main/java/com/snp/batch/jobs/shipdetail/batch/reader/ShipDetailUpdateDataReader.java +++ b/src/main/java/com/snp/batch/jobs/shipdetail/batch/reader/ShipDetailUpdateDataReader.java @@ -123,8 +123,6 @@ public class ShipDetailUpdateDataReader extends BaseApiReader { log.info("[{}] 변경된 IMO 번호 조회 시작...", getReaderName()); ShipUpdateApiResponse response = callShipUpdateApi(); List fullList = extractUpdateImoNumbers(response); - allImoNumbers = new ArrayList<>(fullList); - log.info("[{}] 변경된 IMO 번호 수: {} 개", getReaderName(), response.getShipCount()); log.info("[{}] 총 {} 개의 변경된 IMO 번호 조회 완료", getReaderName(), allImoNumbers.size()); } diff --git a/src/main/java/com/snp/batch/service/BatchDateService.java b/src/main/java/com/snp/batch/service/BatchDateService.java index 13da871..32c45b5 100644 --- a/src/main/java/com/snp/batch/service/BatchDateService.java +++ b/src/main/java/com/snp/batch/service/BatchDateService.java @@ -57,9 +57,28 @@ public class BatchDateService { return null; } + /** + * 현재 Step의 Job 파라미터에서 executor를 확인. + * AUTO_RETRY/MANUAL_RETRY이면 실패건 재수집이므로 기간 테이블을 사용하지 않는다. + */ + private boolean isFailedRecordRetry() { + try { + StepContext context = StepSynchronizationManager.getContext(); + if (context != null && context.getStepExecution() != null) { + String executor = context.getStepExecution().getJobExecution() + .getJobParameters().getString("executor"); + return "AUTO_RETRY".equals(executor) || "MANUAL_RETRY".equals(executor); + } + } catch (Exception e) { + log.debug("executor 파라미터 확인 실패", e); + } + return false; + } + public Map getDateRangeWithoutTimeParams(String apiKey) { - // 재수집 모드: batch_collection_period에서 날짜 조회 - if ("RECOLLECT".equals(getExecutionMode())) { + // 기간 재수집 모드: batch_collection_period에서 날짜 조회 + // 실패건 재수집(AUTO_RETRY/MANUAL_RETRY)은 정상 모드와 동일하게 last_success_date 기반 사용 + if ("RECOLLECT".equals(getExecutionMode()) && !isFailedRecordRetry()) { return getCollectionPeriodDateParams(apiKey); } @@ -88,8 +107,9 @@ public class BatchDateService { public Map getDateRangeWithTimezoneParams(String apiKey, String dateParam1, String dateParam2) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSX"); - // 재수집 모드: batch_collection_period에서 날짜 조회 - if ("RECOLLECT".equals(getExecutionMode())) { + // 기간 재수집 모드: batch_collection_period에서 날짜 조회 + // 실패건 재수집(AUTO_RETRY/MANUAL_RETRY)은 정상 모드와 동일하게 last_success_date 기반 사용 + if ("RECOLLECT".equals(getExecutionMode()) && !isFailedRecordRetry()) { return getCollectionPeriodTimezoneParams(apiKey, dateParam1, dateParam2, formatter); } diff --git a/src/main/java/com/snp/batch/service/RecollectionHistoryService.java b/src/main/java/com/snp/batch/service/RecollectionHistoryService.java index 2eaa1dd..7d4e44d 100644 --- a/src/main/java/com/snp/batch/service/RecollectionHistoryService.java +++ b/src/main/java/com/snp/batch/service/RecollectionHistoryService.java @@ -2,7 +2,6 @@ package com.snp.batch.service; import com.snp.batch.global.dto.JobExecutionDetailDto; import com.snp.batch.global.model.BatchCollectionPeriod; -import com.snp.batch.global.model.BatchLastExecution; import com.snp.batch.global.model.BatchRecollectionHistory; import com.snp.batch.global.model.BatchFailedRecord; import com.snp.batch.global.model.JobDisplayNameEntity; @@ -482,33 +481,6 @@ public class RecollectionHistoryService { .orElse(null); } - /** - * 재수집 실행 전: 현재 last_success_date 조회 (복원용) - */ - @Transactional(readOnly = true) - public LocalDateTime getLastSuccessDate(String apiKey) { - return lastExecutionRepository.findById(apiKey) - .map(BatchLastExecution::getLastSuccessDate) - .orElse(null); - } - - /** - * 재수집 실행 후: Tasklet이 업데이트한 last_success_date를 원래 값으로 복원 - * 재수집은 과거 데이터 재처리이므로 last_success_date를 변경하면 안 됨 - */ - @Transactional(propagation = Propagation.REQUIRES_NEW) - public void restoreLastSuccessDate(String apiKey, LocalDateTime originalDate) { - if (originalDate == null) return; - lastExecutionRepository.findById(apiKey).ifPresent(lastExec -> { - LocalDateTime beforeDate = lastExec.getLastSuccessDate(); - lastExec.setLastSuccessDate(originalDate); - lastExec.setUpdatedAt(LocalDateTime.now()); - lastExecutionRepository.save(lastExec); - log.info("[RecollectionHistory] last_success_date 복원: apiKey={}, before={}, after={}", - apiKey, beforeDate, originalDate); - }); - } - /** * 수집 기간 전체 조회 */