본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

자동 재시도 없음

~11 min · retry, billing-ambiguity, idempotency, intentional

Level 0Empty Shelf
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"'실패하면 재시도' 는 그 실패가 아무것도 안 했다고 조용히 가정해. 유료 호출엔, 그 가정이 도박이야."

가장 반사적인 좋은 관행이, 함정으로

네트워크 호출을 자동 재시도로 감싸는 건 워낙 표준 위생이라 HTTP client 대부분이 기본으로 해줘. 그리고 재시도가 원래 겨냥한 작업, 그러니까 idempotent 하고 부작용 없는 읽기에는 정확히 맞는 얘기야. 호출이 아무 효과도 못 냈거나 알 수 없었을 뿐이고, 어느 쪽이든 다시 돌려도 무해하니까. 유료 전사 호출은 그 둘 중 어느 쪽도 아냐. 돈을 움직이고, 한 번 제출되면 이미 돌았을 수도 있어. 그래서 Recall 은 얼핏 보면 틀려 보이는 걸 해. 유료 호출을 하는 client 에서 자동 재시도를 아예 없애버려.

이유는 분명해. 요청을 제출한 에 난 transport timeout 은 provider 가 job 을 돌렸는지에 대해 아무것도 안 알려줘. provider 가 전사하고 청구까지 했는데 응답만 오는 길에 잃어버린 걸 수도 있어. 그 순간의 자동 재시도는 눈 감고 하는 두 번째 구매야. 유료 경계를 넘어서까지 적용된 재시도 반사는 회복력으로 분장한 돈 누수고.

유료 경계가 선이야

답은 '절대 재시도하지 마' 가 아냐. '되돌릴 수 없는 행위가 정확히 어디 있는지 알고, 자동 재시도가 그 선을 절대 못 넘게 하라' 는 거지. Recall 은 유료 POST 에 단단한 선을 하나 그어.

  • 경계 전 — source hash, 오디오 proxy 빌드, ledger 예약. 여기까지는 돈을 한 푼도 안 썼어. 그래서 여기서 난 실패는 재시도해도 안전해. 첫 시도가 아무 비용도 안 들었다는 게 증명되니까. Recall 은 딱 이걸 작업으로 노출해. '유료 경계 전에 난 게 확실한 실패만 재시도' 하는 작업.
  • 경계에서, 또는 그 뒤 — POST 가 이미 나갔어. 여기서 난 실패는 무해하다는 걸 증명 못 하니까 절대 자동 재시도 안 해. 지난 레슨의 ambiguous 상태가 돼서 사람한테 넘어가.

그러니까 재시도가 금지된 게 아니라 선이 그어진 거야. 엔진은 값싸고 아무 효과도 없었다는 게 증명되는 쪽에서는 마음껏 재시도하고, 돈 경계에서 딱 멈춰. 기술은 그 경계가 정확히 어디 앉는지를 아는 거고. 자동 재시도는 첫 시도가 아무것도 안 했다는 증명만큼만 안전하거든.

회복력은 재시도랑 같은 게 아냐

이 반사가 워낙 깊으니까 분명히 짚고 갈게. 시스템은 자동 재시도를 거부하면서도 얼마든지 회복력이 강할 수 있어. Recall 은 크래시도, 연결 끊김도, provider timeout 도 버텨. 근데 유료 endpoint 를 눈 감고 다시 때려서가 아니라 durable 예약과 outbox 와 idempotent 수락으로 버티는 거야. 진짜 회복력은 모든 상태를 복구할 수 있게 만드는 거지, 같은 호출을 될 때까지 두들기는 게 아냐. 작업이 공짜고 idempotent 하면 마음껏 재시도해. 돈이 들거나 부작용이 없다는 걸 증명 못 하면, 회복력은 나중에 복구할 수 있을 만큼 기록해두고 진실을 확인할 수 있는 사람한테 불확실성을 넘기는 거고.

Code

경계 전엔 마음껏 재시도, 경계는 절대 안 넘음·python
# 유료 client 는 재시도가 일부러 DISABLED.
scribe = HttpClient(retries=0)   # 여기 timeout 은 재시도 아니라 모호함

# 실패는 돈 경계의 어느 쪽에 떨어졌는지로 분류된다:
#
#   유료 경계 전  (hash, proxy 빌드, 예약)     -> 재시도 안전
#   유료 POST 에서/후 (제출됨, 응답 없음)        -> AMBIGUOUS, 사람만
#
# operator 는 증명 가능하게 싼 실패만 재시도할 수 있다:
#   recall-archive retry-failed <batch> --safe-only
#     ^ 유료 POST 전으로 알려진 실패만 재실행한다.
#       이미 청구됐을지 모르는 건 절대 안 건드린다.

External links

Exercise

네 프로젝트의 HTTP client 나 API client 를 봐. 하나하나 물어봐. 자동 재시도를 해? 그리고 그게 부르는 endpoint 에 부작용(결제, 전송, 외부 상태 변경)이 있어? 부작용 경계를 넘어서 재시도하는 걸 하나 찾아봐. 그다음 경계를 명시적으로 그어. 어떤 단계가 아무 효과도 없다는 게 증명되고(재시도 안전), 되돌릴 수 없는 행위는 어디서 일어나(자동 재시도 금지)? 그 선에서 멈추도록 재시도 정책을 다시 설계해.
Hint
질문 두 개면 위험이 드러나. 하나, 내 client 의 기본 재시도 동작이 뭐지? 상당수가 idempotent 메서드를 조용히 재시도해. 둘, timeout 이 났을 때 그 호출이 아무 효과도 없었다는 걸 증명할 수 있어? 두 번째 답이 '아니오' 면 그 호출은 자동 재시도되면 안 돼. 값싼 준비 단계에는 재시도를 남겨두고, 제출한 뒤에 난 실패는 사람이 명시적으로 해결하는 상태로 바꿔.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.