feat(maintenance): 배치 로그 관리 정리 Job 구현 (#16)
- BatchLogCleanupJobConfig: Tasklet 기반 로그 정리 Job - BatchLogCleanupRepository: FK 순서 고려 6단계 삭제 (step_context → step_execution → job_context → job_params → job_execution → job_instance) - application.yml: log-retention-days: 90 설정 - UI 스케줄에서 batchLogCleanupJob 등록하여 사용 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
부모
b0b25f79f6
커밋
9b4dba1568
@ -0,0 +1,63 @@
|
||||
package com.snp.batch.jobs.maintenance;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.job.builder.JobBuilder;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.step.builder.StepBuilder;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 배치 로그 정리 Job
|
||||
* 보관 기간이 지난 Spring Batch 메타데이터를 삭제
|
||||
*
|
||||
* 실행 주기: 매주 일요일 00:00 (Quartz 스케줄)
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class BatchLogCleanupJobConfig {
|
||||
|
||||
private final JobRepository jobRepository;
|
||||
private final PlatformTransactionManager transactionManager;
|
||||
private final BatchLogCleanupRepository cleanupRepository;
|
||||
|
||||
@Value("${app.batch.log-retention-days:90}")
|
||||
private int retentionDays;
|
||||
|
||||
@Bean
|
||||
public Job batchLogCleanupJob() {
|
||||
return new JobBuilder("batchLogCleanupJob", jobRepository)
|
||||
.start(batchLogCleanupStep())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step batchLogCleanupStep() {
|
||||
return new StepBuilder("batchLogCleanupStep", jobRepository)
|
||||
.tasklet(batchLogCleanupTasklet(), transactionManager)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Tasklet batchLogCleanupTasklet() {
|
||||
return (contribution, chunkContext) -> {
|
||||
LocalDateTime before = LocalDateTime.now().minusDays(retentionDays);
|
||||
log.info("[LogCleanup] 배치 로그 정리 시작 (보관 기간: {}일, 기준일시: {})", retentionDays, before);
|
||||
|
||||
int totalDeleted = cleanupRepository.deleteOldLogs(before);
|
||||
|
||||
log.info("[LogCleanup] 배치 로그 정리 완료 (총 {}건 삭제)", totalDeleted);
|
||||
return RepeatStatus.FINISHED;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.snp.batch.jobs.maintenance;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 배치 로그 삭제 Repository
|
||||
* FK 제약 조건 순서를 고려하여 삭제
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class BatchLogCleanupRepository {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
/**
|
||||
* 보관 기간이 지난 배치 로그를 삭제
|
||||
* 삭제 순서: step_context → step_execution → job_context → job_params → job_execution → job_instance(고아)
|
||||
*
|
||||
* @param before 이 시점 이전의 로그를 삭제
|
||||
* @return 삭제된 총 행 수
|
||||
*/
|
||||
public int deleteOldLogs(LocalDateTime before) {
|
||||
int total = 0;
|
||||
|
||||
// 1. batch_step_execution_context (step_execution FK)
|
||||
int stepCtx = jdbcTemplate.update("""
|
||||
DELETE FROM batch_step_execution_context
|
||||
WHERE STEP_EXECUTION_ID IN (
|
||||
SELECT se.STEP_EXECUTION_ID
|
||||
FROM batch_step_execution se
|
||||
INNER JOIN batch_job_execution je ON se.JOB_EXECUTION_ID = je.JOB_EXECUTION_ID
|
||||
WHERE je.START_TIME < ?
|
||||
)
|
||||
""", before);
|
||||
log.info("[LogCleanup] batch_step_execution_context: {}건 삭제", stepCtx);
|
||||
total += stepCtx;
|
||||
|
||||
// 2. batch_step_execution
|
||||
int stepExec = jdbcTemplate.update("""
|
||||
DELETE FROM batch_step_execution
|
||||
WHERE JOB_EXECUTION_ID IN (
|
||||
SELECT JOB_EXECUTION_ID FROM batch_job_execution WHERE START_TIME < ?
|
||||
)
|
||||
""", before);
|
||||
log.info("[LogCleanup] batch_step_execution: {}건 삭제", stepExec);
|
||||
total += stepExec;
|
||||
|
||||
// 3. batch_job_execution_context
|
||||
int jobCtx = jdbcTemplate.update("""
|
||||
DELETE FROM batch_job_execution_context
|
||||
WHERE JOB_EXECUTION_ID IN (
|
||||
SELECT JOB_EXECUTION_ID FROM batch_job_execution WHERE START_TIME < ?
|
||||
)
|
||||
""", before);
|
||||
log.info("[LogCleanup] batch_job_execution_context: {}건 삭제", jobCtx);
|
||||
total += jobCtx;
|
||||
|
||||
// 4. batch_job_execution_params
|
||||
int jobParams = jdbcTemplate.update("""
|
||||
DELETE FROM batch_job_execution_params
|
||||
WHERE JOB_EXECUTION_ID IN (
|
||||
SELECT JOB_EXECUTION_ID FROM batch_job_execution WHERE START_TIME < ?
|
||||
)
|
||||
""", before);
|
||||
log.info("[LogCleanup] batch_job_execution_params: {}건 삭제", jobParams);
|
||||
total += jobParams;
|
||||
|
||||
// 5. batch_job_execution
|
||||
int jobExec = jdbcTemplate.update("""
|
||||
DELETE FROM batch_job_execution WHERE START_TIME < ?
|
||||
""", before);
|
||||
log.info("[LogCleanup] batch_job_execution: {}건 삭제", jobExec);
|
||||
total += jobExec;
|
||||
|
||||
// 6. batch_job_instance (고아 인스턴스)
|
||||
int jobInst = jdbcTemplate.update("""
|
||||
DELETE FROM batch_job_instance
|
||||
WHERE JOB_INSTANCE_ID NOT IN (
|
||||
SELECT JOB_INSTANCE_ID FROM batch_job_execution
|
||||
)
|
||||
""");
|
||||
log.info("[LogCleanup] batch_job_instance (고아): {}건 삭제", jobInst);
|
||||
total += jobInst;
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
@ -104,6 +104,7 @@ app:
|
||||
batch:
|
||||
chunk-size: 10000
|
||||
sub-chunk-size: 5000 # Writer Sub-Chunk 분할 크기
|
||||
log-retention-days: 90 # 배치 로그 보관 기간 (일)
|
||||
source-schema:
|
||||
name: std_snp_data
|
||||
tables:
|
||||
|
||||
불러오는 중...
Reference in New Issue
Block a user