即使我可以捕获从@ post.save引发的异常并记录错误并打印线程
begin
if @post.save
rescue Exception => ex
# rescue Errno::ECONNREFUSED => ex
Thread.list.each {|t| p t}
Rails.logger.error "ERROR: Could not save blog post! Is the Solr server up and running? Exception: #{ex}"
它仍然在网页上出错,并且没有在堆栈跟踪中显示我的任何代码。 solr Sunspot模型回调在一个单独的线程上运行。
rsolr (1.0.9) lib/rsolr/connection.rb:19:in `rescue in execute'
rsolr (1.0.9) lib/rsolr/connection.rb:14:in `execute'
...
sunspot_rails (2.1.0) lib/sunspot/rails/solr_instrumentation.rb:15:in `send_and_receive_with_as_instrumentation'
(eval):2:in `post'
rsolr (1.0.9) lib/rsolr/client.rb:67:in `update'
...
/usr/local/rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/webrick/httpserver.rb:138:in `service'
/usr/local/rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/webrick/httpserver.rb:94:in `run'
/usr/local/rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/webrick/server.rb:295:in `block in start_thread'
注意block in start_thread
?
那么如何捕获此异常并向用户显示错误?我不认为整个应用程序应该崩溃只是因为Solr没有运行。
我发现了这个http://makandracards.com/makandra/5273-using-solr-with-sunspot,但它只描述了如何捕获搜索异常,而不是索引/更新异常。
答案 0 :(得分:2)
哇。看似20个小时......创建lib / rsolr / connection.rb:
require 'net/http'
require 'net/https'
# The default/Net::Http adapter for RSolr.
class RSolr::Connection
# using the request_context hash,
# send a request,
# then return the standard rsolr response hash {:status, :body, :headers}
def execute client, request_context
h = http request_context[:uri], request_context[:proxy], request_context[:read_timeout], request_context[:open_timeout]
request = setup_raw_request request_context
request.body = request_context[:data] if request_context[:method] == :post and request_context[:data]
begin
response = h.request request
charset = response.type_params["charset"]
{:status => response.code.to_i, :headers => response.to_hash, :body => force_charset(response.body, charset)}
rescue Errno::ECONNREFUSED => e
Rails.logger.error "ERROR: #execute: Could not connect to Solr: #{e.message}"
# How to display an error message to the user?
# ActionController::Base.flash.now.alert "Could not connect to search indexer."
# Maybe http://stackoverflow.com/questions/393395/how-to-call-expire-fragment-from-rails-observer-model/608700#608700 ?
return nil
# raise(Errno::ECONNREFUSED.new(request_context.inspect))
# catch the undefined closed? exception -- this is a confirmed ruby bug
rescue NoMethodError
Rails.logger.error "ERROR: #execute: NoMethodError: Could not connect to Solr: #{e.message}"
return nil
# $!.message == "undefined method `closed?' for nil:NilClass" ?
# raise(Errno::ECONNREFUSED.new) :
# raise($!)
end
end
protected
# This returns a singleton of a Net::HTTP or Net::HTTP.Proxy request object.
def http uri, proxy = nil, read_timeout = nil, open_timeout = nil
@http ||= (
http = if proxy
proxy_user, proxy_pass = proxy.userinfo.split(/:/) if proxy.userinfo
Net::HTTP.Proxy(proxy.host, proxy.port, proxy_user, proxy_pass).new uri.host, uri.port
else
Net::HTTP.new uri.host, uri.port
end
http.use_ssl = uri.port == 443 || uri.instance_of?(URI::HTTPS)
http.read_timeout = read_timeout if read_timeout
http.open_timeout = open_timeout if open_timeout
http
)
end
#
def setup_raw_request request_context
http_method = case request_context[:method]
when :get
Net::HTTP::Get
when :post
Net::HTTP::Post
when :head
Net::HTTP::Head
else
raise "Only :get, :post and :head http method types are allowed."
end
headers = request_context[:headers] || {}
raw_request = http_method.new request_context[:uri].request_uri
raw_request.initialize_http_header headers
raw_request.basic_auth(request_context[:uri].user, request_context[:uri].password) if request_context[:uri].user && request_context[:uri].password
raw_request
end
private
def force_charset body, charset
return body unless charset and body.respond_to?(:force_encoding)
body.force_encoding(charset)
end
end