无法捕获 Ruby 异常



具有以下长时间运行的耙子批处理:

class SyncStarredRepo
include Mongoid::Document
def self.update
User.all.map do |user| 
if user.email != "admin@gitwatcher.com"
begin 
conn = Faraday.new "https://api.github.com" 
i = 1  
begin   
resp = conn.get "/users/#{user.nickname}/starred?page=#{i}"
resp.body.each do |repo|
attempts = 0
begin 
existing_repo = user.watchlists.where( html_url: "#{repo['html_url']}" ).batch_size(30)
if existing_repo.exists?  
existing_repo.first.update_attributes!(
html_url: "#{repo['html_url']}",
description: "#{repo['description']}"
)
else   
user.watchlists.create!(
html_url: "#{repo['html_url']}",
description: "#{repo['description']}"
)
end
rescue Moped::Errors::CursorNotFound => c
attempts += 1
puts "error message: #{c.message}"
if attempts < 3
puts "Retrying... Attempt #: #{attempts.to_s}"
sleep(3)
retry 
else 
puts "already retried 3 times, go to the next"
next
end
end
end  
i += 1 
end until resp.body.empty? 
rescue TypeError => e
puts "message error (e.inspect): #{e.inspect}"
puts "go to the next user"
next    
rescue  
p $!, *$@
next    
end  
end  
end 
end
end

我想要抓住轻便摩托车::错误::光标未找到异常,但它不起作用。

在 crontab 日志中,我刚刚收到这条消息:

rake aborted!
The operation: "GET MORE"
failed with error "cursor 2509315744412059250 not found"

然后批处理停止并退出,而我正在查看救援消息和下一个循环操作。

更新

我正在尝试通过这样做来"扩展"设置为标准错误的可捕获异常:

rescue
p $!, *$@
next
end

。以防万一,即使CursorNotFound继承自MongoError,它继承自StandardError,如你在这里看到的。

更新

我刚刚更新了以前的简化代码,使用了 rake 使用的完整SyncStarredRepo类,以防万一我在循环逻辑、开始/救援/结束等中缺少一些东西......

更新

按照rake -t打印的堆栈跟踪:

rake aborted!
The operation: "GET MORE"
failed with error "cursor 5781947091640256877 not found"
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/gems/moped-1.3.2/lib/moped/node.rb:210:in `get_more'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/gems/moped-1.3.2/lib/moped/cursor.rb:44:in `get_more'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/gems/moped-1.3.2/lib/moped/cursor.rb:29:in `each'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/gems/moped-1.3.2/lib/moped/query.rb:77:in `each'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/gems/moped-1.3.2/lib/moped/query.rb:77:in `each'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/bundler/gems/mongoid-92cad16e9fbf/lib/mongoid/contextual/mongo.rb:133:in `block in each'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/bundler/gems/mongoid-92cad16e9fbf/lib/mongoid/contextual/mongo.rb:605:in `selecting'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/bundler/gems/mongoid-92cad16e9fbf/lib/mongoid/contextual/mongo.rb:132:in `each'
/var/www/gitwatcher/vendor/bundle/ruby/1.9.1/bundler/gems/mongoid-92cad16e9fbf/lib/mongoid/contextual.rb:18:in `each'
/var/www/gitwatcher/app/models/sync_starred_repo.rb:15:in `map'
/var/www/gitwatcher/app/models/sync_starred_repo.rb:15:in `update'
/var/www/gitwatcher/lib/tasks/scheduler.rake:9:in `block in <top (required)>'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `call'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `block in execute'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `each'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `execute'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/task.rb:158:in `block in invoke_with_call_chain'
/usr/local/rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/task.rb:151:in `invoke_with_call_chain'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/task.rb:144:in `invoke'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:116:in `invoke_task'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block (2 levels) in top_level'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `each'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block in top_level'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:88:in `top_level'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:66:in `block in run'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/lib/rake/application.rb:63:in `run'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/gems/rake-0.9.2.2/bin/rake:33:in `<top (required)>'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/bin/rake:23:in `load'
/usr/local/rvm/gems/ruby-1.9.3-p194@rails-3.2.8/bin/rake:23:in `<main>'
Tasks: TOP => update_starred_list_per_user

错误在User.all.map期间引发,因此您必须包装begin..rescue阻止整个语句。

基于初始信息的旧答案:

你在循环之外进行救援,所以retry并没有完全按照你的期望去做(另一方面next会提高SyntaxError(1.9)或LocalJumpError(1.8))。事实上,retryrescue只会导致begin内部的代码。rescue块再次运行。

正确的代码应如下所示:

attempts = 0
begin 
i = 1 
resp = conn.get "/users/#{user.nickname}/starred?page=#{i}"
resp.body.each do |repo|
begin
existing_repo = user.watchlists.where( html_url: "#{repo['html_url']}" )
if existing_repo.exists? 
existing_repo.first.update_attributes!(
html_url: "#{repo['html_url']}",
description: "#{repo['description']}"
)
else 
user.watchlists.create!(
html_url: "#{repo['html_url']}",
description: "#{repo['description']}"
)
end
rescue Moped::Errors::CursorNotFound => c
attempts += 1
puts "error message: #{c.message}"
if attempts < 3
puts "Retrying... Attempt #: #{attempts.to_s}"
sleep(3)
retry 
else 
puts "already retried 3 times, go to the next"
next
end
end
end 
i += 1
end until resp.body.empty?

虽然我没有仔细查看您的代码,但请注意,裸rescue并不能捕获所有异常。为此,您需要rescue Exception.

最新更新