无法捕获红宝石异常

unable to catch ruby exception

具有以下长期运行的耙批:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class SyncStarredRepo
  include Mongoid::Document

  def self.update

    User.all.map do |user|

      if user.email !="[email protected]"
        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

我希望捕获moped::errors::cursorNotFound异常,但它不起作用。

在crontab日志中,我只收到以下消息:

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

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

更新

我正在尝试将可捕获的异常集"扩展"为StandardError,方法是:

1
2
3
4
      rescue
        p $!, *$@
        next
      end

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

更新

我刚刚更新了以前的简化代码,Rake使用了完整的SyncStarredrepo类,以防在循环逻辑、begin/rescue/end等中丢失某些内容…

更新

按照rake -t打印的stacktrace操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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/[email protected]/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `
block in execute'
/usr/local/rvm/gems/[email protected]/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/[email protected]/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/[email protected]/gems/rake-0.9.2.2/lib/rake/task.rb:144:in `
invoke'
/usr/local/rvm/gems/[email protected]/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/[email protected]/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `
each'
/usr/local/rvm/gems/[email protected]/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/[email protected]/gems/rake-0.9.2.2/lib/rake/application.rb:88:in `
top_level'
/usr/local/rvm/gems/[email protected]/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/[email protected]/gems/rake-0.9.2.2/lib/rake/application.rb:63:in `
run'
/usr/local/rvm/gems/[email protected]/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/[email protected]/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))。实际上,rescue中的retry只会导致beginrescue块中的代码再次运行。

正确的代码应该如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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