sunspot-queue 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ # Sunspot Queue Changelog
2
+
3
+ ## 0.10.0
4
+ * Sidekiq support
5
+ * SessionProxy now takes a backend as a second required option
6
+ * Sunspot::Queue::Resque::Backend is the backend for Resque
7
+ * Sunspot::Queue::Sidekiq::Backend is the backend for Sidekiq
8
+
9
+ ## 0.9.1
10
+ * Jobs no longer auto commit the solr index. Commits should be done by another process or
11
+ Solr should be configured handle commits automatically (autoCommit config option).
12
+
13
+ ## 0.9.0
14
+ * Initial Release
data/README.md CHANGED
@@ -1,25 +1,88 @@
1
- # sunspot-queue
1
+ # sunspot-queue [![Build Status](https://secure.travis-ci.org/gaffneyc/sunspot-queue.png?branch=master)](http://travis-ci.org/gaffneyc/sunspot-queue)
2
2
 
3
3
  Background search indexing using existing worker systems.
4
4
 
5
5
  ## Install
6
6
 
7
- $ gem install sunspot-queue
7
+ ```console
8
+ $ gem install sunspot-queue
9
+ ```
8
10
 
9
- ## Usage with Rails (or without)
11
+ ## Usage with Rails and Resque
10
12
 
11
13
  In your Gemfile
12
14
 
13
- gem "sunspot-queue"
14
- gem "resque"
15
+ ```ruby
16
+ gem "sunspot-queue"
17
+ gem "resque"
18
+ ```
15
19
 
16
20
  In config/initializers/sunspot.rb
17
21
 
18
- Sunspot.session = Sunspot::Queue::SessionProxy.new(Sunspot.session)
22
+ ```ruby
23
+ require "sunspot/queue/resque"
24
+ backend = Sunspot::Queue::Resque::Backend.new
25
+ Sunspot.session = Sunspot::Queue::SessionProxy.new(Sunspot.session, backend)
26
+ ```
19
27
 
20
28
  Start Resque
21
29
 
