У меня есть задача rake, которая отвечает за пакетную обработку на миллионах URL-адресов. Поскольку этот процесс занимает много времени, я иногда обнаруживаю, что URL-адреса, которые я пытаюсь обрабатывать, более недействительны - 404s, сайт вниз, что угодно.
Когда я изначально написал это, в основном был только один сайт, который постоянно обрабатывался во время обработки, поэтому мое решение заключалось в использовании open-uri
, спасении созданных исключений, немного подождать, а затем повторить попытку.
Это работало отлично, когда набор данных был меньше, но теперь так много времени, что я нахожу URL-адреса, больше не существует и создаю 404.
Используя случай 404, когда это произойдет, мой script просто сидит там и петли бесконечно - очевидно, плохо.
Как я должен обрабатывать случаи, когда страница не загружается успешно, и что еще более важно, как это вписывается в "стек", который я создал?
Я новичок в этом, и 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