【问题标题】:Rescue Timeout::Error from Redis Gem (Ruby)Redis Gem (Ruby) 中的 Rescue Timeout::Error
【发布时间】:2011-10-25 11:46:23
【问题描述】:

我需要拯救从 Redis 库中提出的 Timeout::Error,但我遇到了问题,拯救该特定类似乎不起作用。

begin
  Redis.new( { :host => "127.0.0.X" } )
rescue Timeout::Error => ex
end

=> Timeout::Error: Timeout::Error from /Users/me/.rvm/gems/ree-1.8.7-2011.03@gowalla/gems/redis-2.2.0/lib/redis/connection/hiredis.rb:23:in `connect'

当我试图拯救 Exception 时它仍然不起作用

begin
  Redis.new( { :host => "127.0.0.X" } )
rescue Exception => ex
end

=> Timeout::Error: Timeout::Error from /Users/me/.rvm/gems/ree-1.8.7-2011.03@gowalla/gems/redis-2.2.0/lib/redis/connection/hiredis.rb:23:in `connect'

如果我尝试手动引发异常,我可以拯救它,但不知道为什么当它从 Redis Gem (2.2.0) 中调用时我无法拯救它。

begin
  raise Timeout::Error
rescue Timeout::Error => ex
  puts ex 
end

Timeout::Error
=> nil 

任何线索如何挽救这个异常?

【问题讨论】:

    标签: ruby exception exception-handling redis rescue


    【解决方案1】:

    你在 irb 中运行了这段代码,对吧?你得到的异常实际上并不是由Redis.new 提出的。它是由inspect 方法引发的,irb 调用该方法以显示您刚刚键入的表达式的值。

    只需查看堆栈跟踪(我缩短了路径以使其清晰可见):

    ruby-1.8.7-p330 :009 >   Redis.new(:host => "google.com")
    Timeout::Error: time's up!
        from /.../SystemTimer-1.2.3/lib/system_timer/concurrent_timer_pool.rb:63:in `trigger_next_expired_timer_at'
        from /.../SystemTimer-1.2.3/lib/system_timer/concurrent_timer_pool.rb:68:in `trigger_next_expired_timer'
        from /.../SystemTimer-1.2.3/lib/system_timer.rb:85:in `install_ruby_sigalrm_handler'
        from /..../lib/ruby/1.8/monitor.rb:242:in `synchronize'
        from /.../SystemTimer-1.2.3/lib/system_timer.rb:83:in `install_ruby_sigalrm_handler'
        from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `call'
        from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `initialize'
        from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `new'
        from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `connect'
        from /.../SystemTimer-1.2.3/lib/system_timer.rb:60:in `timeout_after'
        from /.../redis-2.2.2/lib/redis/connection/ruby.rb:115:in `with_timeout'
        from /.../redis-2.2.2/lib/redis/connection/ruby.rb:25:in `connect'
        from /.../redis-2.2.2/lib/redis/client.rb:227:in `establish_connection'
        from /.../redis-2.2.2/lib/redis/client.rb:23:in `connect'
        from /.../redis-2.2.2/lib/redis/client.rb:247:in `ensure_connected'
        from /.../redis-2.2.2/lib/redis/client.rb:137:in `process'
    ... 2 levels...
        from /.../redis-2.2.2/lib/redis/client.rb:46:in `call'
        from /.../redis-2.2.2/lib/redis.rb:90:in `info'
        from /..../lib/ruby/1.8/monitor.rb:242:in `synchronize'
        from /.../redis-2.2.2/lib/redis.rb:89:in `info'
        from /.../redis-2.2.2/lib/redis.rb:1075:in `inspect'
        from /..../lib/ruby/1.8/monitor.rb:242:in `synchronize'
        from /.../redis-2.2.2/lib/redis.rb:1074:in `inspect'
        from /..../lib/ruby/1.8/irb.rb:310:in `output_value'
        from /..../lib/ruby/1.8/irb.rb:159:in `eval_input'
        from /..../lib/ruby/1.8/irb.rb:271:in `signal_status'
        from /..../lib/ruby/1.8/irb.rb:155:in `eval_input'
        from /..../lib/ruby/1.8/irb.rb:154:in `eval_input'
        from /..../lib/ruby/1.8/irb.rb:71:in `start'
        from /..../lib/ruby/1.8/irb.rb:70:in `catch'
        from /..../lib/ruby/1.8/irb.rb:70:in `start'
        from /..../bin/irb:17
    

    正如您在上面看到的,异常发生在inspect 内部,而不是Redis.new。当您在 Redis 对象上调用 inspect 时,它实际上并不仅仅打印出它的状态,它实际上做了很多事情。在这种情况下,inspect 尝试连接到服务器并在超时时抛出异常。这对我来说似乎是一个非常糟糕的设计,也许我们应该向 Redis gem 的维护者提交错误报告。

    这导致了 IRB 中一些有趣的行为:

    • 键入 Redis.new(:host => "google.com") 会导致如上所示的异常
    • 键入 Redis.new(:host => "google.com"); 'hello' 会得到“=> "hello"

    如果您想捕获此异常,请尝试在 begin/rescue/end 块内调用 ensure_connected

    【讨论】:

    • 在我的情况下(请参阅上面的问题,如果我的编辑被批准),这个答案帮助我弄清楚 IRB 的 insect 是问题的根源。谢谢你,戴维!
    猜你喜欢
    • 1970-01-01
    • 2012-07-31
    • 2017-06-06
    • 1970-01-01
    • 2012-07-11
    • 2014-06-22
    • 2019-07-10
    • 1970-01-01
    • 2011-03-30
    相关资源
    最近更新 更多