Ruby 2.3 - 向 net:http 请求添加超时错误和通知
Ruby 2.3 - Adding Timeout error and notification to net:http request
我有一个可以产生错误并将其发送给 Active Admin 使用的工作系统。
例如,在 Active admin 中,对于我们 CMS 的特定页面,该页面可能会执行:
url_must_be_accessible("http://www.exmaple.com", field_url_partner, "URL for the partner")
这使用下面的代码向活动管理编辑器发送不同类型的错误通知:
module UrlHttpResponseHelper
def url_must_be_accessible(url, target_field, field_name)
if url
url_response_code = get_url_http_response(url).code.to_i
case url_response_code
when -1
# DNS issue; website does not exist;
errors.add(target_field,
"#{field_name}: DNS Problem -> #{url} website does not exist")
when 200
return
when 304
return
else
errors.add(target_field,
"#{field_name}: #{url} sends #{url_response_code} response code")
end
end
end
def get_url_http_response(url)
uri = URI.parse(URI.encode(url))
request = Net::HTTP.get_response(uri)
return request
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -1)
end
end
在本地模式下,效果很好!但在生产中,我们在 Heroku 上,当请求 pn Heroku 超过 30 秒时,就像你尝试这个 link "http://www.exmaple.com", the app crashes with a "H12 error".
我想在上面的代码中添加两件事
- 超时:我想我需要 read_timeout 和 open_timeout 并且 read_timeout + open_timeout 应该 < 到 30 秒,让我们采取一些安全措施,最好 < 25 秒
如果请求在 25 秒后仍然是 "going",则通过 给出 up/dropping 请求来避免达到 30 秒
并通过向用户发送通知来捕获此 "we dropped the request intentionnally because risk of timeout"。我想按照以下方式使用我当前的系统:
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -7) # = some random number
end
case url_response_code
when -7
errors.add(target_field,
"#{field_name}: We tried to reach #{url} but this takes too long and risks crashing the app. please check the url and try again.")
我怎样才能创建一个像 -1 这样的代码,但又要创建另一个代码来挽救我自己执行的 "timeout"/"drop the request attempt"。
尝试过,但没有任何效果。如果达到 25 秒,我无法创建捕获和丢弃此请求的代码...
这不是很漂亮的解决方案(请参阅:https://medium.com/@adamhooper/in-ruby-dont-use-timeout-77d9d4e5a001),但我相信您仍然可以在这里使用它,因为与 link 中的示例相反,您内部只发生了一件事,多项操作可能导致不明显的行为:
def get_url_http_response(url)
uri = URI.parse(URI.encode(url))
request = Timeout.timeout(25) { Net::HTTP.get_response(uri) }
return request
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -1)
rescue Timeout::Error
# return here anything you want
end
我有一个可以产生错误并将其发送给 Active Admin 使用的工作系统。
例如,在 Active admin 中,对于我们 CMS 的特定页面,该页面可能会执行:
url_must_be_accessible("http://www.exmaple.com", field_url_partner, "URL for the partner")
这使用下面的代码向活动管理编辑器发送不同类型的错误通知:
module UrlHttpResponseHelper
def url_must_be_accessible(url, target_field, field_name)
if url
url_response_code = get_url_http_response(url).code.to_i
case url_response_code
when -1
# DNS issue; website does not exist;
errors.add(target_field,
"#{field_name}: DNS Problem -> #{url} website does not exist")
when 200
return
when 304
return
else
errors.add(target_field,
"#{field_name}: #{url} sends #{url_response_code} response code")
end
end
end
def get_url_http_response(url)
uri = URI.parse(URI.encode(url))
request = Net::HTTP.get_response(uri)
return request
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -1)
end
end
在本地模式下,效果很好!但在生产中,我们在 Heroku 上,当请求 pn Heroku 超过 30 秒时,就像你尝试这个 link "http://www.exmaple.com", the app crashes with a "H12 error".
我想在上面的代码中添加两件事 - 超时:我想我需要 read_timeout 和 open_timeout 并且 read_timeout + open_timeout 应该 < 到 30 秒,让我们采取一些安全措施,最好 < 25 秒
如果请求在 25 秒后仍然是 "going",则通过 给出 up/dropping 请求来避免达到 30 秒
并通过向用户发送通知来捕获此 "we dropped the request intentionnally because risk of timeout"。我想按照以下方式使用我当前的系统:
rescue Errno::ECONNREFUSED, SocketError => e OpenStruct.new(code: -7) # = some random number end case url_response_code when -7 errors.add(target_field, "#{field_name}: We tried to reach #{url} but this takes too long and risks crashing the app. please check the url and try again.")
我怎样才能创建一个像 -1 这样的代码,但又要创建另一个代码来挽救我自己执行的 "timeout"/"drop the request attempt"。
尝试过,但没有任何效果。如果达到 25 秒,我无法创建捕获和丢弃此请求的代码...
这不是很漂亮的解决方案(请参阅:https://medium.com/@adamhooper/in-ruby-dont-use-timeout-77d9d4e5a001),但我相信您仍然可以在这里使用它,因为与 link 中的示例相反,您内部只发生了一件事,多项操作可能导致不明显的行为:
def get_url_http_response(url)
uri = URI.parse(URI.encode(url))
request = Timeout.timeout(25) { Net::HTTP.get_response(uri) }
return request
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -1)
rescue Timeout::Error
# return here anything you want
end