sunspot-queue 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.md +14 -0
- data/README.md +75 -10
- data/lib/sunspot/queue.rb +9 -2
- data/lib/sunspot/queue/configuration.rb +5 -0
- data/lib/sunspot/queue/helpers.rb +11 -0
- data/lib/sunspot/queue/inline.rb +5 -0
- data/lib/sunspot/queue/inline/backend.rb +20 -0
- data/lib/sunspot/queue/resque.rb +13 -0
- data/lib/sunspot/queue/resque/backend.rb +35 -0
- data/lib/sunspot/queue/{index_job.rb → resque/index_job.rb} +3 -3
- data/lib/sunspot/queue/{removal_job.rb → resque/removal_job.rb} +2 -2
- data/lib/sunspot/queue/session_proxy.rb +6 -8
- data/lib/sunspot/queue/sidekiq.rb +9 -0
- data/lib/sunspot/queue/sidekiq/backend.rb +35 -0
- data/lib/sunspot/queue/sidekiq/index_job.rb +16 -0
- data/lib/sunspot/queue/sidekiq/removal_job.rb +16 -0
- data/lib/sunspot/queue/version.rb +1 -1
- data/spec/configuration_spec.rb +29 -0
- data/spec/inline/backend_spec.rb +21 -0
- data/spec/integration/indexing_spec.rb +1 -1
- data/spec/integration/sidekiq_spec.rb +41 -0
- data/spec/queue_spec.rb +27 -0
- data/spec/resque/backend_spec.rb +48 -0
- data/spec/{index_job_spec.rb → resque/index_job_spec.rb} +11 -5
- data/spec/resque/removal_job_spec.rb +26 -0
- data/spec/session_proxy_spec.rb +11 -12
- data/spec/sidekiq/backend_spec.rb +48 -0
- data/spec/sidekiq/index_job_spec.rb +40 -0
- data/spec/sidekiq/removal_job.rb +17 -0
- data/spec/spec_helper.rb +33 -2
- data/spec/support/sidekiq.rb +19 -0
- metadata +72 -15
- data/spec/removal_job_spec.rb +0 -20
data/History.md
ADDED
@@ -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 [](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
|
-
|
7
|
+
```console
|
8
|
+
$ gem install sunspot-queue
|
9
|
+
```
|
8
10
|
|
9
|
-
## Usage with Rails
|
11
|
+
## Usage with Rails and Resque
|
10
12
|
|
11
13
|
In your Gemfile
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
```ruby
|
16
|
+
gem "sunspot-queue"
|
17
|
+
gem "resque"
|
18
|
+
```
|
15
19
|
|
16
20
|
In config/initializers/sunspot.rb
|
17
21
|
|
18
|
-
|
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
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
98
|
+
```console
|
99
|
+
$ gem install bundler
|
100
|
+
$ bundle
|
101
|
+
$ guard
|
102
|
+
```
|
38
103
|
|
39
104
|
## Copyright
|
40
105
|
|
data/lib/sunspot/queue.rb
CHANGED
@@ -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"
|
@@ -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,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
|
-
|
13
|
+
constantize(klass).find(id).solr_index
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
52
|
+
@backend.remove(klass.to_s, id)
|
55
53
|
end
|
56
54
|
alias :remove_by_id! :remove_by_id
|
57
55
|
|
@@ -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
|
@@ -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
|
@@ -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
|
data/spec/queue_spec.rb
ADDED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/spec/session_proxy_spec.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Sunspot::Queue::SessionProxy do
|
4
|
-
let(:
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/spec/spec_helper.rb
CHANGED
@@ -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.
|
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
|
-
|
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.
|
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:
|
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: :
|
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:
|
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:
|
38
|
-
type: :
|
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:
|
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.
|
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.
|
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:
|
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:
|
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/
|
183
|
-
- lib/sunspot/queue/
|
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/
|
229
|
+
- spec/configuration_spec.rb
|
230
|
+
- spec/inline/backend_spec.rb
|
189
231
|
- spec/integration/indexing_spec.rb
|
190
|
-
- spec/
|
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
|
data/spec/removal_job_spec.rb
DELETED
@@ -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
|