Open 0JUUU opened 2 years ago
CONTINUABLE
: 작업이 남음FINISHED
: 더 이상 반복 ❌ SimpleLimitExceptionHandler
: 기본값으로 예외 타입 중 하나가 발견되면 카운터 증가 & 한계 (limit) 초과되었는지 여부를 확인하고 Throwable을 다시 던짐LogOrRethrowExceptionHandler
: 예외를 로그로 기록할지 아니면 예외로 던질지 결정RethrowOnThresholdExceptionHandler
: 지정된 유형의 예외가 임계값에 도달하면 다시 발생@Bean
public Step step1() throws Exception {
return stepBuilderFactory.get("step1")
.<String, String>chunk(5)
.reader(new ItemReader<String>() {
int i = 0;
@Override
public String read()
throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
i++;
return i > 3 ? null : "item" + i;
}
})
.processor(new ItemProcessor<String, String>() {
RepeatTemplate repeatTemplate = new RepeatTemplate();
@Override
public String process(String item) throws Exception {
repeatTemplate.setExceptionHandler(simpleLimitExceptionHandler()); // 몇 번의 예외가 발생하면 종료
repeatTemplate.iterate(new RepeatCallback() {
int i = 0;
@Override
public RepeatStatus doInIteration(RepeatContext context) throws Exception {
i++;
System.out.println("repeatTemplate testing " + i);
throw new RuntimeException(">> Exception is occurred");
// return RepeatStatus.CONTINUABLE;
}
});
return item;
}
})
.writer(System.out::println)
.build();
}
@Bean
public Step step1() throws Exception {
return stepBuilderFactory.get("step1")
.<String, String>chunk(5)
.reader(new ItemReader<String>() {
int i = 0;
@Override
public String read() throws NoSkippableException {
i++;
if(i == 3) {
throw new NoSkippableException("skip");
}
System.out.println("ItemReader : " + i);
return i > 20 ? null : String.valueOf(i);
}
})
.processor(itemProcessor())
.writer(itemWriter())
.faultTolerant()
.noSkip(NoSkippableException.class)
.build();
}
public class RetryItemProcessor implements ItemProcessor<String, String> {
private int cnt = 0;
@Override
public String process(String item) throws Exception {
if (item.equals("2") || item.equals("3")) {
cnt++;
throw new RetryableException("failed cnt : " + cnt);
}
return item;
}
}
2, 3 지나가고 잘 동작할 줄 알았는데 Exception 발생
🤔 왜?
System.out.println("item = " + item);
출력해서 확인해보자
재시도가 일어나면 Chunk의 처음 단위로 넘어감 ➡️ 아예 처음부터 다시 시작해서 0번째부터 restart
0 ➡️ 1 ➡️ 2 🔥(예외) ➡️ 0 ➡️ 1 ➡️ 2 🔥 ➡️ 0 ➡️ 1 ➡️ 터져버림💥
재시도는 항상 처음부터 시작
해결 : 0, 1, 2 예외터지고 재시도할 때 2 실행 안하고 바로 3으로 갈 수 있도록 (예외가 발생했던 부분은 건너뛰고 바로 다음 단계)
이걸 Skip으로 해결
Retry와 Skip으로 함께 해결하면 됨
public class RetryItemProcessor2 implements ItemProcessor<String, Customer> {
@Autowired
private RetryTemplate retryTemplate;
private int cnt = 0;
@Override
public Customer process(String item) throws Exception {
Classifier<Throwable, Boolean> rollbackClassifier = new BinaryExceptionClassifier(true);
Customer customer = retryTemplate.execute(new RetryCallback<Customer, RuntimeException>() {
@Override
public Customer doWithRetry(RetryContext context) throws RuntimeException {
if (item.equals("1") || item.equals("2")) {
cnt++;
throw new RetryableException("failed cnt : " + cnt);
}
return new Customer(item);
}
}, new RecoveryCallback<Customer>() {
@Override
public Customer recover(RetryContext context) throws Exception {
return new Customer(item);
}
}, new DefaultRetryState(item, rollbackClassifier));
return customer;
}
}