정책 값을 MySQL 에서 12건 UPDATE 하고 화면에서 승인을 눌렀는데 작업이 안 나갔다.
SELECT id, status, updated_at FROM distribution_jobs
WHERE account_id IN (...);
12건이 전부 pending 이었고 updated_at 도 안 바뀌어 있었다.
Table of contents
Open Table of contents
증상 — 정책 변경과 눌린 승인
승인을 누르면 job 이 만들어지고 그것이 순서대로 나가는 구조였다. job 이 없다는 것은 만들어지지 않았다는 뜻이었다.
성공 메시지가 나왔으므로 처리 자체는 오류 없이 끝난 것이었다. 오류도 없고 결과도 없는 상태였다.
비동기와 대기 상태
처음에는 실행이 비동기라 승인 직후에는 pending 으로 보일 수 있다고 의심했다. 그런데 승인 처리가 됐다면 최소한 updated_at 은 바뀌어야 하는데 그것이 안 바뀌었으니 아예 안 잡힌 것이었다.
비동기 실행에서 직후에 대기로 보이는 것은 정상이지만 한참 뒤에도 그대로면 아니다. 기다려 보는 것으로 그 갈래를 닫고 다음으로 갔다.
이미 완료라 걸러졌다
grep 으로 컨트롤러를 읽어 보니 앞쪽에 filter 가 있었다.
public function distributionAccountApprove($id)
{
$policies = $account->providerDeliveryPolicies
->filter(function ($p) {
return !($p->status === 'active'
&& $p->sync_status === 'complete');
});
status 가 active 이면서 sync_status 가 complete 인 것을 빼는 것인데 우리가 UPDATE 로 바꾼 12건이 정확히 그 조건이었다.
UPDATE 로 정책 값만 바꾸면서 sync_status 는 complete 인 채로 뒀던 것이다. 승인 입장에서는 이미 처리가 끝난 건이므로 건너뛰는 것이 설계대로였다.
되돌려야 할 두 자리
다시 처리시키려면 sync_status 를 처리 전 값으로 UPDATE 해 되돌려야 했다. 그것만 되돌리고 다시 눌러 보니 여전히 목록에 안 떴다.
상위 레코드에도 같은 성격의 상태가 하나 더 있어서 그것까지 함께 맞춰야 대상에 들어왔다. 화면 조작 하나가 실제로는 값 여러 개를 함께 바꾸고 있었던 것이다.
갱신 시각으로 하는 판정
이 건에서 남긴 것은 실패 여부를 상태값으로 가르지 않는다는 것이었다. 걸러진 건과 아직 안 나간 건이 같은 상태값으로 보이기 때문이다.
대신 updated_at 을 봤는데 우리가 승인을 누른 시각보다 앞이면 그 처리를 안 탄 것이다. 값 하나로 안 갈리는 것은 시각을 함께 보면 갈린다.
정리
- 승인 처리에 필터가 있어 이미 완료인 것은 건너뛴다
- 건너뛴 건은 오류가 아니라 성공 메시지가 나온다
- 비동기는 직후에 대기로 보이는 것이 정상이다
- 한참 뒤에도 그대로면 다른 원인이다
- 직접
UPDATE는 부수 컬럼을 안 건드린다 - 재처리하려면 동기화 상태를 되돌린다
- 상위 상태도 함께 맞춰야 대상에 들어온다
- 상태값으로 안 갈리면
updated_at을 본다