Skip to content
isdnetworks
Go back

없는 레코드를 영원히 기다린다

(수정됨)

출금 한 건이 사흘째 대기 상태로 멈춰 있다는 이야기가 들어왔다. 실패한 것도 아니고 끝난 것도 아닌 채였다.

Table of contents

Open Table of contents

증상 — 사흘째 대기

출금 처리 워커의 매핑 함수를 열었다.

private function mapSignature($withdrawal)
{
    $sig = $this->findSignature($withdrawal->custody_id);

    if (!$sig) {
        return ['result' => 'pending'];
    }
    ...
}

findSignature 가 빈 값을 내면 그대로 대기를 반환한다.

이 건은 custody_signatures 쪽 대응 항목이 애초에 없는 상태였다. $sig 가 나중에 생기기를 기다리는 구조라서 끝이 없었다.

원인 — 시도 횟수가 안 늘었다

대기로 빠지는 자리를 더 봤다.

if ($result['result'] === 'pending') {
    $withdrawal->status = 'pending';
    $this->withdrawals->save($withdrawal);
    return;              // 시도 횟수 증가 없음
}

$withdrawal->status 만 pending 으로 바꾸고 시도 횟수는 건드리지 않은 채 빠져나간다.

보통은 시도가 쌓이면 한도를 넘어 실패로 빠지고 그때 알림이 나가거나 목록에 잡힌다. 여기서는 한도에 닿을 길이 없으니 아무 신호 없이 영원히 대기였다.

전체 흐름 — 왜 없는지의 경위

대응 항목이 왜 없는지 이력을 역추적했다.

1. 출금 요청  →  위탁 지갑에 서명 요청 생성
2. 그 요청이 사용자 취소로 지갑 쪽에서 폐기됨
3. 사용자가 같은 금액으로 출금을 다시 요청
4. 우리 쪽이 옛 custody_id 를 재사용 → 서명 레코드가 없음
5. 매핑 실패 → 영원히 대기

두 번째 줄의 사용자 취소 가 관건이었다.

서명 요청이 폐기되면 거기에 딸린 custody_signatures 행도 함께 정리된다. 그 뒤에 재요청이 옛 custody_id 를 물고 들어오면 새 요청에는 서명이 없는 상태로 넘어온다.

검증 — 같은 패턴을 세었다

이 건 하나만인지 확인했다.

대기 상태로 방치      몇 건
오류 상태            수백 건

대기 쪽에 수개월 방치된 것들이 섞여 있었다.

오류 는 그래도 집계에 잡히는데 대기 는 아무 데도 안 잡힌다. 정체된 건을 만나면 그 항목에 대응하는 레코드가 있는지부터 본다는 순서를 그때 정했다.

SELECT COUNT(*) FROM custody_signatures WHERE custody_id = ?;

COUNT(*) 가 0이면 이 유형이다.

선택지 — 세 가지 해결 방향

수동 해결 방향을 셋으로 정리했다. 후보는 원인 쪽 정리와 상태 전환과 레코드 생성이다.

① 지갑 쪽에서 요청을 새로 발급     원인 쪽을 정리한다
② 상태를 오류로 강제 전환         대기에서 빼서 목록에 잡히게 한다
③ 수동으로 서명 레코드 생성       없는 것을 만들어 진행시킨다

① 이 가장 깨끗하지만 위탁 지갑 관리 화면에서 해야 한다.

③ 이 가장 위험했다. 서명이 없는 데에는 이유가 있는데 그 이유를 모른 채로 만들면 보내지 않은 것을 보낸 것처럼 기록하는 셈이다.

대응 — 보이게 만드는 것이 먼저

② 를 골랐다. 이유는 ① 은 지갑 쪽 협조가 필요하고 ③ 은 없는 데이터를 만드는 것인데 ② 는 우리 안에서 되고 보이게 만들어서다.

① 은 지갑 쪽 협조가 필요
③ 은 없는 데이터를 만드는 것
② 는 우리 안에서 되고, 보이게 만든다

대기 는 보이지 않는 것이 문제라서 오류 로 바꾸면 최소한 집계에 잡힌다.

대기 라는 말은 곧 될 것이라는 뜻으로 읽힌다. 될 조건이 영영 안 생기는 건이 그 상태로 남아 있으면 그 표시 자체가 거짓 신호다.

근본은 따로 적어 두었다.

대응 레코드 없음
    ↓
시도 횟수 증가
    ↓
한도 초과 시 오류로 전환

곧 될 대기와 영영 안 될 대기를 시도 횟수로 가르는 것이다.

몇 번 시도해도 안 되면 그것은 대기가 아니라 문제다. 그 구분이 코드에 없으면 상태 이름이 실제 상황과 어긋난 채로 남는다.

정리


Share this post on:

Previous Post
플래그 하나를 두 기능이 쓴다
Next Post
24시간 멈추면 안 되는 시스템을 맡는다는 것