Sunspot .index: FloatDomainError: Infinity

285 views Asked by At

I have a large database of products (>23.000), and when I made a change to my schema.xml or in the search definitions of sunspot, I want to re-index all products. But sometimes the re-index fails with the following error:

FloatDomainError: Infinity
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/type.rb:142:in `to_i'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/type.rb:142:in `to_indexed'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/field.rb:44:in `to_indexed'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/field_factory.rb:59:in `populate_document'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/indexer.rb:100:in `block in prepare'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/indexer.rb:99:in `each'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/indexer.rb:99:in `prepare'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/indexer.rb:26:in `block in add'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/indexer.rb:26:in `map'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/indexer.rb:26:in `add'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/session.rb:91:in `index'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot/session_proxy/abstract_session_proxy.rb:11:in `index'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot/lib/sunspot.rb:184:in `index'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/gems/newrelic_rpm-3.6.8.168/lib/new_relic/agent/method_tracer.rb:508:in `block in index_with_trace_SolrClient_Sunspot_index'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/gems/newrelic_rpm-3.6.8.168/lib/new_relic/agent/method_tracer.rb:259:in `trace_execution_scoped'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/gems/newrelic_rpm-3.6.8.168/lib/new_relic/agent/method_tracer.rb:503:in `index_with_trace_SolrClient_Sunspot_index'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/bundler/gems/sunspot-5488725cb258/sunspot_rails/lib/sunspot/rails/searchable.rb:401:in `solr_index'
    from (irb):4:in `block in irb_binding'
    from (irb):4:in `each'
    from (irb):4
    from /var/www/domain1/shared/bundle/ruby/1.9.1/gems/railties-3.2.9/lib/rails/commands/console.rb:47:in `start'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/gems/railties-3.2.9/lib/rails/commands/console.rb:8:in `start'
    from /var/www/domain1/shared/bundle/ruby/1.9.1/gems/railties-3.2.9/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'irb(main):005:0>

I debugged into the re-index, and caught the product that is throwing that error. But then, when I try to call the .index method on that product, everything works fine.

I've read about this FloatDomainError: Infinity that this happens, when a certain number datatype that supports INFINITY is converted to a number datatype, that doesn't support INFINITY. The problem is, that I can't figure out, where to start debugging, or what exactly causes this error.

EDIT

I submitted an issue to the github repo: https://github.com/sunspot/sunspot/issues/521

Because it's easier, I add the information from github here as well:

This is my search definition for the count_on_hand field (that field which throws the error):

integer :count_on_hand, stored: true do |product|
  product.on_hand.nil? ? -1 : product.on_hand
end

I don't think that the schema.xml field definitions are helpful, because they only contain the standard configuration.

Then, I debugged into the populate_document method at field_factory.rb:57 inside the sunspot gem, and added some more output when the error is thrown:

model.inspect =>
#<Spree::Product id: 19502, name: "Foo Bar", description: "Bar foo", available_on: "2013-12-14 13:30:10", deleted_at: nil, permalink: "foo-bar", meta_description: nil, meta_keywords: "", tax_category_id: 3, shipping_category_id: 1, created_at: "2013-11-26 15:12:25", updated_at: "2013-12-14 13:30:10", count_on_hand: 2>

document.inspect =>
#<RSolr::Xml::Document:0x007ff6f4d58390 @fields=[#<RSolr::Xml::Field:0x007ff6f4d58570 @attrs={:name=>:id}, @value="Spree::Product 19502">,
<RSolr::Xml::Field:0x007ff6f4d58b88 @attrs={:name=>:type}, @value="Spree::Product">,
<RSolr::Xml::Field:0x007ff6f4d58e30 @attrs={:name=>:type}, @value="ActiveRecord::Base">,
<RSolr::Xml::Field:0x007ff6f49a3268 @attrs={:name=>:class_name}, @value="Spree::Product">,
<RSolr::Xml::Field:0x007ff6f47b95b0 @attrs={:name=>:available_on_d}, @value="2013-12-14T13:30:10Z">,
<RSolr::Xml::Field:0x007ff6f47a7220 @attrs={:name=>:price_f}, @value="10.3">],
@attrs={:boost=>1.0}>

@field =>
#<Sunspot::AttributeField:0x00000006081320 @multiple=false, @type=#<Sunspot::Type::IntegerType:0x00000003722dd0>, @name=:count_on_hand, @stored=true, @more_like_this=false, @indexed_name="count_on_hand_is", @reference=nil>

value =>
Infinity

As you can see, the count_on_hand from model.inspect has the value 2. But the value variable inside the method has the value Infinity. Furthermore, the count_on_hand doesn't show up in the document.inspect. I'm not sure, if this has something to do with it, but maybe it's a hint.

The problem is, that I can't reproduce this issue in development. That error above was thrown in production, and that's the reason why I monkey-patched the sunspot gem, and added this code into production (along with an Airbrake.notify):

module Sunspot
  module FieldFactory
    class Static < Abstract
      alias_method :old_populate_document, :populate_document
      def populate_document(document, model)
        begin
          value = @data_extractor.value_for(model)
          old_populate_document(document, model)
        rescue Exception => e
          message = $!.inspect
          model_msg = model.inspect
          document_msg = document.inspect
          field_msg = @field.inspect
          debugger
          Airbrake.notify(e,
             :error_message    => "Sunspot populate_document crashed with: #{message} ___________________ model: #{model_msg} ___________________ document: #{document_msg} ___________________ field: #{field_msg} ___________________ value: #{value}",
             :environment_name => "production"
           )
          raise(e)
        end
      end
    end
  end
end
0

There are 0 answers