RunIdIncrementer - ์์ ํ uniqueํ์ง ์๋ค.
JobInstanceAlreadyCompleteException ํน์ JobExecutionAlreadyRunningException์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ
batch job์ run.id ์ job parameter๊ฐ ๋์ผํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ๊ฒฝ์ฐ์ผ ํ๋ฅ ์ด ํฌ๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด spring batch์์ run.id๋ฅผ ์๋์ผ๋ก 1์ฉ ์ฆ๊ฐ์์ผ ๋์ผํ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ๋ฌ๋ฒ ์ฌ์ฉํ ์ ์๋๋ก ์ค์ ํ๋ค.
@Bean
public Job myBatchJob() {
return jobBuilderFactory.get("myBatchJob")
.incrementer(new RunIdIncrementer()) // RunIdIncrementer ์ ์ฉ
.start(myStep())
.build();
}
ํ์ง๋ง RunIdIncrementer๋ ์๋ฒฝํ ๊ณ ์ ์ฑ์ด ๋ณด์ฅ๋์ง ์๋๋ค.
๋์ผํ ์๊ธฐ์ ์ฌ๋ฌ ๋ฐฐ์น๊ฐ ๋์ํ๋ ๊ฒฝ์ฐ ๋์ผํ run id๊ฐ ์์ฑ๋ ์ ์๋ค.
Batch ์คํ ์ ๋ณด ์ดํด๋ณด๊ธฐ
ํด๊ฒฐ๋ฐฉ๋ฒ์ ์ฐพ๊ธฐ์ run id์ job ํ๋ผ๋ฏธํฐ ๋ฑ ๋ฐฐ์น ์คํ ์ ๋ณด๋ฅผ ์ด๋ค์์ผ๋ก ์ด๋์ ์ ์ฅ๋์ด ์๋์ง ์์๋ณผ ๊ฒ์ด๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก batch์ ๋ฉํ ๋ฐ์ดํฐ๋ ๋ด์ฅ H2 DB์ ์ ์ฅ๋๋ค.
์ด DB๋ ๋ฉ๋ชจ๋ฆฌ ์์์ ์ด์๋๋ฏ๋ก ์ดํ๋ฆฌ์ผ์ด์ ์ด ์ข ๋ฃ๋๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ ์๊ฐ๋ฒ๋ฆฐ๋ค.
์ ๋ณด๋ฅผ ์ ์งํ๊ณ ์ถ์ ๊ฒฝ์ฐ spring batch application.yaml์ ๊ธฐ๋ณธ ์ธ๋ถ DB๋ฅผ ์ฐ๊ฒฐํ๋ฉด ๋๋ค.
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://your-mysql-host:3306/your-database
username: your-username
password: your-password
์ ์ฅ๋๋ ์ ๋ณด๋ ๋ค์๊ณผ ๊ฐ๋ค.
BATCH_JOB_INSTANCE : ๊ฐ ์์ ์ธ์คํด์ค์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ
BATCH_JOB_SEQ : 'BATCH_JOB_INSTANCE.JOB_INSTANCE_ID'์ ๊ณ ์ ๊ฐ์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ
BATCH_JOB_EXECUTION : ๊ฐ ๋ฐฐ์น ์์ ์ ์คํ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ, ์์ ์คํ์ ๋ํ ์ํ ๋ฐ ํ์์คํฌํ ์ ๋ณดBATCH_JOB_EXECUTION_CONTEXT : ๊ฐ ์์ ์คํ์ ๋ํ `ExecutionContext`์ ์ง๋ ฌํ๋ ํํ์ ์ ์ฅBATCH_JOB_EXECUTION_PARAMS : ์์ ์คํ์ ์ ๋ฌ๋ ํ๋ผ๋ฏธํฐ ์ ๋ณด๋ฅผ ์ ์ฅ
BATCH_JOB_EXECUTION_SEQ : 'BATCH_JOB_EXECUTION.JOB_EXECUTION_ID'์ ๊ณ ์ ๊ฐ์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ
BATCH_STEP_EXECUTION : ๊ฐ ๋ฐฐ์น ์คํ ์ ์คํ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅ, ์คํ ์คํ์ ๋ํ ์ํ ๋ฐ ํ์์คํฌํ ์ ๋ณด
BATCH_STEP_EXECUTION_CONTEXT : ๊ฐ ์คํ ์คํ์ ๋ํ `ExecutionContext`์ ์ง๋ ฌํ๋ ํํ์ ์ ์ฅ
BATCH_STEP_EXECUTION_SEQ : 'BATCH_STEP_EXECUTION.STEP_EXECUTION_ID'์ ๊ณ ์ ๊ฐ์ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ
๊ฐ์กฐํ 3๊ฐ์ง ํ ์ด๋ธ์ ๊ด๊ณ๋ง ๊ฐ๋จํ ์ดํด๋ณด์๋ฉด
BATCH_JOB_INSTANCE์๋ job์ด ์คํ๋ ๋๋ง๋ค job instance id์ job name์ด ์ ๊ท๋ก ์์ฑ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ๋์ job instance์๋ ์ฌ๋ฌ๊ฐ์ job execution์ด ์์ ์ ์๋๋ฐ (job์์์ execution์ด ์คํจ ํ ์ฌ์๋ ๋๊ฑฐ๋ chunk ๊ธฐ๋ฐ ์ฒ๋ฆฌ ์ฒ๋ผ ๋ณ๋ ฌ์ฒ๋ฆฌ๋ก ์ธํด job execution์ด ์ฌ๋ฌ๊ฐ ์์ฑ๋๋ ๊ฒฝ์ฐ) job execution์ ๋ํ ์ ๋ณด๋ BATCH_JOB_EXECUTION์ ์ ์ฅ๋๋ค.
๊ฐ execution์ ์ฌ์ฉ๋ parameters๋ BATCH_JOB_EXECUTION_PARAMS์ ์ ์ฅ๋๋ ์์ด๋ค.
๊ฐ๋ฅํ๋ค๋ฉด DB์์ ๋ฌธ์ ๊ฐ ๋๋ run.id๋ฅผ ์กฐํํด๋ณด๊ณ ์ด๋ฏธ ์คํ๋ ๊ธฐ๋ก์ด ์๋์ง ์ฐพ์๋ณด์.
๋ง์ฝ ์ด๋ฏธ ๊ธฐ๋ก์ด ์๋ค๋ฉด ์๋ ํด๊ฒฐ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ๋ฅํ ๊ฒ์ด๊ณ ์๋๋ผ๋ฉด ๋ค๋ฅธ ์ ๋ณด๋ฅผ ์ฐพ๋ ๊ฒ์ด ์ข์ ๊ฒ์ด๋ค.
๊ณ ์ ํ parameter ์๋ ์์ฑ
๋ฌธ์ ๋ก ๋์๊ฐ์ JobInstanceAlreadyCompleteException ํน์ JobExecutionAlreadyRunningException์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ job ๋ง๋ค parameter๋ฅผ ๋ค๋ฅด๊ฒ ์ฃผ๋ ๊ฒ์ด๋ค.
ํด๊ฒฐ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒ๋ค์ด ์๋ค.
- run.id๋ฅผ ์ปค์คํ
ํ๊ฒ ์ค์
: run.id๊ฐ ์ ์ญํ ์ ๋ค ํ๊ฒ ํ๋ ๋ฐฉ๋ฒ
- JobLauncher๋ฅผ ์์ํ์ฌ ์ปค์คํ
: ๋ชจ๋ job์ job incremeter๋ฅผ ๋ณ๊ฒฝํ์ง์๊ณ , ์ ์ฒด ์ ์ฉ์ ์ํ๋ ๊ฒฝ์ฐ - JobParametersIncrementer๋ฅผ ์์ํ์ฌ ์ปค์คํ
: ์ฌ๋ฌ๊ฐ์ง job incremeter๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
- JobLauncher๋ฅผ ์์ํ์ฌ ์ปค์คํ
- ์ปค์คํ
ํ parameter ๊ฐ ์ถ๊ฐ
: ๋ณ๋์ parameter ์ถ๊ฐ๊ฐ ์๊ด์์ ๋
JobLauncher๋ฅผ ์์ํ์ฌ ์ปค์คํ
import org.springframework.batch.core.*;
import org.springframework.batch.core.launch.JobLauncher;
import java.util.Date;
public class CustomJobLauncher implements JobLauncher {
private final JobLauncher jobLauncher;
public CustomJobLauncher(JobLauncher jobLauncher) {
this.jobLauncher = jobLauncher;
}
@Override
public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException {
JobParametersBuilder builder = new JobParametersBuilder(jobParameters)
.addDate("currentTime", new Date());
return jobLauncher.run(job, builder.toJobParameters());
}
}
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class BatchConfiguration {
private final JobLauncher jobLauncher;
public BatchConfiguration(JobLauncher jobLauncher) {
this.jobLauncher = jobLauncher;
}
@Bean
@Primary
public JobLauncher currentTimeJobLauncher() {
return new CurrentTimeJobLauncher(jobLauncher);
}
}
๊ธฐ๋ณธ๊ฐ์ผ๋ก customJobLauncher๋ฅผ ์ฌ์ฉํ๋๋ก ์ค์
JobParametersIncrementer๋ฅผ ์์ํ์ฌ ์ปค์คํ
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersIncrementer;
public class CurrentTimeMillisIncrementer implements JobParametersIncrementer {
@Override
public JobParameters getNext(JobParameters parameters) {
return new JobParametersBuilder(parameters)
.addLong("run.id", System.currentTimeMillis())
.toJobParameters();
}
}
์ปค์คํ ํ parameter ๊ฐ ์ถ๊ฐ
mport org.springframework.beans.factory.annotation.Value;
import javax.annotation.PostConstruct;
import java.util.Date;
public class CustomJobParameters {
@Value("#{jobParameters[chunkSize]?:100}")
private Integer chunkSize;
@Value("#{jobParameters[currentTime]?:T(java.lang.System).currentTimeMillis()}")
private Long currentTime; // ๊ฐ์ ๋ฃ์ง ์์ผ๋ฉด ํ์ฌ์๊ฐ์ด ์ค์ ๋๋๋ก ์ธํ
}
'๊ฐ๋ฐ > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JDBC Templete + PostgreSql ERROR (Can't infer the SQL type to use for an instance of java.util.ArrayList.) (0) | 2022.05.09 |
---|---|
domain, entity, dao, dto, vo ?? (0) | 2022.05.06 |
์คํ๋ง ์น ๊ฐ๋ฐ ๋ฐฉ์ (static / MVC / API) (0) | 2022.03.03 |
Spring ํ๋ก์ ํธ ์์ฑ (Gradle) (0) | 2022.03.03 |
ZonedDateTime (UTC -> KST) (0) | 2022.02.23 |