들어가기전
JobInstance, JobExecution 의 개념은 알고가자.
https://devfunny.tistory.com/476?category=820618
예제코드
- JobExecutionConfiguration
package com.spring.batch.job;
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@RequiredArgsConstructor
public class JobExecutionConfiguration {
// job 생성
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
@Bean
public Job JobExecutionTestJob() {
return this.jobBuilderFactory.get("JobExecutionTestJob")
/* step start */
.start(JobExecutionTestStep1())
.next(JobExecutionTestStep2())
.build();
}
@Bean
public Step JobExecutionTestStep1() {
return stepBuilderFactory.get("JobExecutionTestStep1")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("JobExecutionTestStep1 was executed");
return RepeatStatus.FINISHED;
}
})
.build();
}
@Bean
public Step JobExecutionTestStep2() {
return stepBuilderFactory.get("JobExecutionTestStep2")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("JobExecutionTestStep2 was executed");
/** 에러 발생 */
// throw new RuntimeException("step2 has failed"); // 에러 발생시키기
return RepeatStatus.FINISHED;
}
})
.build();
}
}
1) JobExecutionTestJob 이 실행되었다.
2) Job이 COMPLETED 상태로 수행 완료되었다.
테이블 | exec |
BATCH_JOB_INSTANCE | insert row 1 |
BATCH_JOB_EXECUTION | insert row 1 (COMPLETED) |
3) 다시 JobExecutionTestJob 을 실행시킨다.
4) 같은 job, parameter 로 수행되었으므로 이미 JobInsatance 가 존재한다는 에러가 발생한다.
[변환]
1) 위 과정을 통해 INSERT 된 데이터를 모두 지우자.
2) 코드 변경 - JobExecutionTestStep2()에서 에러를 발생시키자.
...
@Bean
public Step JobExecutionTestStep2() {
return stepBuilderFactory.get("JobExecutionTestStep2")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("JobExecutionTestStep2 was executed");
/** 에러 발생 */
throw new RuntimeException("step2 has failed"); // 에러 발생시키기
//return RepeatStatus.FINISHED;
}
})
.build();
}
...
3) BATCH_JOB_EXECUTION, BATCH_JOB_INSTANCE 테이블이 비워진 상태에서 JobExecutionTestJob 을 실행시킨다.
4) Job이 FAILED 상태로 수행 완료되었다.
테이블 | exec |
BATCH_JOB_INSTANCE | insert row 1 |
BATCH_JOB_EXECUTION | insert row 1 (FAILED) |
5) 여기서 다시 코드를 원복하자. (에러 발생 코드를 주석 처리한다.)
...
@Bean
public Step JobExecutionTestStep2() {
return stepBuilderFactory.get("JobExecutionTestStep2")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
System.out.println("JobExecutionTestStep2 was executed");
/** 에러 발생 */
// throw new RuntimeException("step2 has failed"); // 에러 발생시키기
return RepeatStatus.FINISHED;
}
})
.build();
}
...
6) 다시 JobExecutionTestJob 이 실행시켜보자.
7) Job이 COMPLETED 상태로 수행 완료되었다.
테이블 | exec |
BATCH_JOB_INSTANCE | 이미 존재하므로 데이터가 새로 insert 되지 않는다. |
BATCH_JOB_EXECUTION | insert row 1 (COMPLETED) |
이 이후로는 다시 해당 job을 수행시킨다면 또다시 이미 jobInstance가 존재한다고 에러가 발생할 것이다.
정리
JobExecution은 JobInstance 가 실행될 때마다 생성된다. JobInstance 는 위 예제에서 보이듯, 같은 job, jobParameter 로는 오직 1번만 실행된다. 하지만 만약 이전의 동일한 Job이 Failed 상태로 종료된다면 JobInstance를 재사용하여 잡 재실행이 가능하고 이렇게 실행될때마다 BATCH_JOB_EXECUTION은 1개씩 데이터가 insert 된다.
다시한번 아래 흐름을 이해해보자. 이해되지 않는다면 다시 처음으로 돌아가, 글을 읽어보자.
[첫번째 실행] JobA
JobInstanceId : 1
JobExecution
> JobInstanceId : 1
> JobExecutionId : 1
> Status : COMPLETED
[두번째 실행] jobB
JobInstanceId : 2
JobExecution
> JobInstanceId : 2
> JobExecutionId : 2
> Status : FAILED
[세번째 실행] jobB
JobInstanceId : 2
JobExecution
> JobInstanceId : 2 (재사용)
> JobExecutionId : 3
> Status : COMPLETED
'Coding > Spring Batch' 카테고리의 다른 글
스프링배치 StepContribution (0) | 2022.01.19 |
---|---|
SpringBatch 에서 StepExecution 알아보기 (0) | 2022.01.16 |
[스프링 배치] Spring Batch + mysql 설정하기 (0) | 2021.10.09 |
[스프링 배치] 두가지 포맷의 파일을 각 포맷(접두어)에 따라 처리하기 (PatternMatchingCompositeLineMapper , LineTokenizer, FieldSetMapper (0) | 2021.10.08 |
[스프링 배치] resources/ 경로의 파일 읽어와 여러 방법으로 필드 매핑하기 (FieldSetMapper, LineTokenizer) (0) | 2021.10.01 |