Skip to content
isdnetworks
Go back

주석 처리가 폐지는 아니다

24시간 뒤 자동 완료가 안 된다는 문의를 받고 원인을 추적했다. 옛 시스템의 스케줄러를 열어 그 명령이 걸린 줄을 찾았다.

Table of contents

Open Table of contents

증상 — 주석 처리된 스케줄

그 줄은 이렇게 돼 있었다.

// $schedule->command('order:cancel-auto-complete')->hourly();

order:cancel-auto-complete 가 주석 처리돼 있으니 기능을 껐구나 싶었다.

자동 완료 기능이 비활성화돼 있다고 그대로 답할 뻔했다. 증상과 그 // 한 줄이 딱 맞아떨어져 더 볼 이유가 없어 보였다.

그대로 답할 뻔했다

그런데 그 답에는 설명되지 않는 구석이 하나 남아 있었다.

왜 껐는지가 설명되지 않았고 껐으면 대체가 있거나 요구사항이 없어졌어야 하는데 둘 다 확인하지 않았다.

// 한 줄이 그 자리에서 답을 주는 것처럼 보였다. 그것이 왜 그렇게 됐는지는 아무것도 말해 주지 않았다.

껐다는 사실은 상태이고 왜 껐는지는 이유다. 상태만 보고 답하면 그 // 가 나온 맥락을 통째로 건너뛴다. 껐다는 것만 알고 이유를 모르면 되살려도 되는지조차 못 정한다.

원인 — 신 시스템에 있었다

이 시스템은 옛 schedule 과 새 @Scheduled 가 함께 도는 기간이었다.

@Scheduled(cron = "0 */5 * * * ?")
fun processOrderCancel() {
    val claims = repository.findByTypeAndStatus("cancel", "ready")
    claims.forEach { kafka.send(it) }
}

processOrderCancel 이 5분 주기로 같은 일을 하고 있었다.

kafka.send 만 하고 끝나는지도 봤다.

class CancelHandler {
    fun handle(msg: CancelMessage) = when (msg.claimStatus) {
        "ClaimReady"  -> confirmCancel(msg)    // 승인
        "ClaimDone"   -> completeCancel(msg)   // 완료
        "ClaimReject" -> rejectCancel(msg)     // 거부
    }
}

CancelHandlerclaimStatus 별로 처리하고 있었다.

kafka.send 만 있고 handle 이 없으면 job 이 쌓이기만 하는데 양쪽이 다 있었다. 여기까지 보고 나니 그 // 가 폐지가 아니라 이관이라는 것이 분명해졌다.

주기도 달랐는데 hourly 쪽은 한 시간이고 @Scheduled 쪽은 5분이다. 옮기면서 주기까지 다시 정한 흔적으로 읽힌다. 그대로 옮긴 것이 아니라 옮기면서 값을 다시 정한 셈이다.

제약 — 확정하지 못한 부분

다만 이것을 확정할 근거가 약했다.

이관을 명시한 주석    없음
이관 커밋 메시지      확인 못 함

schedule->command@Scheduled 가 둘 다 있다는 것으로 판단한 것이다.

그래서 기록에는 이관을 명시한 주석과 커밋을 확인하지 못했고 두 저장소의 코드 병존으로 판단했다고 적었다.

// 옆에 이관을 적은 한 줄만 있었어도 확정이었을 텐데 없었다. 확정이라고 쓸 근거가 없을 때는 그것을 판단이라고 적는 편이 맞았다.

다음 사람이 그 강도를 알고 읽어야 잘못된 확신이 안 생긴다. 판단을 확정처럼 적으면 그 뒤의 결정이 전부 그 위에 쌓인다.

대응 — 바뀐 조사 방향

이것으로 문의 조사의 방향이 바뀌었다.

[처음]  옛 스케줄러가 꺼져 있다  →  켜면 되나?
[실제]  신 시스템이 도는데 안 된다  →  거기를 봐야 한다

hourly 쪽을 켜면 @Scheduled 와 같은 대상을 처리해 이중 처리가 된다.

주석을 폐지로 읽고 되살리는 것이 그 상황에서 가장 나쁜 선택이었고 되살리기 전에 다른 쪽을 확인하는 것이 순서였다. 고치기 전에 지금 무엇이 실제로 도는지부터 보는 것이 먼저였다.

미처리 원인은 새 쪽의 수집과 소비 구간에서 찾아야 했고 방향이 바뀐 뒤에야 볼 곳이 정해졌다.

교훈 — 주석에 적혀 있어야 할 것

이 조사가 길어진 이유는 그 줄에 아무 이유도 없었기 때문이다.

// v2 의 OrderCancelProcessorJob 으로 이관 (2018-xx)
// $schedule->command('order:cancel-auto-complete')->hourly();

OrderCancelProcessorJob 을 적은 한 줄이면 됐고 그 한 줄이 없어서 두 저장소를 다 뒤졌다.

주석 처리한 코드에는 왜 껐는지와 옮긴 곳까지 적어야 하고 껐다는 사실만 남으면 다음 사람이 같은 조사를 다시 한다.

병존 구조에서는 한쪽만 봐서는 판단이 안 된다.

옛 것에 없다  →  없는 게 아니라 새 것에 있을 수 있다
새 것에 없다  →  아직 안 옮겨져 옛 것에 있을 수 있다

항상 양쪽 스케줄러를 보고 어느 쪽이 실제로 도는지도 확인해야 한다. 둘 다 돌고 있으면 그것대로 이중 처리이고 둘 다 꺼져 있으면 그때가 진짜 폐지다.

병존 기간에는 한쪽 저장소의 코드가 그 기능의 전부가 아니고 어디에 있느냐보다 어느 쪽이 도느냐가 답이었다.

정리


Share this post on:

Previous Post
경로 하나에 근거 넷
Next Post
백 초쯤 지나면 끊기던 연결