WEBBOOK CHAPTER

실무 스프링 배치 6: 30장. ItemStream과 ExecutionContext를 직접 검증한다

30장. ItemStream과 ExecutionContext를 직접 검증한다

restart 가능한 reader는 어디까지 읽었는지 ExecutionContext에 저장한다. 값은 개발자가 보는 임시 메모가 아니라 다음 실행의 동작을 바꾸는 영속 상태다. key 이름이 바뀌거나 serializer가 달라지면 과거 실행을 이어 갈 수 없다.

custom reader를 만들 때 open은 저장된 offset을 읽고, update는 commit 직전에 다음 위치를 기록하며, close는 자원을 닫는다. item을 읽을 때마다 외부 파일에 offset을 쓰는 방식은 DB transaction과 원자적이지 않다. chunk rollback 뒤 offset만 앞서가면 행을 잃는다.


final class CursorReader implements ItemStreamReader<OrderRow> {
  private int nextIndex;
  public void open(ExecutionContext context) {
    nextIndex = context.getInt("orders.nextIndex", 0);
  }
  public OrderRow read() { return nextIndex < rows.size() ? rows.get(nextIndex++) : null; }
  public void update(ExecutionContext context) {
    context.putInt("orders.nextIndex", nextIndex);
  }
  public void close() { }
}

실습에서는 250건, chunk 100으로 실행해 201번째 처리 중 실패시킨다. repository context의 orders.nextIndex, commit count와 output 수를 비교한다. restart 후 빠짐·중복 없이 250개의 업무 키가 남아야 한다. reader 이름이 바뀌면 context key namespace가 달라질 수 있으므로 bean·stream name도 호환성 계약이다.

ExecutionContext에 대형 객체, 고객 원문, secret을 넣지 않는다. 필요한 최소 cursor, checksum, version만 넣는다. serializer 변경 전에는 과거 실패 instance 수, restart 필요 기간과 migration 가능성을 조사한다.