在Ruby的核心库中修补类

时间:2011-08-30 00:10:07

标签: ruby

我正在尝试将后续http调用的超时设置为非常不可靠的API。我尝试过多次尝试使用Ruby的内置Timeout.timeout()方法,但是没有这么好的运气让它扩展到子调用。例如,Timeout.timeout(300)会将第一个超时设置为300,但子调用将返回60.我添加了一个seconds_delay的打印,这是我所看到的:

[16:55:16 miker@laughwhat-lm ~/optisol/src/rails/tools_app/trunk/adhoc/ticket] $ bundle exec ruby buck.rb 
300
nil
warning: peer certificate won't be verified in this SSL session
60
60
nil
warning: peer certificate won't be verified in this SSL session
60

这是我通过完整堆栈跟踪收到的错误:

[16:49:50 miker@laughwhat-lm ~/optisol/src/rails/tools_app/trunk/adhoc/ticket] $ bundle exec ruby buck.rb 
warning: peer certificate won't be verified in this SSL session
warning: peer certificate won't be verified in this SSL session
warning: peer certificate won't be verified in this SSL session
warning: peer certificate won't be verified in this SSL session
warning: peer certificate won't be verified in this SSL session
warning: peer certificate won't be verified in this SSL session
warning: peer certificate won't be verified in this SSL session
/Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/timeout.rb:64:in `rbuf_fill': execution expired (Timeout::Error)
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/protocol.rb:134:in `rbuf_fill'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/protocol.rb:116:in `readuntil'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/protocol.rb:126:in `readline'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/http.rb:2028:in `read_status_line'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/http.rb:2017:in `read_new'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/http.rb:1051:in `request_without_fakeweb'
    from /Users/miker/.rvm/gems/ree-1.8.7-2011.03/gems/fakeweb-1.3.0/lib/fake_web/ext/net_http.rb:50:in `request'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/http.rb:845:in `post'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/netHttpClient.rb:93:in `post'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/netHttpClient.rb:116:in `start'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/net/http.rb:543:in `start'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/netHttpClient.rb:115:in `start'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/netHttpClient.rb:92:in `post'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/streamHandler.rb:170:in `send_post'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/streamHandler.rb:109:in `send'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/rpc/proxy.rb:170:in `route'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/rpc/proxy.rb:141:in `call'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/rpc/driver.rb:178:in `call'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/soap/rpc/driver.rb:232:in `getByBuyer'
    from buck.rb:9
    from /Users/miker/.rvm/gems/ree-1.8.7-2011.03/gems/yieldmanager-0.8.2/lib/yieldmanager/client.rb:131:in `session'
    from buck.rb:8
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/timeout.rb:67:in `timeout'
    from /Users/miker/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/timeout.rb:101:in `timeout'
    from buck.rb:6

所以我想我的问题是如何修补protocol.rb BufferedIO的方法看起来像这样:

class BufferedIO
  private
  def rbuf_fill
    puts "working"
    timeout(300) { # forced 300 second timeout
      @rbuf << @io.sysread(BUFSIZE)
    }
  end
end

在我执行我的requires / includes之前或之后将它添加到我的ruby文件中没有影响(即没有打印出“工作”)。希望有人有解决方案。谢谢!

1 个答案:

答案 0 :(得分:0)

在所有各种Ruby库中,在我看来,最笨拙的工作和ugliest必须是net :: http。你有没有考虑过这样的事情:

https://github.com/dbalatero/typhoeus

typhoeus中的请求是通过lib-curl发生的,所以当嵌套或线程超时方法不受Ruby的不可靠约束时。

就rbuf_fill问题而言,我不确定是否会让你到那里。如果我没记错的话,当超时异常触发时,它总是显示代码当前位于堆栈中的位置。那个位置只是偶然的。以下面的例子我刚刚跑进了irb。注意它是如何告诉你“睡眠”中发生的超时?报告超时的时间恰好是当时正在执行的操作,而不是必须实现超时代码的地方,如果有多个超时代码,也不知道跳闸的超时。我不得不追逐rbuf_fill为你确认这一点,我现在必须跑...

IRB&GT;超时(2){sleep 5}

超时::错误:执行已过期     from(irb):3:in sleep' from (irb):3:in block in irb_binding'     来自(irb):3     来自/ home / ebelan