如果您从 Web 源收到 Bad Gateway 错误响应,如何重试 rake 任务

How to retry a rake task if you get a Bad Gateway error response from a web source

我正在尝试 运行 抽取任务以从 Instagram 获取所有带有特定标签的数据,然后将一些数据输入我的服务器。

任务 运行 很好,只是有时我会收到错误响应。它有点随机,所以我认为它有时会发生,而且由于这是一个相当长的 运行ning 任务,它最终会发生。

这是我的控制台上的错误: Instagram::BadGateway: GET https://api.instagram.com/v1/tags/xxx/media/recent.json?access_token=xxxxx&max_id=996890856542960826: 502: 服务器返回无效或不完整的响应。

发生这种情况时,除了 运行 任务再次从 max_id 开始,我不知道还能做什么。但是,如果我能让整个事情自动化,并在收到错误时从那时起重试自己,那就太好了。

我的任务看起来像这样:

task :download => :environment do
  igs = Instagram.tag_recent_media("xxx")
  begin
    sleep 0.2
    igs.each do |ig|
      dl = Instadownload.new
      dl.instagram_url = ig.link
      dl.image_url = ig.images.standard_resolution.url
      dl.caption = ig.caption.text if ig.caption
      dl.taken_at = Time.at(ig.created_time.to_i)
      dl.save!
    end
    if igs.pagination.next_max_id?
      igs = Instagram.tag_recent_media("xxx", max_id: igs.pagination.next_max_id)
      moreigs = true
    else
      moreigs = false
    end
  end while moreigs
end

Chad Pytel 和 Tammer Saleh 在他们的 Rails Antipatterns 书中称此 "Fire and forget" 反模式:

Assuming that the request always succeeds or simply not caring if it fails may be valid in rare circumstances, but in most cases it's unsufficient. On the other hand, rescuing all the exceptions would be a bad practice aswell. The proper solution would be to understand the actual exceptions that will be raised by external service and rescue those only.

所以,您应该做的是将您的代码块包装到 begin/rescue 块中,并包含 Instagram 引发的适当错误集(这些错误的列表可以在 here 中找到).我不确定您的代码片段的哪一行以 502 代码结尾,所以只是为了让您了解它的外观:

begin
  dl = Instadownload.new
  dl.instagram_url = ig.link
  dl.image_url = ig.images.standard_resolution.url
  dl.caption = ig.caption.text if ig.caption
  dl.taken_at = Time.at(ig.created_time.to_i)
  dl.save!
rescue Instagram::BadGateway => e # list of acceptable errors can be expanded
  retry  # restart from beginning
end