"전달은 반복돼도 의도한 효과는 하나로 지켜."
의도한 효과 하나를 정해
네트워크는 자기를 반복해. 탭이 두 번 전달되고 timeout이 성공을 가리고, worker가 output을 쓴 뒤 acknowledge 전에 재시작할 수 있어. 재시도는 정상이고 중복 효과가 버그야.
같은 durable 행을 재시도해
현재 Inkwell은 실패한 durable job의 같은 행을 queued로 돌려 재시도해. guarded update는 queued, running, done이면 아무것도 바꾸지 않으니 retry 명령이 반복돼도 새 job을 만들지 않아.
재시도와 새 요청을 섞지 마
재시도를 전부 새 job으로 보면 경쟁하는 번역이 생겨. 음성은 on-demand라 durable job이 아니야. 원문이 바뀌면 pending review를 supersede하지 retry 명령 안에 두 번째 정체성을 숨기지 않아.
crash를 시간선에 넣어
이 설계는 평온한 demo가 아니라 아무 순간에 process가 사라지는 시간선에서 시험해야 해. 수락 전, commit 뒤, claim 뒤, 외부 호출 뒤, 결과 저장 뒤에 각각 crash를 놓고 database가 무엇을 말하는지 적어. 사용자가 같은 요청을 다시 보내도 돈과 문장이 두 번 생기지 않아야 해.
직접 설계해
failed job을 queued로 돌린 직후 client timeout이 난 경우의 반복 retry를 설계해. status와 timestamp, attempt 행을 같이 써. 복구 script가 추측으로 행을 덮지 않고 어떤 증거로 전환하는지 설명해.
관찰 가능성이 복구 가능성이야
운영자가 SQL 한 번으로 queued, running, failed, done을 구분하고 다음 안전 행동을 알 수 있어야 해. 알 수 없는 침묵을 queue라고 부르면 기다림은 이미 데이터를 잃은 거야.
운영 증거를 남겨
같은 failed job에 retry가 반복돼도 guarded update의 승자는 한 번뿐이야. 뒤 요청은 이미 queued인 같은 job id와 status를 읽어 돌려줘.
느린 외부 호출은 transaction 밖에 두고, claim과 완료만 짧고 atomic하게 만들어. 그래야 기다림이 database 전체를 잠그지 않아.