如何让 Sidekiq 尊重 Retry-After 响应 header?
How can I make Sidekiq respect a Retry-After response header?
我正在使用 Sidekiq 尝试通过 Firebase 云消息传递 (FCM) 发送推送通知。 FCM 要求使用它的服务器提供 2 个东西:
- 指数退避
- 在 500 条回复中表彰 Retry-After header
https://firebase.google.com/docs/cloud-messaging/http-server-ref#table4
我们使用 Sidekiq 免费获得指数退避,但我不确定如何告诉它至少延迟到 header 中指定的时间重试。
我在下面有一个 hacky 解决方案,我在 raise
之前让工作人员 sleep
但似乎重试逻辑应该存在于 Sidekiq 中。无论如何,我是否可以告诉 Sidekiq 关于 Retry-After
header 值,以便它可以做正确的事情?
class SendPushNotification
include Sidekiq::Worker
sidekiq_options queue: :low
def perform(user_id)
notification = { body: 'hello world' }
user = User.find(user_id)
fcm_token = user.try(:fcm_token) || ENV['FCM_TOKEN']
uri = URI('https://fcm.googleapis.com/fcm/send')
http = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true)
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json',
'Authorization' => "key=#{ENV['FCM_API_KEY']}")
req.body = {
badge: 0, # badge is removed when set to zero
click_action: 'click', # string
collapse_key: 'Handshake', # collapse multiple messages under this header
content_available: true, # wake inactive app
data: nil,
registration_ids: [fcm_token], # fcm device tokens
notification: notification,
mutable_content: true, # iOS 10 feature
priority: 'high', # high or low (corresponds to 5 and 10 in apns)
subtitle: nil,
time_to_live: 2419200, # max and default for FCM
dry_run: false # message is not sent when set to true
}.to_json
res = http.request(req)
case res
when Net::HTTPOK
true
when Net::HTTPUnauthorized
raise 'Unauthorized'
when Net::HTTPBadRequest
raise "BadRequest: #{res.body}"
else
if res.header['Retry-After']
# this seems like a hacky solution
sleep res.header['Retry-After']
end
raise 'Remote Server Error'
end
end
end
不要使用 Sidekiq 的内置重试。安排与当前作业相同的新作业到 运行 秒数。
self.class.perform_in(res.header['Retry-After'].to_i, user_id)
我正在使用 Sidekiq 尝试通过 Firebase 云消息传递 (FCM) 发送推送通知。 FCM 要求使用它的服务器提供 2 个东西:
- 指数退避
- 在 500 条回复中表彰 Retry-After header
https://firebase.google.com/docs/cloud-messaging/http-server-ref#table4
我们使用 Sidekiq 免费获得指数退避,但我不确定如何告诉它至少延迟到 header 中指定的时间重试。
我在下面有一个 hacky 解决方案,我在 raise
之前让工作人员 sleep
但似乎重试逻辑应该存在于 Sidekiq 中。无论如何,我是否可以告诉 Sidekiq 关于 Retry-After
header 值,以便它可以做正确的事情?
class SendPushNotification
include Sidekiq::Worker
sidekiq_options queue: :low
def perform(user_id)
notification = { body: 'hello world' }
user = User.find(user_id)
fcm_token = user.try(:fcm_token) || ENV['FCM_TOKEN']
uri = URI('https://fcm.googleapis.com/fcm/send')
http = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true)
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json',
'Authorization' => "key=#{ENV['FCM_API_KEY']}")
req.body = {
badge: 0, # badge is removed when set to zero
click_action: 'click', # string
collapse_key: 'Handshake', # collapse multiple messages under this header
content_available: true, # wake inactive app
data: nil,
registration_ids: [fcm_token], # fcm device tokens
notification: notification,
mutable_content: true, # iOS 10 feature
priority: 'high', # high or low (corresponds to 5 and 10 in apns)
subtitle: nil,
time_to_live: 2419200, # max and default for FCM
dry_run: false # message is not sent when set to true
}.to_json
res = http.request(req)
case res
when Net::HTTPOK
true
when Net::HTTPUnauthorized
raise 'Unauthorized'
when Net::HTTPBadRequest
raise "BadRequest: #{res.body}"
else
if res.header['Retry-After']
# this seems like a hacky solution
sleep res.header['Retry-After']
end
raise 'Remote Server Error'
end
end
end
不要使用 Sidekiq 的内置重试。安排与当前作业相同的新作业到 运行 秒数。
self.class.perform_in(res.header['Retry-After'].to_i, user_id)