Задача Rails Rake показала сообщение об истечении срока выполнения и программа остановлена - PullRequest
2 голосов
/ 10 июня 2011

У меня есть грабельное задание загрузить изображение машины с веб-сайтов с помощью скрепки. Изображение хранится в базе данных в виде удаленной ссылки.

Вот мой код, и я использую ruby ​​1.8.7, rails 2.3.8 и DB mysql.

namespace :db do

  task :load_photo  => :environment do
  require 'rubygems'
  require 'open-uri'
  require 'net/http'
  require 'paperclip'
  begin
  images =Website.find(:all,:conditions=>["image_url is not null"])
  images.each do |photo|
     url = URI.parse(photo.image_url)
     Net::HTTP.start(url.host, url.port) do |http|
         if http.head(url.request_uri).code == "200"
           Car.update_attribute(:photo,open(url))
         end
     end
  end
  rescue Exception => e
  end
 end 
 end 

Запустить над граблями задание по db: load_photo. В моей таблице (на сайте) есть 60000 строк. Задача Rake, выполняющая только до 10000 строк, и выполнение прекращается с сообщением об ошибке «выполнение истекло» .

Может ли кто-нибудь помочь мне понять это?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 10 июня 2011

Вы можете счесть его более производительным для запуска в пакетном режиме, активная запись имеет метод find_in_batches, который прекращает загрузку всех записей в память одновременно.

http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find

Вы можете изменить свой код так:

namespace :db do
  task :load_photo  => :environment do
    require 'rubygems'
    require 'open-uri'
    require 'net/http'
    require 'paperclip'
    Website.find_in_batches(:conditions=>["image_url is not null"]) do |websites|
      websites.each do |website|
        begin
          url = URI.parse(website.image_url)
          Net::HTTP.start(url.host, url.port) do |http|
            if http.head(url.request_uri).code == "200"
              Car.update_attribute(:photo,open(url))
            end
          end
        rescue Exception => e
        end
      end
    end
  end 
end
1 голос
/ 10 июня 2011

Я могу только догадываться, но похоже, что вы делаете небольшую DoS-атаку на сервер, с которого вы извлекаете изображения.

Вы можете попробовать играть с небольшой задержкой между последовательными запросами (например,"sleep 1").

Кроме того, если ваше "выполнение истекло", это исключение Timeout :: Error, то вы не можете перехватить его с помощью

rescue Exception => e

, поскольку Timeout :: Errorне является подклассом StandardError, это подкласс класса Interrupt.Вы должны это уловить явно, вот так:

rescue Timeout::Error => e
...