Sidekiq 재시도: 백오프, 재시도 횟수, 유료 API 호출
Sidekiq은 기본적으로 실패한 작업을 약 20일간 25번 재시도합니다. 횟수를 제한하고, sidekiq_retry_in으로 retry-after만큼 기다리고, 같은 Idempotency-Key를 재사용하세요.

Sidekiq은 기본적으로 실패한 작업을 지수 백오프로 25번 재시도합니다. 매번 (retry_count ** 4) + 15초에 무작위 시간을 더한 만큼 기다리며 약 20일에 걸쳐 재시도하고, 그 뒤에는 작업을 Dead set으로 옮깁니다. API로 비용이 드는 일을 시작하는 작업이라면 sidekiq_options retry: 5로 횟수에 상한을 두고, sidekiq_retry_in으로 API의 retry-after만큼 기다리거나 재시도로 해결되지 않는 오류는 kill하고, Idempotency-Key를 작업 인수로 만드세요. 그래야 재시도가 두 번째 실행을 결제하는 대신 원래 실행을 재전송합니다.
Sidekiq 관련 내용은 Sidekiq 위키의 오류 처리, 모범 사례, 기본 개념 페이지와 Ruby의 Net::HTTP 문서에서, Sume 관련 내용은 Format 호출하기 (영문), 오류와 비용 (영문), 실행과 결과 (영문)에서 가져왔습니다. 모두 2026-09-28에 확인했습니다. Sume에는 Sidekiq용 gem이 없으며, 작업이 일반 HTTPS 호출을 한 번 보냅니다. 같은 패턴을 Python으로 구현한 글은 Celery 태스크 재시도: 유료 API 호출용 백오프와 지터입니다.
Sidekiq은 얼마나 오래 재시도하나요?
전체 공식은 (retry_count ** 4) + 15 + (rand(10) * (retry_count + 1))초이므로, 초반 재시도는 금방 이어지고 후반 재시도는 며칠 간격으로 벌어집니다. 마지막 재시도가 끝나면 작업은 Dead set으로 가며, Dead set은 작업을 최대 10,000개 또는 6개월까지 보관합니다. 거기서부터는 Web UI에서 직접 재시도하며, Web UI의 Retries 탭과 Dead 탭에 실패한 작업이 나열됩니다.
| 재시도 | 직전 대기 시간 | 누적 대기 시간 |
|---|---|---|
| 1 | 20초 | 20초 |
| 5 | 4분 56초 | 8분 24초 |
| 10 | 1시간 50분 26초 | 4시간 22분 38초 |
| 15 | 10시간 41분 46초 | 1일 11시간 41분 52초 |
| 20 | 1일 12시간 13분 56초 | 6일 12시간 40분 16초 |
| 25 | 3일 20시간 11분 56초 | 20일 10시간 17분 0초 |
재시도 횟수는 어떻게 바꾸나요?
작업 클래스마다 sidekiq_options로 바꿉니다.
retry: 5: 다섯 번 재시도한 뒤 Dead set으로 보냅니다.retry: 0: 재시도하지 않습니다. 실패한 작업은 곧바로 Dead set으로 갑니다.retry: false: 작업이 실패하면 버려집니다.retry_for: 48.hours(Sidekiq 7.1.3 이상): 횟수 대신 일정 기간 동안 재시도합니다.sidekiq.yml의:max_retries는 전역 최대값을 정합니다.sidekiq_retries_exhausted는 작업이 Dead set으로 옮겨지기 직전에 실행됩니다. 누군가에게 알림을 보내기 좋은 곳입니다.
유료 API 호출은 어떻게 안전하게 재시도하나요?
실행할 때마다 같은 키와 본문을 보내세요. Sidekiq 모범 사례는 Sidekiq이 작업을 정확히 한 번이 아니라 최소 한 번 실행하며, 완료된 작업도 다시 실행될 수 있다고 말합니다. 인수는 작업의 JSON 해시 안에 담겨 전달되므로 인수로 만든 키는 매번 같고, Sume는 반복 요청에 두 번째 청구 대신 원래 영수증과 idempotency_hit: true를 담은 200으로 응답합니다. Sume 문서의 표현대로라면 시도마다 무작위 키를 쓸 경우 헤더는 장식에 불과해집니다. 나머지 재전송 사례는 AI 영상 API 멱등성 키에서 다룹니다.
sidekiq_retry_in은 재시도 횟수와 예외를 받습니다. 기다릴 초를 반환하거나, 작업을 Dead set으로 보내려면 :kill(Sidekiq 6.5.2 이상)을, 기본 지연을 쓰려면 nil을 반환하세요. 어느 경우인지는 Sume의 오류 봉투가 알려 줍니다. retryable은 다시 보내 성공할 수 있는지 알려 주고, 429에는 초 단위의 retry-after가 담겨 있으며, 문서는 503은 나중에 같은 키로 재시도하라고 말합니다. retryable로 표시되지 않은 그 밖의 4xx는 호출 자체를 고쳐야 한다는 뜻입니다. 아무것도 실행되지 않았고 아무것도 청구되지 않았으므로, Fatal은 다섯 번의 재시도를 거치지 않고 곧바로 Dead set으로 갑니다. Ruby의 Net::HTTP에서 res.code는 "429" 같은 문자열이고, res["retry-after"]로 헤더를 읽습니다.
require "net/http"
class StartVideoJob
include Sidekiq::Job
sidekiq_options retry: 5
RateLimited = Class.new(StandardError)
Fatal = Class.new(StandardError)
sidekiq_retry_in do |count, exception|
case exception
when RateLimited then exception.message.to_i # the API's retry-after
when Fatal then :kill # to the Dead set, no more retries
end # nil: Sidekiq's default backoff
end
def perform(order_id, version = 1)
res = Net::HTTP.post(URI("https://api.sume.com/v1/formats/acme/product-promo/runs"),
{ input: { order_id: order_id },
communication: { webhook_url: "https://example.com/hooks/sume" } }.to_json,
{ "Authorization" => "Bearer #{ENV.fetch("SUME_API_KEY")}", "Content-Type" => "application/json",
"Idempotency-Key" => "order-#{order_id}-promo-v#{version}" }) # same on every retry
body = JSON.parse(res.body)
return body["data"]["id"] if res.is_a?(Net::HTTPSuccess) # 202 new, 200 replay: store it
raise RateLimited, res["retry-after"] if res.code == "429"
raise body["error"]["code"] if body["error"]["retryable"] || res.code == "503"
raise Fatal, "#{res.code} #{body["error"]["code"]}"
end
end작업이 끝난 뒤 영상 실행이 실패하면 어떻게 하나요?
Sidekiq 재시도로는 해결할 수 없습니다. 이전 키는 실패한 영수증에 묶여 있으므로, 그 키를 다시 쓰면 실패를 재전송할 뿐입니다. 다음 버전으로 새 작업을 큐에 넣으세요. StartVideoJob.perform_async(1042, 2)의 키는 -v2로 끝납니다. Sidekiq 스레드를 영상을 기다리는 데 붙잡아 두지도 마세요. 롱폼 영상은 만드는 데 15분에서 30분이 걸리며, 작업이 기다리기를 멈춰도 실행과 그 지출은 멈추지 않습니다. 실행이 완료되거나 실패하면 Sume가 서명된 format.run.terminal 영수증 하나를 communication.webhook_url로 POST합니다. 받는 방법은 Rails 웹훅: 컨트롤러에서 HMAC 서명 검증하기에서 다룹니다.
출처
관련 글
연동 카테고리의 다른 글
- Slack API 파일 업로드: files.upload 대신 세 번 호출
files.upload 지원 중단 뒤에는 files.getUploadURLExternal, upload_url에 바이트 POST, channel_id와 files.completeUploadExternal 순입니다.
- Strands Agents MCP: 에이전트를 Sume MCP 서버에 연결
MCPClient로 Strands 에이전트를 원격 MCP 서버에 연결하세요. Sume 호스팅 MCP URL과 API 키 헤더를 넣고, tool_filters로 유료 도구를 뺍니다.
- Teams Incoming Webhook 종료: Workflows로 전환
Microsoft는 Teams의 Office 365 커넥터를 May 18~22, 2026에 비활성화하기로 했습니다. 대신 Workflows 웹훅 URL을 만들고 Adaptive Card를 POST하세요.
- ChatGPT에 MCP 서버를 추가하는 방법: 개발자 모드
ChatGPT 개발자 모드를 켜고, 서버 URL로 앱을 만들고, OAuth로 로그인하세요. Sume 호스팅 MCP 서버를 예로 들어 단계를 설명합니다.
작성자 Sume