У меня есть задача rake, которая отвечает за пакетную обработку миллионов URL-адресов. Поскольку этот процесс занимает так много времени, я иногда обнаруживаю, что URL-адреса, которые я пытаюсь обработать, больше недействительны --404, сайт не работает и так далее.
Когда я изначально писал это, в основном был только один сайт, который постоянно отключался во время обработки, поэтому я решил использовать open-uri
, спасать все созданные исключения, немного подождать, а затем повторить попытку.
Это работало нормально, когда набор данных был меньше, но теперь проходит так много времени, что я обнаруживаю, что URL-адресов больше нет, и выдает ошибку 404.
Используя случай 404, когда это происходит, мой сценарий просто сидит и бесконечно зацикливается --, очевидно, плохо.
Как мне обрабатывать случаи, когда страница не загружается успешно, и, что более важно, как это вписывается в «стек», который я построил?
Я довольно новичок в этом и в Rails, поэтому приветствуются любые мнения о том, где я мог ошибиться в этом дизайне!
Вот какой-то анонимный код, который показывает, что у меня есть:
Задача rake, которая вызывает MyHelperModule:
# 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