22
- $ QUEUE=sunspot rake resque:work
30
+ ```console
31
+ $ QUEUE=sunspot rake resque:work
32
+ ```
33
+
34
+ ## Usage with Rails and Sidekiq
35
+
36
+ In your Gemfile
37
+
38
+ ```ruby
39
+ gem "sunspot-queue"
40
+ gem "sidekiq"
41
+ ```
42
+
43
+ In config/initializers/sunspot.rb
44
+
45
+ ```ruby
46
+ require "sunspot/queue/sidekiq"
47
+ backend = Sunspot::Queue::Sidekiq::Backend.new
48
+ Sunspot.session = Sunspot::Queue::SessionProxy.new(Sunspot.session, backend)
49
+ ```
50
+
51
+ Start Sidekiq
52
+
53
+ ```console
54
+ $ sidekiq -q sunspot
55
+ ```
56
+
57
+ ## Configuring Sunspot Queue
58
+
59
+ In config/initializers/sunspot.rb
60
+
61
+ ```ruby
62
+ Sunspot::Queue.configure do |config|
63
+ # Override default job classes
64
+ config.index_job = CustomIndexJob
65
+ config.removal_job = CustomRemovalJob
66
+ end
67
+ ```
68
+
69
+ ## Configuring Auto Commit
70
+
71
+ The sunspot-queue jobs update the Solr index but those changes don't appear in
72
+ search results until Solr commits those changes. Solr supports automatically
73
+ commiting changes based on either the number of changes and / or time between
74
+ commits.
75
+
76
+ Add (or uncomment) the following in solrconfig.xml
77
+
78
+ ```xml
79
+ <autoCommit>
80
+ <maxDocs>10000</maxDocs>
81
+ <maxTime>30000</maxTime>
82
+ </autoCommit>
83
+ ```
84
+
85
+ See [Solr's documentation](http://wiki.apache.org/solr/SolrConfigXml#Update_Handler_Section) for more information.
23
86
 
24
87
  ## Note on Patches/Pull Requests
25
88
 
@@ -32,9 +95,11 @@ Please don't make changes to the Rakefile, version, or history.
32
95
 
33
96
  ## Development
34
97
 
35
- $ gem install bundler (if you don't have it)
36
- $ bundle install
37
- $ guard
98
+ ```console
99
+ $ gem install bundler
100
+ $ bundle
101
+ $ guard
102
+ ```
38
103
 
39
104
  ## Copyright
40
105
 
@@ -2,10 +2,17 @@ module Sunspot
2
2
  module Queue
3
3
  class Error < StandardError; end
4
4
  class NotPersistedError < Error; end
5
+
6
+ def self.configure(&blk)
7
+ yield configuration
8
+ end
9
+
10
+ def self.configuration
11
+ @configuration ||= Sunspot::Queue::Configuration.new
12
+ end
5
13
  end
6
14
  end
7
15
 
8
16
  require "sunspot/queue/version"
17
+ require "sunspot/queue/configuration"
9
18
  require "sunspot/queue/session_proxy"
10
- require "sunspot/queue/index_job"
11
- require "sunspot/queue/removal_job"
@@ -0,0 +1,5 @@
1
+ module Sunspot::Queue
2
+ class Configuration
3
+ attr_accessor :index_job, :removal_job
4
+ end
5
+ end
@@ -16,5 +16,16 @@ module Sunspot::Queue
16
16
  ensure
17
17
  Sunspot.session = proxy if proxy
18
18
  end
19
+
20
+ def constantize(klass)
21
+ names = klass.to_s.split('::')
22
+ names.shift if names.empty? || names.first.empty?
23
+
24
+ constant = Object
25
+ names.each do |name|
26
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
27
+ end
28
+ constant
29
+ end
19
30
  end
20
31
  end
@@ -0,0 +1,5 @@
1
+ module Sunspot::Queue
2
+ module Inline
3
+ require "sunspot/queue/inline/backend"
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ require "sunspot/queue/inline"
2
+ require "sunspot/queue/helpers"
3
+
4
+ module Sunspot::Queue::Inline
5
+ class Backend
6
+ include ::Sunspot::Queue::Helpers
7
+
8
+ def index(klass, id)
9
+ without_proxy do
10
+ constantize(klass).find(id).solr_index
11
+ end
12
+ end
13
+
14
+ def remove(klass, id)
15
+ without_proxy do
16
+ ::Sunspot.remove_by_id(klass, id)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ require "sunspot/queue"
2
+
3
+ module Sunspot::Queue
4
+ module Resque
5
+ require "sunspot/queue/resque/backend"
6
+ require "sunspot/queue/resque/index_job"
7
+ require "sunspot/queue/resque/removal_job"
8
+ end
9
+ end
10
+
11
+ # Backwards compatability with 0.9.x. Will be removed by 1.0 / 0.11.
12
+ ::Sunspot::Queue::IndexJob = ::Sunspot::Queue::Resque::IndexJob
13
+ ::Sunspot::Queue::RemovalJob = ::Sunspot::Queue::Resque::RemovalJob
@@ -0,0 +1,35 @@
1
+ require "resque"
2
+ require "sunspot/queue/resque/index_job"
3
+ require "sunspot/queue/resque/removal_job"
4
+
5
+ module Sunspot::Queue::Resque
6
+ class Backend
7
+ attr_reader :configuration
8
+
9
+ def initialize(configuration = Sunspot::Queue.configuration)
10
+ @configuration = configuration
11
+ end
12
+
13
+ def enqueue(job, klass, id)
14
+ ::Resque.enqueue(job, klass, id)
15
+ end
16
+
17
+ def index(klass, id)
18
+ enqueue(index_job, klass, id)
19
+ end
20
+
21
+ def remove(klass, id)
22
+ enqueue(removal_job, klass, id)
23
+ end
24
+
25
+ private
26
+
27
+ def index_job
28
+ configuration.index_job || ::Sunspot::Queue::Resque::IndexJob
29
+ end
30
+
31
+ def removal_job
32
+ configuration.removal_job || ::Sunspot::Queue::Resque::RemovalJob
33
+ end
34
+ end
35
+ end
@@ -1,8 +1,8 @@
1
1
  require "sunspot/queue/helpers"
2
2
 
3
- module Sunspot::Queue
3
+ module Sunspot::Queue::Resque
4
4
  class IndexJob
5
- extend Helpers
5
+ extend ::Sunspot::Queue::Helpers
6
6
 
7
7
  def self.queue
8
8
  :sunspot
@@ -10,7 +10,7 @@ module Sunspot::Queue
10
10
 
11
11
  def self.perform(klass, id)
12
12
  without_proxy do
13
- ::Resque.constantize(klass).find(id).solr_index
13
+ constantize(klass).find(id).solr_index
14
14
  end
15
15
  end
16
16
  end
@@ -1,8 +1,8 @@
1
1
  require "sunspot/queue/helpers"
2
2
 
3
- module Sunspot::Queue
3
+ module Sunspot::Queue::Resque
4
4
  class RemovalJob
5
- extend Helpers
5
+ extend ::Sunspot::Queue::Helpers
6
6
 
7
7
  def self.queue
8
8
  :sunspot
@@ -1,13 +1,11 @@
1
- require "resque"
2
- require "sunspot/queue/index_job"
3
- require "sunspot/queue/removal_job"
4
-
5
1
  module Sunspot::Queue
6
2
  class SessionProxy
7
3
  attr_reader :session
4
+ attr_accessor :backend
8
5
 
9
- def initialize(session)
6
+ def initialize(session, backend)
10
7
  @session = session
8
+ @backend = backend
11
9
  end
12
10
 
13
11
  def index(*objects)
@@ -18,7 +16,7 @@ module Sunspot::Queue
18
16
  end
19
17
 
20
18
  objects.each do |object|
21
- ::Resque.enqueue(IndexJob, object.class.name, object.id)
19
+ @backend.index(object.class.name, object.id)
22
20
  end
23
21
  end
24
22
  alias :index! :index
@@ -34,7 +32,7 @@ module Sunspot::Queue
34
32
  # persisted and can safely be ignored since it shouldn't exist in the
35
33
  # search index.
36
34
  if object.id
37
- ::Resque.enqueue(RemovalJob, object.class.name, object.id)
35
+ @backend.remove(object.class.name, object.id)
38
36
  end
39
37
  end
40
38
  end
@@ -51,7 +49,7 @@ module Sunspot::Queue
51
49
 
52
50
  # Enqueues a removal job based on class and id.
53
51
  def remove_by_id(klass, id)
54
- ::Resque.enqueue(RemovalJob, klass.to_s, id)
52
+ @backend.remove(klass.to_s, id)
55
53
  end
56
54
  alias :remove_by_id! :remove_by_id
57
55
 
@@ -0,0 +1,9 @@
1
+ require "sunspot/queue"
2
+
3
+ module Sunspot::Queue
4
+ module Sidekiq
5
+ require "sunspot/queue/sidekiq/backend"
6
+ require "sunspot/queue/sidekiq/index_job"
7
+ require "sunspot/queue/sidekiq/removal_job"
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ require "sunspot/queue/sidekiq/index_job"
2
+ require "sunspot/queue/sidekiq/removal_job"
3
+
4
+ module Sunspot::Queue::Sidekiq
5
+ class Backend
6
+ attr_reader :configuration
7
+
8
+ def initialize(configuration = Sunspot::Queue.configuration)
9
+ @configuration = configuration
10
+ end
11
+
12
+ # Job needs to include Sidekiq::Worker
13
+ def enqueue(job, klass, id)
14
+ job.perform_async(klass, id)
15
+ end
16
+
17
+ def index(klass, id)
18
+ index_job.perform_async(klass, id)
19
+ end
20
+
21
+ def remove(klass, id)
22
+ removal_job.perform_async(klass, id)
23
+ end
24
+
25
+ private
26
+
27
+ def index_job
28
+ configuration.index_job || ::Sunspot::Queue::Sidekiq::IndexJob
29
+ end
30
+
31
+ def removal_job
32
+ configuration.removal_job || ::Sunspot::Queue::Sidekiq::RemovalJob
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ require "sidekiq/worker"
2
+
3
+ module Sunspot::Queue::Sidekiq
4
+ class IndexJob
5
+ include ::Sunspot::Queue::Helpers
6
+ include ::Sidekiq::Worker
7
+
8
+ sidekiq_options :queue => "sunspot"
9
+
10
+ def perform(klass, id)
11
+ without_proxy do
12
+ constantize(klass).find(id).solr_index
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require "sidekiq/worker"
2
+
3
+ module Sunspot::Queue::Sidekiq
4
+ class RemovalJob
5
+ include ::Sunspot::Queue::Helpers
6
+ include ::Sidekiq::Worker
7
+
8
+ sidekiq_options :queue => "sunspot"
9
+
10
+ def perform(klass, id)
11
+ without_proxy do
12
+ ::Sunspot.remove_by_id(klass, id)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module Sunspot
2
2
  module Queue
3
- VERSION = "0.9.1"
3
+ VERSION = "0.10.0"
4
4
  end
5
5
  end
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ describe Sunspot::Queue::Configuration do
4
+ subject(:configuration) { described_class.new }
5
+
6
+ describe "#index_job" do
7
+ it "defaults to nil" do
8
+ configuration.index_job.should be_nil
9
+ end
10
+
11
+ it "can be set to a custom job" do
12
+ expect {
13
+ configuration.index_job = "CustomIndexJob"
14
+ }.to change(configuration, :index_job).to("CustomIndexJob")
15
+ end
16
+ end
17
+
18
+ describe "#removal_job" do
19
+ it "defaults to nil" do
20
+ configuration.removal_job.should be_nil
21
+ end
22
+
23
+ it "can be set to a custom job" do
24
+ expect do
25
+ configuration.removal_job = "CustomRemovalJob"
26
+ end.to change(configuration, :removal_job).to("CustomRemovalJob")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+ require "sunspot/queue/inline"
3
+
4
+ describe Sunspot::Queue::Inline::Backend, :backend => :inline do
5
+ it "indexes the class inline" do
6
+ expect do
7
+ Person.create(:name => "Steven Seagal")
8
+ commit
9
+ end.to change { Person.search.hits.size }.by(1)
10
+ end
11
+
12
+ it "removes the class inline" do
13
+ chuck = Person.create(:name => "Chuck Norris")
14
+ commit
15
+
16
+ expect do
17
+ chuck.destroy
18
+ commit
19
+ end.to change { Person.search.hits.size }.by(-1)
20
+ end
21
+ end
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- describe "Queued Indexing" do
3
+ describe "Queued Indexing", :backend => :resque do
4
4
  # Given an active record model
5
5
  # When I save the model
6
6
  # Then the record should not be in solr
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+
3
+ describe "Sidekiq Integration", :backend => :sidekiq do
4
+ let(:index_job) { Sunspot::Queue::Sidekiq::IndexJob }
5
+ let(:removal_job) { Sunspot::Queue::Sidekiq::RemovalJob }
6
+
7
+ #
8
+ it "queues indexing on creation and update" do
9
+ jimmy = Person.create(:name => "Jimmy Olson")
10
+
11
+ index_job.jobs.size.should == 1
12
+ index_job.perform_work
13
+ commit
14
+
15
+ Person.search { fulltext "Olson" }.hits.size.should == 1
16
+
17
+ jimmy.update_attribute(:name, "James Bartholomew Olsen")
18
+ index_job.jobs.size.should == 1
19
+ index_job.perform_work
20
+ commit
21
+
22
+ Person.search { fulltext "Bartholomew" }.hits.size.should == 1
23
+ end
24
+
25
+ it "queues removal on destroy" do
26
+ pinky =
27
+ without_proxy do
28
+ Person.create(:name => "Pinky the Whiz Kid")
29
+ end
30
+ commit
31
+
32
+ Person.search.hits.size.should == 1
33
+
34
+ pinky.destroy
35
+ removal_job.jobs.size.should == 1
36
+ removal_job.perform_work
37
+ commit
38
+
39
+ Person.search.hits.size.should == 0
40
+ end
41
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ describe Sunspot::Queue do
4
+
5
+ describe "#configuration" do
6
+ it "returns a default configuration" do
7
+ config = Sunspot::Queue.configuration
8
+ config.should be_kind_of(Sunspot::Queue::Configuration)
9
+ end
10
+
11
+ it "returns the same configuration when requested multiple times" do
12
+ config = Sunspot::Queue.configuration
13
+ Sunspot::Queue.configuration.should be(config)
14
+ Sunspot::Queue.configuration.should be(config)
15
+ end
16
+ end
17
+
18
+ describe "#configure(&blk)" do
19
+ it "yields the configuration to a block" do
20
+ config = Sunspot::Queue.configuration
21
+ expect do |blk|
22
+ Sunspot::Queue.configure(&blk)
23
+ end.to yield_with_args(config)
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+
3
+ describe Sunspot::Queue::Resque::Backend do
4
+
5
+ # Mock ResqueJob
6
+ class CustomResqueJob
7
+ @queue = :custom_queue
8
+
9
+ def perform(klass, id)
10
+ end
11
+ end
12
+
13
+ subject(:backend) { described_class.new(configuration) }
14
+
15
+ let(:configuration) { ::Sunspot::Queue::Configuration.new }
16
+
17
+ describe "#index" do
18
+ it "uses the index job set in the global configuration" do
19
+ configuration.index_job = CustomResqueJob
20
+
21
+ expect do
22
+ backend.index(Person, 3)
23
+ end.to change { ResqueSpec.queue_for(CustomResqueJob).size }.by(1)
24
+ end
25
+
26
+ it "uses the default index job if one is not configured" do
27
+ expect do
28
+ backend.index(Person, 12)
29
+ end.to change { ResqueSpec.queue_for(Sunspot::Queue::Resque::IndexJob).size }.by(1)
30
+ end
31
+ end
32
+
33
+ describe "#remove" do
34
+ it "uses the removal job set in the global configuration" do
35
+ configuration.removal_job = CustomResqueJob
36
+
37
+ expect do
38
+ backend.remove(Person, 3)
39
+ end.to change { ResqueSpec.queue_for(CustomResqueJob).size }.by(1)
40
+ end
41
+
42
+ it "uses the default index job if one is not configured" do
43
+ expect do
44
+ backend.remove(Person, 12)
45
+ end.to change { ResqueSpec.queue_for(Sunspot::Queue::Resque::RemovalJob).size }.by(1)
46
+ end
47
+ end
48
+ end
@@ -1,13 +1,19 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Sunspot::Queue::IndexJob do
3
+ describe Sunspot::Queue::Resque::IndexJob do
4
+ it "is linked to Sunspot::Queue::IndexJob for backwards compatibility" do
5
+ ::Sunspot::Queue::IndexJob.should == ::Sunspot::Queue::Resque::IndexJob
6
+ end
7
+
4
8
  context "ActiveRecord" do
9
+ let(:job) { Sunspot::Queue::Resque::IndexJob }
10
+
5
11
  it "indexes an ActiveRecord model" do
6
12
  # This will queue a job but we'll just ignore it to isolate the job
7
13
  person = Person.create(:name => "The Grandson")
8
14
 
9
15
  expect do
10
- Sunspot::Queue::IndexJob.perform(Person, person.id)
16
+ job.perform(Person, person.id)
11
17
  commit
12
18
  end.to change { Person.search.hits.size }.by(1)
13
19
 
@@ -17,13 +23,13 @@ describe Sunspot::Queue::IndexJob do
17
23
 
18
24
  it "raises an error if the record could not be found" do
19
25
  expect do
20
- Sunspot::Queue::IndexJob.perform(Person, 404)
26
+ job.perform(Person, 404)
21
27
  end.to raise_error(ActiveRecord::RecordNotFound)
22
28
  end
23
29
 
24
30
  it "maintains the existing proxy if there was an error" do
25
31
  expect do
26
- Sunspot::Queue::IndexJob.perform(Person, 404) rescue nil
32
+ job.perform(Person, 404) rescue nil
27
33
  end.to_not change { Sunspot.session }
28
34
  end
29
35
 
@@ -31,7 +37,7 @@ describe Sunspot::Queue::IndexJob do
31
37
  person = Person.create(:name => "The Grandson")
32
38
 
33
39
  expect do
34
- Sunspot::Queue::IndexJob.perform(Person, person.id)
40
+ job.perform(Person, person.id)
35
41
  end.to_not change { Person.search.hits.size }
36
42
 
37
43
  expect do
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+ require "sunspot/queue/resque"
3
+ require "sunspot/queue/helpers"
4
+
5
+ describe Sunspot::Queue::Resque::RemovalJob do
6
+ let(:job) { Sunspot::Queue::Resque::RemovalJob }
7
+
8
+ it "is linked to Sunspot::Queue::IndexJob for backwards compatibility" do
9
+ ::Sunspot::Queue::RemovalJob.should == ::Sunspot::Queue::Resque::RemovalJob
10
+ end
11
+
12
+ it "removes a job from the search index" do
13
+ person =
14
+ without_proxy do
15
+ Person.create(:name => "The Albino")
16
+ end
17
+ commit
18
+
19
+ Person.search.hits.size.should == 1
20
+
21
+ expect do
22
+ job.perform(Person, person.id)
23
+ commit
24
+ end.to change { Person.search.hits.size }.by(-1)
25
+ end
26
+ end
@@ -1,7 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Sunspot::Queue::SessionProxy do
4
- let(:proxy) { Sunspot::Queue::SessionProxy.new(mock) }
4
+ let(:backend) { mock }
5
+ let(:proxy) { Sunspot::Queue::SessionProxy.new(mock, backend) }
5
6
 
6
7
  context "#index" do
7
8
  it "enqueues a single job for each class" do
@@ -9,8 +10,7 @@ describe Sunspot::Queue::SessionProxy do
9
10
  Person.create(:name => "#{i} of 5")
10
11
  end
11
12
 
12
- Resque.should_receive(:enqueue).with do |job, klass, id|
13
- job.should == ::Sunspot::Queue::IndexJob
13
+ backend.should_receive(:index).with do |klass, _|
14
14
  klass.should == "Person"
15
15
  end.exactly(5).times
16
16
 
@@ -22,7 +22,7 @@ describe Sunspot::Queue::SessionProxy do
22
22
  Person.create(:name => "Clone ##{i}")
23
23
  end
24
24
 
25
- Resque.should_receive(:enqueue).exactly(2).times
25
+ backend.should_receive(:index).exactly(2).times
26
26
 
27
27
  proxy.index(people)
28
28
  end
@@ -30,7 +30,7 @@ describe Sunspot::Queue::SessionProxy do
30
30
  it "handles a single object being enqueued" do
31
31
  person = Person.create(:name => "Buttercup")
32
32
 
33
- Resque.should_receive(:enqueue).with do |_,_,id|
33
+ backend.should_receive(:index).with do |_, id|
34
34
  id.should == person.id
35
35
  end
36
36
 
@@ -62,7 +62,8 @@ describe Sunspot::Queue::SessionProxy do
62
62
  people = 2.times.map { |i| Person.new(:name => i) }
63
63
  people.first.save
64
64
 
65
- Resque.should_not_receive(:enqueue)
65
+ backend.should_not_receive(:index)
66
+
66
67
  expect do
67
68
  proxy.index(people)
68
69
  end.to raise_error(Sunspot::Queue::NotPersistedError)
@@ -75,8 +76,7 @@ describe Sunspot::Queue::SessionProxy do
75
76
  Person.create(:name => "#{i} of 5")
76
77
  end
77
78
 
78
- Resque.should_receive(:enqueue).with do |job, klass, id|
79
- job.should == ::Sunspot::Queue::RemovalJob
79
+ backend.should_receive(:remove).with do |klass, id|
80
80
  klass.should == "Person"
81
81
  end.exactly(5).times
82
82
 
@@ -88,7 +88,7 @@ describe Sunspot::Queue::SessionProxy do
88
88
  Person.create(:name => "Clone ##{i}")
89
89
  end
90
90
 
91
- Resque.should_receive(:enqueue).exactly(2).times
91
+ backend.should_receive(:remove).exactly(2).times
92
92
 
93
93
  proxy.remove(people)
94
94
  end
@@ -96,8 +96,7 @@ describe Sunspot::Queue::SessionProxy do
96
96
  it "handles a single object" do
97
97
  person = Person.create(:name => "Buttercup")
98
98
 
99
- Resque.should_receive(:enqueue).with do |job, _, id|
100
- job.should == ::Sunspot::Queue::RemovalJob
99
+ backend.should_receive(:remove).with do |_, id|
101
100
  id.should == person.id
102
101
  end
103
102
 
@@ -108,7 +107,7 @@ describe Sunspot::Queue::SessionProxy do
108
107
  people = 2.times.map { |i| Person.new(:name => "Thing #{i}") }
109
108
  people.first.save
110
109
 
111
- Resque.should_receive(:enqueue).once
110
+ backend.should_receive(:remove).once
112
111
 
113
112
  proxy.remove(people)
114
113
  end
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+
3
+ describe Sunspot::Queue::Sidekiq::Backend do
4
+
5
+ # Mock SidekiqJob
6
+ class CustomSidekiqJob
7
+ include ::Sidekiq::Worker
8
+
9
+ def perform(klass, id)
10
+ end
11
+ end
12
+
13
+ subject(:backend) { described_class.new(configuration) }
14
+
15
+ let(:configuration) { ::Sunspot::Queue::Configuration.new }
16
+
17
+ describe "#index" do
18
+ it "uses the index job set in the global configuration" do
19
+ configuration.index_job = CustomSidekiqJob
20
+
21
+ expect do
22
+ backend.index(Person, 9)
23
+ end.to change { CustomSidekiqJob.jobs.size }.by(1)
24
+ end
25
+
26
+ it "uses the default index job if one is not configured" do
27
+ expect do
28
+ backend.index(Person, 11)
29
+ end.to change { ::Sunspot::Queue::Sidekiq::IndexJob.jobs.size }.by(1)
30
+ end
31
+ end
32
+
33
+ describe "#remove" do
34
+ it "uses the removal job set in the global configuration" do
35
+ configuration.removal_job = CustomSidekiqJob
36
+
37
+ expect do
38
+ backend.remove(Person, 11)
39
+ end.to change { CustomSidekiqJob.jobs.size }.by(1)
40
+ end
41
+
42
+ it "uses the default removal job if one is not configured" do
43
+ expect do
44
+ backend.remove(Person, 11)
45
+ end.to change { ::Sunspot::Queue::Sidekiq::RemovalJob.jobs.size }.by(1)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Sunspot::Queue::Sidekiq::IndexJob do
4
+ context "ActiveRecord" do
5
+ let(:job) { Sunspot::Queue::Sidekiq::IndexJob.new }
6
+
7
+ it "index an ActiveRecord model" do
8
+ person = Person.create(:name => "Dum Dum Dugen")
9
+
10
+ expect do
11
+ job.perform(Person, person.id)
12
+ commit
13
+ end.to change { Person.search.hits.size }.by(1)
14
+ end
15
+
16
+ it "raises an error if the record could not be found" do
17
+ expect do
18
+ job.perform(Person, 404)
19
+ end.to raise_error(ActiveRecord::RecordNotFound)
20
+ end
21
+
22
+ it "maintains the existing proxy if there was an error" do
23
+ expect do
24
+ job.perform(Person, 404) rescue nil
25
+ end.to_not change { Sunspot.session }
26
+ end
27
+
28
+ it "does not commit changes to the index" do
29
+ person = Person.create(:name => "Kato")
30
+
31
+ expect do
32
+ job.perform(Person, person.id)
33
+ end.to_not change { Person.search.hits.size }
34
+
35
+ expect do
36
+ commit
37
+ end.to change { Person.search.hits.size }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe Sunspot::Queue::Sidekiq::RemovalJob do
4
+ let(:job) { Sunspot::Queue::Sidekiq::RemovalJob.new }
5
+
6
+ it "removes a job from the search index" do
7
+ person = Person.create(:name => "James 'Bucky' Barnes")
8
+ commit
9
+
10
+ Person.search.hits.size.should == 1
11
+
12
+ expect do
13
+ job.perform(Person, person.id)
14
+ commit
15
+ end.to change { Person.search.hits.size }.by(-1)
16
+ end
17
+ end
@@ -8,6 +8,14 @@ require "sunspot/rails"
8
8
  require "sunspot/solr/server"
9
9
  require "resque_spec"
10
10
 
11
+ # Neither is required when loading sunspot/queue
12
+ require "sunspot/queue/resque"
13
+ require "sunspot/queue/sidekiq"
14
+
15
+ # Sidekiq
16
+ require "sidekiq"
17
+ require "sidekiq/testing"
18
+
11
19
  # Configure ActiveRecord and Sunspot to work with ActiveRecord
12
20
  ActiveRecord::Base.establish_connection(
13
21
  :adapter => "sqlite3",
@@ -35,7 +43,11 @@ end
35
43
  RSpec.configure do |config|
36
44
  config.treat_symbols_as_metadata_keys_with_true_values = true
37
45
  config.run_all_when_everything_filtered = true
38
- config.filter_run :focus
46
+ config.order = "random"
47
+
48
+ # Requires supporting ruby files with custom matchers and macros, etc,
49
+ # in spec/support/ and its subdirectories.
50
+ Dir[File.expand_path("../support/*.rb", __FILE__)].each { |f| require(f) }
39
51
 
40
52
  config.include(Sunspot::Queue::Helpers)
41
53
  config.include(
@@ -49,11 +61,30 @@ RSpec.configure do |config|
49
61
  # Original sunspot session not wrapped in our proxy object
50
62
  session = Sunspot.session
51
63
 
64
+ # Clean up data between tests and reset the session
52
65
  config.before(:each) do
66
+ Sunspot.session = session
53
67
  session.remove_all!
68
+ end
69
+
70
+ config.before(:each, :backend => :resque) do
54
71
  ResqueSpec.reset!
55
72
 
56
- Sunspot.session = Sunspot::Queue::SessionProxy.new(session)
73
+ backend = Sunspot::Queue::Resque::Backend.new
74
+ Sunspot.session = Sunspot::Queue::SessionProxy.new(session, backend)
75
+ end
76
+
77
+ config.before(:each, :backend => :sidekiq) do
78
+ Sidekiq::Worker.clear_all
79
+
80
+ require "sunspot/queue/sidekiq"
81
+ backend = Sunspot::Queue::Sidekiq::Backend.new
82
+ Sunspot.session = Sunspot::Queue::SessionProxy.new(session, backend)
83
+ end
84
+
85
+ config.before(:each, :backend => :inline) do
86
+ backend = Sunspot::Queue::Inline::Backend.new
87
+ Sunspot.session = Sunspot::Queue::SessionProxy.new(session, backend)
57
88
  end
58
89
 
59
90
  # Configure Solr and run a server in the background for the duration of the
@@ -0,0 +1,19 @@
1
+ module Sidekiq
2
+ module Worker
3
+ module ClassMethods
4
+ def perform_work
5
+ if job = jobs.pop
6
+ self.new.perform(*Sidekiq.load_json(Sidekiq.dump_json(job["args"])))
7
+ end
8
+
9
+ true
10
+ end
11
+
12
+ def perform_all_the_work
13
+ while jobs.any?
14
+ perform_work
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunspot-queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-01 00:00:00.000000000 Z
12
+ date: 2013-01-23 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sunspot_rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.3.0
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: resque
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -19,7 +35,7 @@ dependencies:
19
35
  - - ! '>='
20
36
  - !ruby/object:Gem::Version
21
37
  version: '0'
22
- type: :runtime
38
+ type: :development
23
39
  prerelease: false
24
40
  version_requirements: !ruby/object:Gem::Requirement
25
41
  none: false
@@ -28,21 +44,37 @@ dependencies:
28
44
  - !ruby/object:Gem::Version
29
45
  version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
- name: sunspot_rails
47
+ name: sidekiq
32
48
  requirement: !ruby/object:Gem::Requirement
33
49
  none: false
34
50
  requirements:
35
51
  - - ! '>='
36
52
  - !ruby/object:Gem::Version
37
- version: 1.3.0
38
- type: :runtime
53
+ version: '0'
54
+ type: :development
39
55
  prerelease: false
40
56
  version_requirements: !ruby/object:Gem::Requirement
41
57
  none: false
42
58
  requirements:
43
59
  - - ! '>='
44
60
  - !ruby/object:Gem::Version
45
- version: 1.3.0
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
46
78
  - !ruby/object:Gem::Dependency
47
79
  name: rspec
48
80
  requirement: !ruby/object:Gem::Requirement
@@ -50,7 +82,7 @@ dependencies:
50
82
  requirements:
51
83
  - - ~>
52
84
  - !ruby/object:Gem::Version
53
- version: 2.10.0
85
+ version: 2.11.0
54
86
  type: :development
55
87
  prerelease: false
56
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +90,7 @@ dependencies:
58
90
  requirements:
59
91
  - - ~>
60
92
  - !ruby/object:Gem::Version
61
- version: 2.10.0
93
+ version: 2.11.0
62
94
  - !ruby/object:Gem::Dependency
63
95
  name: resque_spec
64
96
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +146,7 @@ dependencies:
114
146
  requirements:
115
147
  - - ! '>='
116
148
  - !ruby/object:Gem::Version
117
- version: '0'
149
+ version: 3.2.0
118
150
  type: :development
119
151
  prerelease: false
120
152
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +154,7 @@ dependencies:
122
154
  requirements:
123
155
  - - ! '>='
124
156
  - !ruby/object:Gem::Version
125
- version: '0'
157
+ version: 3.2.0
126
158
  - !ruby/object:Gem::Dependency
127
159
  name: guard
128
160
  requirement: !ruby/object:Gem::Requirement
@@ -178,20 +210,39 @@ executables: []
178
210
  extensions: []
179
211
  extra_rdoc_files: []
180
212
  files:
213
+ - lib/sunspot/queue/configuration.rb
181
214
  - lib/sunspot/queue/helpers.rb
182
- - lib/sunspot/queue/index_job.rb
183
- - lib/sunspot/queue/removal_job.rb
215
+ - lib/sunspot/queue/inline/backend.rb
216
+ - lib/sunspot/queue/inline.rb
217
+ - lib/sunspot/queue/resque/backend.rb
218
+ - lib/sunspot/queue/resque/index_job.rb
219
+ - lib/sunspot/queue/resque/removal_job.rb
220
+ - lib/sunspot/queue/resque.rb
184
221
  - lib/sunspot/queue/session_proxy.rb
222
+ - lib/sunspot/queue/sidekiq/backend.rb
223
+ - lib/sunspot/queue/sidekiq/index_job.rb
224
+ - lib/sunspot/queue/sidekiq/removal_job.rb
225
+ - lib/sunspot/queue/sidekiq.rb
185
226
  - lib/sunspot/queue/version.rb
186
227
  - lib/sunspot/queue.rb
187
228
  - lib/sunspot-queue.rb
188
- - spec/index_job_spec.rb
229
+ - spec/configuration_spec.rb
230
+ - spec/inline/backend_spec.rb
189
231
  - spec/integration/indexing_spec.rb
190
- - spec/removal_job_spec.rb
232
+ - spec/integration/sidekiq_spec.rb
233
+ - spec/queue_spec.rb
234
+ - spec/resque/backend_spec.rb
235
+ - spec/resque/index_job_spec.rb
236
+ - spec/resque/removal_job_spec.rb
191
237
  - spec/session_proxy_spec.rb
238
+ - spec/sidekiq/backend_spec.rb
239
+ - spec/sidekiq/index_job_spec.rb
240
+ - spec/sidekiq/removal_job.rb
192
241
  - spec/spec_helper.rb
242
+ - spec/support/sidekiq.rb
193
243
  - LICENSE
194
244
  - README.md
245
+ - History.md
195
246
  homepage: https://github.com/gaffneyc/sunspot-queue
196
247
  licenses: []
197
248
  post_install_message:
@@ -204,12 +255,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
204
255
  - - ! '>='
205
256
  - !ruby/object:Gem::Version
206
257
  version: '0'
258
+ segments:
259
+ - 0
260
+ hash: -2557787847468836943
207
261
  required_rubygems_version: !ruby/object:Gem::Requirement
208
262
  none: false
209
263
  requirements:
210
264
  - - ! '>='
211
265
  - !ruby/object:Gem::Version
212
266
  version: '0'
267
+ segments:
268
+ - 0
269
+ hash: -2557787847468836943
213
270
  requirements: []
214
271
  rubyforge_project:
215
272
  rubygems_version: 1.8.24
@@ -1,20 +0,0 @@
1
- require "spec_helper"
2
- require "sunspot/queue/helpers"
3
-
4
- describe Sunspot::Queue::IndexJob do
5
- it "removes a job from the search index" do
6
- person =
7
- without_proxy do
8
- Person.create(:name => "The Albino").tap do
9
- commit
10
- end
11
- end
12
-
13
- Person.search.hits.size.should == 1
14
-
15
- expect do
16
- Sunspot::Queue::RemovalJob.perform(Person, person.id)
17
- commit
18
- end.to change { Person.search.hits.size }.by(-1)
19
- end
20
- end