계약이 끝난 현장의 장비에서 콘텐츠가 계속 재생됐다는 제보를 받았다. 우리 중앙 시스템에서는 contents.status 가 STOPPED 로 되어 있어서 겉으로는 정상이었다.
Table of contents
Open Table of contents
배경 — 상태는 정상이고 작업은 실패였다
상태만 보지 말고 device_jobs 를 시간순으로 봤다. 등록 작업은 성공했고 그 뒤의 STOP 작업이 실패로 남아 있었으며 재시도도 알림도 없었다.
한 달 뒤에 deleted_at 이 찍힌 기록이 이어졌다. 우리 쪽 상태는 우리가 의도한 것이고 그것이 장비에 반영됐다는 근거는 작업 결과에만 있다.
원인 — 이름 길이가 막은 중지
실패 로그를 보니 장비 쪽에서 Data too long for column 'title' 로 거부한 것이었다. 중지도 UPDATE 요청으로 나가는데 그 요청에 콘텐츠 제목이 포함되고 등록 뒤에 길게 고친 제목이 장비 쪽 VARCHAR(50) 을 넘었다.
MySQL 5.7 매뉴얼은 strict 모드에서 ER_DATA_TOO_LONG 을 잘라 넣지 않고 오류로 낸다고 적는다. 장비 쪽 DB 는 strict 였고 중앙 쪽은 컬럼이 더 길어 아무 문제가 없었다. 중지하려는데 이름이 길어서 못 하는 상황이다. 관계없어 보이는 검증이 관계없어 보이는 동작을 막는 구조였다.
막힌 지점 — 삭제 표식이 가린 이력
현장이 정리되면서 deleted_at 이 찍히자 관리 목록에서 그 건이 사라졌다. 실패한 중지 작업이 있다는 사실을 볼 수 있는 화면이 없어진 것이다.
장비에서는 계속 재생 중인데 우리 화면에는 아무것도 안 보이는 상태가 됐다. 현장에서 사진을 찍어 보내서야 그 사실이 드러났다.
조치 — 상태가 아니라 작업으로 확인
그래서 중지가 실제로 반영됐는지는 상태 컬럼이 아니라 그 장비의 STOP 작업이 성공했는지로 확인하기로 했다. 정리 절차에도 중지 요청과 삭제 표식 사이에 성공 확인과 실패 건 별도 처리를 끼워 넣었다.
확인 없이 삭제 표식을 설정하면 실패가 그대로 은폐된다. 순서 하나를 바꾸는 것으로 은폐 경로가 닫혔다. 대신 현장 정리가 장비 응답을 기다리느라 하루 이틀 늦어지는 것을 감수했다.
주의 — 미검증 표기와 전수 점검
왜 그 실패가 실패로 인식되지 않았는지는 확인하지 못했다. device_jobs.result 가 NULL 이라 실패 목록 조회에 안 잡힌 것으로 보이지만 코드를 봐야 확정되므로 미검증 추정으로 적었다.
추정을 사실처럼 적으면 다음 사람이 그것을 근거로 다른 판단을 한다. 마지막으로 중지 실패 뒤에 삭제된 건이 얼마나 있는지를 세어 보니 여럿 나왔고 하나를 고치면서 같은 부류를 전수로 세는 것이 이런 조사의 실질이었다.
정리
- 우리 상태가 중지여도 장비에서는 재생 중일 수 있다
- 상태는 의도이고 작업 결과가 현실이다
- 반영 여부는 그 작업의 성공 여부로 확인한다
- 관계없어 보이는 검증이 관계없어 보이는 동작을 막는다
- 삭제 표식이 실패 이력을 목록에서 지운다
- 정리 절차에 성공 확인 단계를 넣는다
- 확실치 않은 것은 미검증 추정으로 적는다
- 하나를 고치면서 같은 부류를 전수로 센다