Обработка ошибки тайм-аута

#ruby-on-rails #ruby

#ruby-on-rails #ruby

Вопрос:

После использования тайм-аута:

  status = Timeout::timeout(5) {
  # Something that should be interrupted if it takes too much time...
}
  

Я получил эту ошибку тайм-аута:

 /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/net/http.rb:644:in `initialize': execution expired (Timeout::Error)
    from /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/net/http.rb:644:in `open'
    from /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/net/http.rb:644:in `block in connect'
    from /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/timeout.rb:44:in `timeout'
    from /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/timeout.rb:87:in `timeout'
    from /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/net/http.rb:644:in `connect'
    from /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/net/http.rb:637:in `do_start'
    from /Users/galharth/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/1.9.1/net/http.rb:632:in `start'
    from /Users/galharth/.rvm/gems/ruby-1.9.2-p136/gems/mechanize-1.0.0/lib/mechanize.rb:527:in `fetch_page'
    from /Users/galharth/.rvm/gems/ruby-1.9.2-p136/gems/mechanize-1.0.0/lib/mechanize.rb:259:in `get'
  

Что мне делать?

Комментарии:

1. status = Timeout::timeout(5) { puts "ok" } Сбой?

2. Я только что протестировал на ruby1-9-2- p180 — проблемы нет

3. Моя интуиция подсказывает мне, что вы должны приложить усилия, чтобы предотвратить возникновение тайм-аута, если это возможно. Можете ли вы разделить этот единственный запрос на несколько меньших запросов?

4. @yock, вы не можете контролировать поведение Интернета. Один запрос для небольшой страницы может занимать минуты. Это не имеет ничего общего с количеством запросов, это скорость реагирования хоста, возвращающего запрос.

5. Все зависит от причины длительного времени отклика. Если вызов API выполняется медленно из-за того, что он возвращает много данных, вы, вероятно, могли бы разбить этот вызов на множество меньших вызовов. Итак, нет, вы не всегда действуете по указке Интернета.

Ответ №1:

Что ж, это ожидаемое поведение Timeout . Если блок занимает слишком много времени, его выполнение завершается и генерируется исключение.

Вероятно, вы хотели бы перехватить исключение и обработать его соответствующим образом:

 require 'timeout'
begin
  status = Timeout::timeout(5) {
    # Something that should be interrupted if it takes too much time...
  }
rescue Timeout::Error
  puts 'That took too long, exiting...'
end
  

Комментарии:

1. Timeout распространенным исключением является Timeout::Error . Вот еще одна проблема

2. Будет ли блок восстановления обрабатывать Timeout::Error?

3. @yock «Будет ли блок восстановления обрабатывать Timeout::Error?» Из документации по тайм-ауту : If the block execution terminates before sec seconds has passed, it returns the result value of the block. If not, it terminates the execution and raises exception (which defaults to Timeout::Error).

4. Я понимаю, что он выдает «исключение», но его тип — «Прерывание», не так ли? AFAIK, блок восстановления улавливает только StandardError и его подтипы.

5.Вы действительно можете rescue это. Timeout::Error.ancestors выдает Timeout::Error RuntimeError StandardError Exception Object Kernel BasicObject

Ответ №2:

 uri = URI.parse("https://example.com")
        # Full control
        http = Net::HTTP.new(uri.host, uri.port)
        http.use_ssl = true
        #http.read_timeout = 500
        request = Net::HTTP::Post.new(uri.request_uri)
        request.set_form_data({"locationcode" => "999", "sublocationcode" => "1"})
        response = http.request(request)
        render :json => response.body