require 'delayed_job' require 'thinking_sphinx' # Delayed Deltas for Thinking Sphinx, using Delayed Job. # # This documentation is aimed at those reading the code. If you're looking for # a guide to Thinking Sphinx and/or deltas, I recommend you start with the # Thinking Sphinx site instead - or the README for this library at the very # least. # # @author Patrick Allan # @see http://ts.freelancing-gods.com Thinking Sphinx # class ThinkingSphinx::Deltas::DelayedDelta < ThinkingSphinx::Deltas::DefaultDelta def self.cancel_jobs where_clause = [ "handler LIKE (?) AND locked_at IS NULL AND locked_by IS NULL AND failed_at IS NULL", "--- !ruby/object:ThinkingSphinx::Deltas::%" ] if Delayed::Job.respond_to?(:where) # Supported in Rails 3 and up. Delayed::Job.where(where_clause).delete_all else # Supported from Rails 2, deprecated in Rails 5. Delayed::Job.delete_all(where_clause) end end def self.enqueue_unless_duplicates(object) if Delayed::Job.respond_to?(:where) return if Delayed::Job.where( :handler => object.to_yaml, :locked_at => nil, :failed_at => nil ).count > 0 else return if Delayed::Job.count( :conditions => {:handler => object.to_yaml, :locked_at => nil, :failed_at => nil} ) > 0 end Delayed::Job.enqueue object, job_options end def self.job_options if Gem.loaded_specs['delayed_job'].version.to_s.match(/^2\.0\./) # Fallback for compatibility with old release 2.0.x of DJ # Only priority option is supported for these versions ThinkingSphinx::Configuration.instance.delayed_job_priority || 0 else { :priority => job_option(:delayed_job_priority, 0), :queue => job_option(:delayed_job_queue) } end end def self.job_option(setting, default = nil) configuration = ThinkingSphinx::Configuration.instance if configuration.respond_to? setting configuration.send(setting) elsif configuration.respond_to? :settings configuration.settings[setting.to_s] || default else default end end module Binary # Adds a job to the queue for processing the given model's delta index. A job # for hiding the instance in the core index is also created, if an instance is # provided. # # Neither job will be queued if updates or deltas are disabled, or if the # instance (when given) is not toggled to be in the delta index. The first two # options are controlled via ThinkingSphinx.updates_enabled? and # ThinkingSphinx.deltas_enabled?. # # @param [Class] model the ActiveRecord model to index. # @param [ActiveRecord::Base] instance the instance of the given model that # has changed. Optional. # @return [Boolean] true # def index(model, instance = nil) return true if skip? instance self.class.enqueue_unless_duplicates( ThinkingSphinx::Deltas::DelayedDelta::DeltaJob.new( model.delta_index_names ) ) Delayed::Job.enqueue( ThinkingSphinx::Deltas::DelayedDelta::FlagAsDeletedJob.new( model.core_index_names, instance.sphinx_document_id, instance.class.name, instance.id ), self.class.job_options ) if instance true end private # Checks whether jobs should be enqueued. Only true if updates and deltas are # enabled, and the instance (if there is one) is toggled. # # @param [ActiveRecord::Base, NilClass] instance # @return [Boolean] # def skip?(instance) !ThinkingSphinx.updates_enabled? || !ThinkingSphinx.deltas_enabled? || (instance && !toggled(instance)) end end module SphinxQL def delete(index, instance) id = instance.send(index.options[:primary_key] || :id) Delayed::Job.enqueue( ThinkingSphinx::Deltas::DelayedDelta::FlagAsDeletedJob.new( index.name, index.document_id_for_key(id), instance.class.name, id ), self.class.job_options ) end # Adds a job to the queue for processing the given index. # # @param [Class] index the Thinking Sphinx index object. # def index(index) self.class.enqueue_unless_duplicates( ThinkingSphinx::Deltas::DelayedDelta::DeltaJob.new(index.name) ) end end if [:delayed_job_priority, 'delayed_job_priority'].any? { |method| ThinkingSphinx::Configuration.instance_methods.include?(method) } include Binary else include SphinxQL end end require 'thinking_sphinx/deltas/delayed_delta/delta_job' require 'thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job' ThinkingSphinx.before_index_hooks << Proc.new { ThinkingSphinx::Deltas::DelayedDelta.cancel_jobs }