퇴점한 업체의 상품에서 실주문이 발생했다. 우리 목록에는 없는 상품이었다.
Table of contents
Open Table of contents
증상 — 목록에 없는 상품
먼저 조회했다.
SELECT * FROM distribution_products WHERE product_id = ?;
0건
deleted_at 을 포함해 보니 나왔다.
SELECT *, deleted_at FROM distribution_products
WHERE product_id = ? AND deleted_at IS NOT NULL;
deleted_at (1년 전)
deleted_at 이 1년 전으로 찍힌 소프트 삭제 상태였다.
목록에 없는데 주문이 들어온다면 우리 자료와 외부 상태가 갈려 있다는 뜻이다. 갈린 시점이 언제이고 무엇 때문인지를 찾아야 했다.
타임라인 — 시간순으로 봤다
작업 이력을 시간순으로 조회했다.
SELECT event, created_at, fail_status, last_log
FROM distribution_product_jobs
WHERE product_id = ? AND channel = ?
ORDER BY created_at;
두 줄이 결정적이었다.
(1년 반 전) stop FAIL 'SSG 최대 입력 가능한 상품명 글자수는
공백포함 90byte 입니다.(입력: 96byte)'
(1년 전) --- DP soft delete
stop 이 FAIL 로 끝난 뒤 반년쯤 지나 삭제가 이어졌다.
① 중지 작업 발사 → 실패 (글자수 초과)
② 실패를 아무도 안 봄
③ 퇴점 처리 → 소프트 삭제
④ 목록에서 사라짐
⑤ 밖에서는 계속 판매중
stop 이 안 됐는데 우리 쪽에서만 지운 것이었다.
원인 — 실패를 덮는 삭제
stop 실패만 있는 경우와 삭제까지 된 경우를 나란히 놓았다.
[중지 실패만 있었으면] 목록에 실패 상태로 남음 → 눈에 띔
[삭제까지 되면] 목록에서 아예 사라짐 → 안 보임
deleted_at 이 채워지면 화면과 목록에서 전부 빠진다.
실패한 작업을 찾는 조회도 deleted_at IS NULL 을 달고 있어 함께 빠지고 다시 시도할 기회가 사라진다. 실패가 해결된 것이 아니라 안 보이는 곳으로 들어간 것이다.
결과 — 밖에서는 판매중
우리 쪽에서 안 보이는 동안에도 외부에서는 계속 유효했다.
[우리] 이 업체 상품 없음
[밖] 판매중
판매중 이라 주문이 들어오는데 퇴점 업체라 처리할 사람도 없었다.
last_log 에 남은 실패 사유는 사소했다. 상한이 90바이트인데 96바이트가 들어가 6바이트 초과로 걸린 것이었다. 중지 요청인데 상품명 검증에 걸린 것은 상대 API 가 중지에도 전체 상품 데이터를 요구하기 때문이었다.
재발 방지 — 삭제 전에 확인한다
stop 과 삭제 사이의 순서를 한 단계 바꿨다.
[사고 순서] 중지 발사 → (실패) → 삭제
[안전 순서] 중지 발사 → 성공 확인 → 삭제
확인 쿼리도 함께 남겼다.
SELECT event, fail_status, last_log
FROM distribution_product_jobs
WHERE product_id = ? AND channel = ? AND event = 'stop'
ORDER BY created_at DESC LIMIT 1;
fail_status 가 실패면 삭제하지 않고 실패 상태로 목록에 남겨 둔다.
소프트 삭제는 정리가 아니라 감춤이었다. 문제가 해결돼서 없애는 것과 문제가 있는 채로 안 보이게 하는 것은 다르다. 해결 여부를 확인하지 않고 감추면 그 문제가 영속화된다.
주의 — 확정 못 한 것
같은 조사에서 providers 쪽이 하나 더 걸렸다.
SELECT is_active, deleted_at FROM providers WHERE id = ?;
is_active 1
deleted_at NULL
퇴점한 업체인데 상위 표에는 활성으로 남아 있었다.
다른 방식으로 관리되는 것일 수도 있고 누락일 수도 있어 확정하지 못했다. 기록에는 반영이 안 됐거나 다른 방식으로 관리되는 것으로 보인다고 미확정으로 적었다.
providers 한 건으로는 결함인지 설계인지 안 갈린다. 확인하지 않은 것을 확인한 것처럼 적으면 다음 사람이 그것을 근거로 판단한다.
정리
- 작업 실패 위에 소프트 삭제가 얹히면 목록에서 완전히 사라진다
- 실패를 찾는 조회에서도 함께 빠진다
- 삭제가 실패를 덮어 없어진 것처럼 만든다
- 우리 쪽에서 안 보여도 밖에서는 계속 유효하다
- 사소한 실패가 안 보이는 곳으로 들어가면 사고가 된다
- 삭제 이전에 성공 여부를 확인한다
- 실패면 삭제하지 않는다
- 소프트 삭제는 정리가 아니라 감춤이다
- 확정 못 한 것은 미확정으로 적는다