Split the function

This commit is contained in:
2026-02-09 20:52:41 +09:00
parent ef31309f77
commit c2d4d3a5f0
2 changed files with 51 additions and 25 deletions

View File

@@ -18,14 +18,21 @@ import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus; import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
/** /**
* Child Job 실행 Tasklet (Parent Job용) * Child Job 실행 Tasklet (Parent Job용)
* *
* <p>진행 중인 모든 분석 회차(AnalCntInfo)를 조회하여 각 회차마다 독립적인 Child Job을 실행합니다. 각 Child Job은 3개의 * <p>
* 진행 중인 모든 분석 회차(AnalCntInfo)를 조회하여 각 회차마다 독립적인 Child Job을 실행합니다. 각 Child Job은
* 3개의
* Step(makeGeoJson → dockerRun → zipResponse)을 순차적으로 실행합니다. * Step(makeGeoJson → dockerRun → zipResponse)을 순차적으로 실행합니다.
* *
* <p><b>주요 기능:</b> * <p>
* <b>주요 기능:</b>
* *
* <ul> * <ul>
* <li>진행 중인 분석 회차 목록 조회 (tb_map_sheet_anal_inference, anal_state='ING') * <li>진행 중인 분석 회차 목록 조회 (tb_map_sheet_anal_inference, anal_state='ING')
@@ -34,7 +41,8 @@ import org.springframework.stereotype.Component;
* <li>부분 실패 허용 (한 회차 실패해도 다른 회차 계속 처리) * <li>부분 실패 허용 (한 회차 실패해도 다른 회차 계속 처리)
* </ul> * </ul>
* *
* <p><b>실행 조건:</b> * <p>
* <b>실행 조건:</b>
* *
* <ul> * <ul>
* <li>tb_map_sheet_anal_inference.anal_state = 'ING' (진행 중) * <li>tb_map_sheet_anal_inference.anal_state = 'ING' (진행 중)
@@ -42,7 +50,8 @@ import org.springframework.stereotype.Component;
* <li>all_cnt != file_cnt (아직 파일 생성이 완료되지 않음) * <li>all_cnt != file_cnt (아직 파일 생성이 완료되지 않음)
* </ul> * </ul>
* *
* <p><b>실패 정책:</b> * <p>
* <b>실패 정책:</b>
* *
* <ul> * <ul>
* <li>현재: 부분 실패 허용 (일부 Child Job 실패해도 Parent Job 성공) * <li>현재: 부분 실패 허용 (일부 Child Job 실패해도 Parent Job 성공)
@@ -69,10 +78,15 @@ public class LaunchChildJobsTasklet implements Tasklet {
@Qualifier("processAnalCntInfoJob") @Qualifier("processAnalCntInfoJob")
private final Job processAnalCntInfoJob; private final Job processAnalCntInfoJob;
/** 트랜잭션 매니저 (트랜잭션 제어용) */
private final PlatformTransactionManager transactionManager;
/** /**
* Parent Job의 메인 로직 실행 * Parent Job의 메인 로직 실행
* *
* <p>진행 중인 모든 분석 회차를 조회하여 각 회차마다 Child Job을 실행합니다. 한 회차가 실패해도 다른 회차는 계속 처리되며, 최종적으로 통계를 * <p>
* 진행 중인 모든 분석 회차를 조회하여 각 회차마다 Child Job을 실행합니다. 한 회차가 실패해도 다른 회차는 계속 처리되며,
* 최종적으로 통계를
* 로깅합니다. * 로깅합니다.
* *
* @param contribution Step 실행 정보를 담는 객체 * @param contribution Step 실행 정보를 담는 객체
@@ -133,8 +147,7 @@ public class LaunchChildJobsTasklet implements Tasklet {
try { try {
// Child Job Parameters 생성 // Child Job Parameters 생성
JobParameters jobParameters = JobParameters jobParameters = new JobParametersBuilder()
new JobParametersBuilder()
.addLong("analUid", info.getAnalUid()) .addLong("analUid", info.getAnalUid())
.addString("resultUid", info.getResultUid()) .addString("resultUid", info.getResultUid())
.addLong("timestamp", System.currentTimeMillis()) // JobInstance 고유성 보장 .addLong("timestamp", System.currentTimeMillis()) // JobInstance 고유성 보장
@@ -148,7 +161,21 @@ public class LaunchChildJobsTasklet implements Tasklet {
// asyncJobLauncher를 사용하여 별도 쓰레드에서 실행 // asyncJobLauncher를 사용하여 별도 쓰레드에서 실행
// 내부적으로 makeGeoJsonStep → dockerRunStep → zipResponseStep 순차 실행 // 내부적으로 makeGeoJsonStep → dockerRunStep → zipResponseStep 순차 실행
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
JobExecution jobExecution = asyncJobLauncher.run(processAnalCntInfoJob, jobParameters);
// 트랜잭션 일시 정지 후 실행 (Existing transaction detected 에러 방지)
JobExecution jobExecution = new TransactionTemplate(transactionManager,
new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_NOT_SUPPORTED))
.execute(status -> {
try {
return asyncJobLauncher.run(processAnalCntInfoJob, jobParameters);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
if (jobExecution == null) {
throw new RuntimeException("JobExecution is null after launching child job");
}
// Child Job 완료 대기 (비동기 실행이므로 완료를 폴링) // Child Job 완료 대기 (비동기 실행이므로 완료를 폴링)
log.info("[Child Job 대기] 실행 완료 대기 중... (JobExecutionId={})", log.info("[Child Job 대기] 실행 완료 대기 중... (JobExecutionId={})",
@@ -222,8 +249,7 @@ public class LaunchChildJobsTasklet implements Tasklet {
// 성공률 계산 // 성공률 계산
if (analList.size() > 0) { if (analList.size() > 0) {
double successRate = double successRate = (double) processedCount / (analList.size() - skippedCount) * 100;
(double) processedCount / (analList.size() - skippedCount) * 100;
log.info(" - 성공률: {}% (건너뛴 회차 제외)", String.format("%.2f", successRate)); log.info(" - 성공률: {}% (건너뛴 회차 제외)", String.format("%.2f", successRate));
} }