Skip to content
isdnetworks
Go back

전파가 환불에 매달려 있었다

취소가 채널에 반영이 안 된다는 문의가 왔다. 우리 쪽 상태부터 봤다.

Table of contents

Open Table of contents

증상 — 우리는 완료, 전파는 실패

상태 컬럼 셋을 꺼냈다.

SELECT cancel_status, distribution_cancel_status, distribution_claim_id
  FROM order_cancels WHERE order_id = ?;
cancel_status                complete
distribution_cancel_status   fail
distribution_claim_id        NULL

cancel_statuscomplete 인데 distribution_cancel_statusfail 이다.

전파 작업을 찾아봤더니 그 행 자체가 없었다.

SELECT * FROM distribution_jobs WHERE ... AND job = 'cancel';

distribution_jobs 에 실패한 행이 남은 것이 아니라 행이 아예 안 만들어진 상태였다. 다시 돌릴 대상이 없으니 재시도로 해결될 일이 아니었다.

원인 — 발행 지점이 환불에 있었다

이 작업을 누가 만드는지 역추적했다.

grep -rn "JobCompleteCancel" app/

한 곳이 나왔다.

// Order/Refund/Helper.php
public function completeRefund($refund)
{
    ...
    JobCompleteCancel::dispatch($order);
}

JobCompleteCancel::dispatch 가 취소 처리부가 아니라 completeRefund 안에 있었다.

[예상]  취소 처리 → 전파 작업 생성
[실제]  환불 완료 → 전파 작업 생성

전파가 취소가 아니라 환불에 매달려 있는 구조였다. 취소만 하고 completeRefund 를 안 지나가면 그 작업은 만들어지지 않는다.

환불이 없었다

그 주문에 환불이 있는지 셌다.

SELECT COUNT(*) FROM order_refunds WHERE order_id = ?;
0

환불이 없으니 completeRefund 를 지날 일이 없었다.

왜 환불이 없는지도 따라갔다.

SELECT provider_id FROM orders WHERE id = ?;
SELECT provider_id FROM distribution_orders WHERE order_id = ?;
NULL
NULL

퇴점한 입점사의 주문이라 ordersdistribution_orders 양쪽의 provider_id 가 비어 있었다.

제약 — 구조적으로 불가능한 경로

퇴점 처리되면서 provider_id 가 가리키던 결제 정보와의 연결이 끊긴 것으로 보인다.

환불하려면 결제 정보가 필요

없음

환불 레코드 안 생김

전파 작업 안 생김

코드나 자료를 손봐서 될 문제가 아니라 이 경로로는 도달할 수 없는 상태였다.

몇 번을 다시 돌려도 결과가 같은 종류다. order_refunds 가 안 생기는 한 이 주문에서는 연동이 성립하지 않는다.

남은 길은 외부 관리 화면에서 직접 취소하는 것이고 그것은 운영이 손으로 해야 한다. 고칠 수 있는 문제와 다른 경로로 넘겨야 하는 문제를 가르는 것이 여기서 필요했다.

조치 — 바뀐 확인 순서

이 건으로 같은 문의가 왔을 때의 순서가 정해졌다.

[전]  전파 작업 확인 → 없음 → 왜 없지 → 클레임 확인 → ...
[후]  환불 레코드 존재 확인 → 없으면 여기서 끝

distribution_jobs 부터 보면 없다는 사실만 알고 왜 없는지는 모른다.

SELECT COUNT(*) FROM order_refunds WHERE order_id = ?;

이 한 줄로 구조적으로 불가한 건인지 아닌지가 갈린다.

조사에서 먼저 볼 것을 고르는 기준이 거기 있었다. 결과를 가장 크게 가르는 조회를 앞에 두면 나머지 단계를 안 밟게 된다.

검증 — 미발생을 찾는 점검

왜 환불에 매달았는지도 짚어 봤다.

[취소 시점에 전파]  취소했지만 환불이 안 될 수도 있음
[환불 완료에 전파]  돈이 돌아간 뒤에 밖에 알림

돈 처리가 끝난 뒤에 알리는 것은 그 자체로 안전한 순서다.

먼저 알리고 환불이 실패하면 밖에서는 complete 로 보이는데 돈은 안 돌아간 상태가 된다. 다만 이 설계는 환불이 항상 있다는 전제 위에 서 있고 이번 건이 그 전제가 깨지는 경우였다.

전제가 깨지면 조용히 빠지는 것이 이 구조의 성질이다.

[에러]  작업이 실패로 남음 → 눈에 띔
[미생성]  작업이 없음 → 안 보임

distribution_jobs 의 실패 목록에 안 뜨니 문의가 오기 전까지 아무도 모른다.

없는 것을 찾으려면 있어야 할 것과 대조하는 수밖에 없다.

SELECT o.id FROM orders o
  JOIN order_cancels c ON c.order_id = o.id
 WHERE c.cancel_status = 'complete'
   AND c.distribution_cancel_status <> 'success'
   AND NOT EXISTS (SELECT 1 FROM order_refunds r WHERE r.order_id = o.id);

cancel_status 는 완료인데 전파가 안 됐고 order_refunds 도 없는 건을 찾는다.

이 수가 0이 아니면 같은 케이스가 쌓이고 있다는 뜻이다. 앞서 본 것들도 같은 모양이었다. 실패한 중지 위에 삭제가 얹혀 사라진 건이나 승인이 필터에 걸린 건이 전부 오류가 아니라 미발생이었다.

정리


Share this post on:

Previous Post
다섯으로 수렴한 실패 사유
Next Post
두 갱신이 서로를 기다렸다