我有一个 rake 任务,负责对数百万个 URL 进行批处理。因为这个过程需要很长时间,我有时会发现我尝试处理的 URL 不再有效—— 404、站点关闭等等。
当我最初写这篇文章时,基本上只有一个站点在处理过程中会不断关闭,所以我的解决方案是使用open-uri
,拯救任何产生的异常,稍等片刻,然后重试。
当数据集较小时,这工作得很好,但现在时间过去了,我发现 URL 不再存在并产生 404。
使用 404 的情况,当发生这种情况时,我的脚本只是坐在那里并无限循环——显然很糟糕。
我应该如何处理页面未成功加载的情况,更重要的是这如何适合我构建的“堆栈”?
我对这个和 Rails 很陌生,所以欢迎任何关于我在这个设计中可能出错的地方的意见!
这是一些显示我所拥有的匿名代码:
调用 MyHelperModule 的 rake 任务:
# lib/tasks/my_app_tasks.rake
namespace :my_app do
desc "Batch processes some stuff @ a later time."
task :process_the_batch => :environment do
# The dataset being processed
# is millions of rows so this is a big job
# and should be done in batches!
MyModel.where(some_thing: nil).find_in_batches do |my_models|
MyHelperModule.do_the_process my_models: my_models
end
end
end
end
MyHelperModule 接受my_models
ActiveRecord 并做进一步的事情。它调用SomeClass
:
# lib/my_helper_module.rb
module MyHelperModule
def self.do_the_process(args = {})
my_models = args[:my_models]
# Parallel.each(my_models, :in_processes => 5) do |my_model|
my_models.each do |my_model|
# Reconnect to prevent errors with Postgres
ActiveRecord::Base.connection.reconnect!
# Do some active record stuff
some_var = SomeClass.new(my_model.id)
# Do something super interesting,
# fun,
# AND sexy with my_model
end
end
end
SomeClass
将通过以下方式访问网络WebpageHelper
并处理一个页面:
# lib/some_class.rb
require_relative 'webpage_helper'
class SomeClass
attr_accessor :some_data
def initialize(arg)
doc = WebpageHelper.get_doc("http://somesite.com/#{arg}")
# do more stuff
end
end
WebpageHelper
是捕获异常并在 404 的情况下启动无限循环的地方:
# lib/webpage_helper.rb
require 'nokogiri'
require 'open-uri'
class WebpageHelper
def self.get_doc(url)
begin
page_content = open(url).read
# do more stuff
rescue Exception => ex
puts "Failed at #{Time.now}"
puts "Error: #{ex}"
puts "URL: " + url
puts "Retrying... Attempt #: #{attempts.to_s}"
attempts = attempts + 1
sleep(10)
retry
end
end
end