How can I catch the Sunspot rsolr exception raised in another thread from the model callback?

Even if I can catch the exception raised from @ post.save and log the error and print the threads

begin if @post.save rescue Exception => ex # rescue Errno::ECONNREFUSED => ex Thread.list.each {|t| pt} Rails.logger.error "ERROR: Could not save blog post! Is the Solr server up and running? Exception: #{ex}" 

it still contains errors on the webpage and does not show any of my code in the stack trace. The Solr Sunspot model callback runs in a separate thread.

 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' 

Pay attention to block in start_thread ?

So how can I catch this exception and show the user an error? I don't think the whole application should crash just because Solr is down.

I found this, http://makandracards.com/makandra/5273-using-solr-with-sunspot , but it only describes how to catch search exceptions, not index / update exceptions.

+2
source share
1 answer

Wow. After what seems like 20 hours ... create 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 
+2
source

Source: https://habr.com/ru/post/1500370/


All Articles