2011-06-10 51 views
2

我有一个rake任务,使用回形针从表网站加载汽车的图像。图像作为远程链接存储在数据库中。Rails Rake任务显示执行过期消息和程序停止

这里是我的代码,我使用红宝石1.8.7,导轨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运行在rake任务之上。在我的表(网站)有60,000行。 Rake任务最多只能运行10000行,并且执行以错误消息“execution expired”终止。

任何人都可以帮我解决这个问题吗?

在此先感谢。

+0

尝试用'read_timeout' http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html玩#M001372 – 2011-06-10 10:33:34

+0

你可以显示rake db的输出:load_photo --trace – 2011-06-10 12:14:54

回答

2

您可能会发现批处理运行它的更高性能,活动记录有一个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 
+0

嗨安德鲁,你能帮我修理耙子中止!, 未定义的方法'哪里#for#谢谢! – prabu 2011-06-13 10:42:55

+0

我已经修复了rake任务,现在在rails 2.3.x中工作,那里方法是rails 3的一部分,它现在应该可以工作 – 2011-06-13 11:00:29

+0

嗨Andrew,似乎上面的代码对所有记录都执行了。但在日志显示“错误=太多链接 -/var/www/rails/public/images/photos/32123”。任何想法? – prabu 2011-06-13 15:58:03

1

我只能猜测,但它看起来像你正在做一个小的DoS攻击你拉的图像服务器从。

您可以尝试在顺序请求(如“睡眠1”)之间稍稍延迟播放。

此外,如果你的“执行过期”是一个超时::错误例外,那么你就不能

rescue Exception => e 

抓住它,因为超时::错误不是StandardError的子类,它是一个Interrupt类的子类。你必须明确地抓住它,就像这样:

rescue Timeout::Error => e 
+0

嗨亚历克西斯,我也尝试过超时::错误异常处理,但仍然耙任务获取过期或SIGNUP消息显示。帮助我谢谢! – prabu 2011-06-13 10:49:45

+0

你也可以尝试没有参数的“救援” - 可以捕捉任何类型的异常。另外,终止前它总是* 10000行吗? – Alexis 2011-06-13 11:57:04

+0

您是否在每次请求后尝试添加延迟?我仍然认为问题在于服务器超负荷请求。如果每次请求后的“睡眠1”太慢,可以将它与Andrew Nesbitt的“find_in_batches”建议结合使用。 – Alexis 2011-06-13 12:06:51