PIA 공지 자동 수집에서 사용한 코드.
private final AtomicBoolean collectionRunning =
new AtomicBoolean(false);
자동 수집이 겹치지 않게 하려고 넣었다.
처음에는 boolean으로 해도 되지 않나 싶었는데
확인하고 값을 바꾸는 작업이 따로 실행되면 동시에 들어온 작업이 둘 다 통과할 수 있다.
if (collectionRunning) {
return;
}
collectionRunning = true;
그래서 AtomicBoolean의 compareAndSet()을 사용했다.
if (!collectionRunning.compareAndSet(false, true)) {
log.warn(
"외부공지 자동 수집 건너뜀: 이전 실행이 아직 진행 중입니다. trigger={}",
trigger
);
return;
}
현재 값이 false일 때만 true로 바꾼다.
성공하면 true
이미 true면 변경하지 않고 false
즉
수집 안 하는 중
→ false
→ compareAndSet(false, true)
→ true로 변경
→ 수집 시작
이미 수집 중이면 이번 실행은 건너뛴다.
수집이 끝나면 다시 false로 돌려줘야 한다.
try {
collectionService.runCollection();
} catch (RuntimeException exception) {
log.error("외부공지 자동 수집 실패: trigger={}", trigger, exception);
} finally {
collectionRunning.set(false);
}
오류가 나도 상태를 풀어줘야 하니까 finally에서 처리했다.
이 AtomicBoolean은 ExternalNoticeScheduler 안에 있는 값이다.
그래서 스케줄러 실행끼리 겹치는 건 막을 수 있다.
수동 수집 API는 이 값을 확인하지 않아서
수동 수집과 자동 수집이 동시에 실행되는 것까지 막는 건 아니다.
서버가 여러 대인 경우도 마찬가지로 각 서버마다 값이 따로 있다.
compareAndSet(false, true)
→ false인지 확인하고 true로 바꾸는 걸 한 번에 처리
내 코드에서는 이 정도로 기억해두면 될 것 같다.