Skip to content
isdnetworks
Go back

pending은 오류가 아니다

(수정됨)

한 채널의 교환 주문이 만들어졌는데 후속 교환 주문이 안 생긴다는 문의가 왔다. laravel.log 에도 failed_jobs 에도 오류는 남아 있지 않았다.

Table of contents

Open Table of contents

증상 — 성공 건과 방치 건의 대조

같은 유형에서 정상으로 처리된 건이 있어서 그것과 안 된 셋을 나란히 놓고 상태를 비교했다. 성공한 건만 order_items 의 일차 교환 항목이 status = 'exchange' 를 유지하고 있었고 그 아래에 return_items 행이 살아 있었다.

방치된 셋은 일차 항목이 cancelled 나 shipped 로 바뀌어 있었고 return_items 행이 없었다. 오류 로그가 없을 때 성공 건과 나란히 놓는 것이 유일한 출발점이었다.

원인 — 선행 상태에 의존한 매핑

코드를 보니 mapExchange() 가 일차 교환 항목의 return_items 를 찾아 매핑하는데 없으면 pending 을 돌려주고 있었다. throw 하는 것이 아니라 정상 흐름의 한 상태로 다루고 있었다.

그리고 return_items 행은 일차 항목이 exchange 를 유지할 때만 살아 있다. 선행 상태가 다른 값으로 바뀌면 그 항목이 사라지므로 매핑이 영영 성립하지 않는다.

영구가 된 대기 상태

pending 을 받은 호출부는 exchange_orders.status 를 pending 으로 바꾸고 다음 스케줄에 다시 시도하겠다는 전제로 넘어간다. 그런데 다시 시도해도 선행 상태는 안 바뀌므로 같은 결과가 나온다.

재시도로 풀리는 대기와 안 풀리는 대기를 구분하지 않으면 뒤의 것이 영구 정지 상태가 된다. 코드는 정상 흐름을 돌고 있고 결과만 영원히 나오지 않는다.

조용한 이유

예외가 아니므로 laravel.log 에 없고 failed_jobs 에도 안 쌓이므로 실패 지표도 없다. 정상 흐름의 한 상태이므로 알림도 걸려 있지 않다.

그래서 고객이 교환이 안 됐다고 말할 때까지 아무도 모른다. 문의가 사실상 감시 역할을 하고 있는 상태였다.

조치 — 선례가 없다는 확인

대응 방법을 정하기 전에 이 유형을 전에 수동으로 처리한 적이 있는지 manual_actions 를 조회했다. 전 채널과 전 기간에 걸쳐 하나도 없었다.

선례가 있으면 그것을 따르면 되고 없으면 내가 만드는 것이 선례가 되므로 무엇을 왜 했는지 남겨야 한다. 없다는 것도 조회로 확인해야지 안 찾아보고 없을 것이라고 말하지 않는다.

두 가지 방법이 있었는데 셋을 손으로 후속 교환 주문을 만들어 주는 것과 mapExchange() 를 고쳐 선행 상태가 바뀐 경우 failed 를 돌려주게 배포하는 것이다. 앞쪽을 먼저 하고 뒤쪽은 다음 배포에 넣었다. 이유는 셋은 고객이 기다리고 있고 코드 수정은 배포 주기를 타서다. 대신 배포 전에 같은 유형이 또 나오면 손으로 또 해야 하는 것을 감수했고 그 사실을 manual_actions 에 사유와 함께 적었다.

정리


Share this post on:

Previous Post
아무것도 증명하지 않는 통과
Next Post
잠긴 것이 아니라 기다리는 중