ts-resque-delta 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.markdown +57 -0
- data/Rakefile +6 -0
- data/config/redis-cucumber.conf +13 -0
- data/features/resque_deltas.feature +62 -0
- data/features/step_definitions/common_steps.rb +63 -0
- data/features/step_definitions/resque_delta_steps.rb +33 -0
- data/features/support/env.rb +35 -0
- data/features/support/redis_test_setup.rb +23 -0
- data/features/thinking_sphinx/database.example.yml +3 -0
- data/features/thinking_sphinx/database.yml +5 -0
- data/features/thinking_sphinx/db/migrations/create_delayed_betas.rb +17 -0
- data/features/thinking_sphinx/models/delayed_beta.rb +6 -0
- data/lib/thinking_sphinx/deltas/resque_delta.rb +74 -0
- data/lib/thinking_sphinx/deltas/resque_delta/delta_job.rb +54 -0
- data/lib/thinking_sphinx/deltas/resque_delta/flag_as_deleted_job.rb +30 -0
- data/lib/thinking_sphinx/deltas/resque_delta/tasks.rb +22 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/thinking_sphinx/deltas/resque_delta/delta_job_spec.rb +39 -0
- data/spec/thinking_sphinx/deltas/resque_delta/flag_as_deleted_job_spec.rb +66 -0
- data/spec/thinking_sphinx/deltas/resque_delta_spec.rb +93 -0
- data/tasks/distribution.rb +29 -0
- data/tasks/rails.rake +1 -0
- data/tasks/testing.rb +20 -0
- metadata +201 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Pat Allan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
Delayed Deltas for Thinking Sphinx (with Resque)
|
2
|
+
================================================
|
3
|
+
|
4
|
+
**This code is HEAVILY borrowed from [ts-delayed-delta](http://github.com/freelancing-god/ts-delayed-delta).**
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
You'll need Thinking Sphinx 1.3.0 or later, and Resque as well. The latter is flagged as a dependency.
|
10
|
+
|
11
|
+
gem install ts-resque-delta
|
12
|
+
|
13
|
+
In your `Gemfile` file, with the rest of your gem dependencies:
|
14
|
+
|
15
|
+
gem 'ts-resque-delta', '0.0.1', :require => 'thinking_sphinx/deltas/resque_delta'
|
16
|
+
|
17
|
+
And add the following line to the bottom of your `Rakefile`:
|
18
|
+
|
19
|
+
require 'thinking_sphinx/deltas/resque_delta/tasks'
|
20
|
+
|
21
|
+
For the indexes you want to use this delta approach, make sure you set that up in their `define_index` blocks.
|
22
|
+
|
23
|
+
define_index do
|
24
|
+
# ...
|
25
|
+
set_property :delta => ThinkingSphinx::Deltas::ResqueDelta
|
26
|
+
end
|
27
|
+
|
28
|
+
If you've never used delta indexes before, you'll want to add the boolean column named delta to each model that is using the approach.
|
29
|
+
|
30
|
+
def self.up
|
31
|
+
add_column :articles, :delta, :boolean, :default => true, :null => false
|
32
|
+
end
|
33
|
+
|
34
|
+
Usage
|
35
|
+
-----
|
36
|
+
|
37
|
+
Once you've got it all set up, all you need to do is make sure that the Resque worker is running. You can do this either by running Resque's workers and specifying the `:ts_delta` queue, or Thinking Sphinx's custom rake task:
|
38
|
+
|
39
|
+
rake thinking_sphinx:resque_delta
|
40
|
+
|
41
|
+
There's also a short name for the same task, to save your fingers some effort:
|
42
|
+
|
43
|
+
rake ts:rd
|
44
|
+
|
45
|
+
Original Contributors (for ts-delayed-delta)
|
46
|
+
--------------------------------------------
|
47
|
+
|
48
|
+
* [Pat Allan](http://github.com/freelancing-god)
|
49
|
+
* [Ryan Schlesinger](http://github.com/ryansch) (Allowing installs as a plugin)
|
50
|
+
* [Maximilian Schulz](http://max.jungeelite.de) (Ensuring compatibility with Bundler)
|
51
|
+
* [Edgars Beigarts](http://github.com/ebeigarts) (Adding intelligent description for tasks)
|
52
|
+
* [Alexander Simonov](http://simonov.me/) (Explicit table definition)
|
53
|
+
|
54
|
+
Copyright
|
55
|
+
---------
|
56
|
+
|
57
|
+
Copyright (c) 2010 Aaron Gibralter, and released under an MIT Licence.
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
Feature: Resque Delta Indexing
|
2
|
+
In order to have delta indexing on frequently-updated sites
|
3
|
+
Developers
|
4
|
+
Should be able to use Resque to handle delta indexes to lower system load
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given Sphinx is running
|
8
|
+
And I am searching on delayed betas
|
9
|
+
And I have data and it has been indexed
|
10
|
+
|
11
|
+
Scenario: Delta Index should not fire automatically
|
12
|
+
When I search for one
|
13
|
+
Then I should get 1 result
|
14
|
+
|
15
|
+
When I change the name of delayed beta one to eleven
|
16
|
+
And I wait for Sphinx to catch up
|
17
|
+
And I search for one
|
18
|
+
Then I should get 1 result
|
19
|
+
|
20
|
+
When I search for eleven
|
21
|
+
Then I should get 0 results
|
22
|
+
|
23
|
+
Scenario: Delta Index should fire when jobs are run
|
24
|
+
When I search for one
|
25
|
+
Then I should get 1 result
|
26
|
+
|
27
|
+
When I change the name of delayed beta two to twelve
|
28
|
+
And I wait for Sphinx to catch up
|
29
|
+
And I search for twelve
|
30
|
+
Then I should get 0 results
|
31
|
+
|
32
|
+
When I run the delayed jobs
|
33
|
+
And I wait for Sphinx to catch up
|
34
|
+
And I search for twelve
|
35
|
+
Then I should get 1 result
|
36
|
+
|
37
|
+
When I search for two
|
38
|
+
Then I should get 0 results
|
39
|
+
|
40
|
+
Scenario: ensuring that duplicate jobs are deleted
|
41
|
+
When I change the name of delayed beta two to fifty
|
42
|
+
And I change the name of delayed beta five to twelve
|
43
|
+
And I change the name of delayed beta one to fifteen
|
44
|
+
And I change the name of delayed beta six to twenty
|
45
|
+
And I run one delayed job
|
46
|
+
Then there should be no more DeltaJobs on the Resque queue
|
47
|
+
|
48
|
+
When I run the delayed jobs
|
49
|
+
And I wait for Sphinx to catch up
|
50
|
+
And I search for fifty
|
51
|
+
Then I should get 1 result
|
52
|
+
|
53
|
+
When I search for two
|
54
|
+
Then I should get 0 results
|
55
|
+
|
56
|
+
Scenario: canceling jobs
|
57
|
+
When I change the name of delayed beta two to fifty
|
58
|
+
And I cancel the jobs
|
59
|
+
And I run the delayed jobs
|
60
|
+
And I wait for Sphinx to catch up
|
61
|
+
And I search for fifty
|
62
|
+
Then I should get 0 results
|
@@ -0,0 +1,63 @@
|
|
1
|
+
Before do
|
2
|
+
$queries_executed = []
|
3
|
+
ThinkingSphinx::Deltas::ResqueDelta.cancel_thinking_sphinx_jobs
|
4
|
+
@model = nil
|
5
|
+
@method = :search
|
6
|
+
@query = ""
|
7
|
+
@conditions = {}
|
8
|
+
@with = {}
|
9
|
+
@without = {}
|
10
|
+
@with_all = {}
|
11
|
+
@options = {}
|
12
|
+
@results = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
Given "Sphinx is running" do
|
16
|
+
ThinkingSphinx::Configuration.instance.controller.should be_running
|
17
|
+
end
|
18
|
+
|
19
|
+
Given /^I am searching on (.+)$/ do |model|
|
20
|
+
@model = model.gsub(/\s/, '_').singularize.camelize.constantize
|
21
|
+
end
|
22
|
+
|
23
|
+
Given "I have data and it has been indexed" do
|
24
|
+
DelayedBeta.create(:name => "one")
|
25
|
+
DelayedBeta.create(:name => "two")
|
26
|
+
DelayedBeta.create(:name => "three")
|
27
|
+
DelayedBeta.create(:name => "four")
|
28
|
+
DelayedBeta.create(:name => "five")
|
29
|
+
DelayedBeta.create(:name => "six")
|
30
|
+
DelayedBeta.create(:name => "seven")
|
31
|
+
DelayedBeta.create(:name => "eight")
|
32
|
+
DelayedBeta.create(:name => "nine")
|
33
|
+
DelayedBeta.create(:name => "ten")
|
34
|
+
ThinkingSphinx::Deltas::ResqueDelta.cancel_thinking_sphinx_jobs
|
35
|
+
ThinkingSphinx::Configuration.instance.controller.index
|
36
|
+
sleep(1.5)
|
37
|
+
end
|
38
|
+
|
39
|
+
When "I wait for Sphinx to catch up" do
|
40
|
+
sleep(0.5)
|
41
|
+
end
|
42
|
+
|
43
|
+
When /^I search for (\w+)$/ do |query|
|
44
|
+
@results = nil
|
45
|
+
@query = query
|
46
|
+
end
|
47
|
+
|
48
|
+
Then /^I should get (\d+) results?$/ do |count|
|
49
|
+
results.length.should == count.to_i
|
50
|
+
end
|
51
|
+
|
52
|
+
def results
|
53
|
+
@results ||= (@model || ThinkingSphinx).send(
|
54
|
+
@method,
|
55
|
+
@query,
|
56
|
+
@options.merge(
|
57
|
+
:conditions => @conditions,
|
58
|
+
:with => @with,
|
59
|
+
:without => @without,
|
60
|
+
:with_all => @with_all
|
61
|
+
)
|
62
|
+
)
|
63
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
When /^I run the delayed jobs$/ do
|
2
|
+
unless @resque_worker
|
3
|
+
@resque_worker = Resque::Worker.new("ts_delta")
|
4
|
+
@resque_worker.register_worker
|
5
|
+
end
|
6
|
+
while job = @resque_worker.reserve
|
7
|
+
@resque_worker.perform(job)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
When /^I run one delayed job$/ do
|
12
|
+
unless @resque_worker
|
13
|
+
@resque_worker = Resque::Worker.new("ts_delta")
|
14
|
+
@resque_worker.register_worker
|
15
|
+
end
|
16
|
+
job = @resque_worker.reserve
|
17
|
+
@resque_worker.perform(job)
|
18
|
+
end
|
19
|
+
|
20
|
+
When /^I cancel the jobs$/ do
|
21
|
+
ThinkingSphinx::Deltas::ResqueDelta.cancel_thinking_sphinx_jobs
|
22
|
+
end
|
23
|
+
|
24
|
+
When /^I change the name of delayed beta (\w+) to (\w+)$/ do |current, replacement|
|
25
|
+
DelayedBeta.find_by_name(current).update_attributes(:name => replacement)
|
26
|
+
end
|
27
|
+
|
28
|
+
Then /^there should be no more DeltaJobs on the Resque queue$/ do
|
29
|
+
job_classes = Resque.redis.lrange("queue:ts_delta", 0, -1).collect do |j|
|
30
|
+
Resque.decode(j)["class"]
|
31
|
+
end
|
32
|
+
job_classes.should_not include("ThinkingSphinx::Deltas::ResqueDelta::DeltaJob")
|
33
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'cucumber'
|
3
|
+
require 'spec/expectations'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'active_record'
|
6
|
+
|
7
|
+
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
8
|
+
|
9
|
+
$:.unshift(File.join(PROJECT_ROOT, 'lib'))
|
10
|
+
$:.unshift(File.dirname(__FILE__))
|
11
|
+
|
12
|
+
require 'cucumber/thinking_sphinx/internal_world'
|
13
|
+
|
14
|
+
Time.zone_default = Time.__send__(:get_zone, 'Melbourne')
|
15
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
16
|
+
ActiveRecord::Base.default_timezone = :utc
|
17
|
+
|
18
|
+
world = Cucumber::ThinkingSphinx::InternalWorld.new
|
19
|
+
world.configure_database
|
20
|
+
|
21
|
+
require 'thinking_sphinx'
|
22
|
+
require 'thinking_sphinx/deltas/resque_delta'
|
23
|
+
|
24
|
+
world.setup
|
25
|
+
|
26
|
+
require 'redis_test_setup'
|
27
|
+
RedisTestSetup.start_redis!(PROJECT_ROOT, :cucumber)
|
28
|
+
Resque.redis = '127.0.0.1:6398'
|
29
|
+
Before do
|
30
|
+
Resque.redis.flushall
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'database_cleaner'
|
34
|
+
require 'database_cleaner/cucumber'
|
35
|
+
DatabaseCleaner.strategy = :truncation
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RedisTestSetup
|
2
|
+
|
3
|
+
def self.start_redis!(rails_root, env)
|
4
|
+
dir_temp = File.expand_path(File.join(rails_root, 'tmp'))
|
5
|
+
dir_conf = File.expand_path(File.join(rails_root, 'config'))
|
6
|
+
cwd = Dir.getwd
|
7
|
+
Dir.chdir(rails_root)
|
8
|
+
self.cleanup(dir_temp, env)
|
9
|
+
raise "unable to launch redis-server" unless system("redis-server #{dir_conf}/redis-#{env}.conf")
|
10
|
+
Dir.chdir(cwd)
|
11
|
+
Kernel.at_exit do
|
12
|
+
if (pid = `cat #{dir_temp}/redis-#{env}.pid`.strip) =~ /^\d+$/
|
13
|
+
self.cleanup(dir_temp, env)
|
14
|
+
Process.kill("KILL", pid.to_i)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.cleanup(dir_temp, env)
|
20
|
+
`rm -f #{dir_temp}/redis-#{env}-dump.rdb`
|
21
|
+
`rm -f #{dir_temp}/redis-#{env}.pid`
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
ActiveRecord::Base.connection.create_table :delayed_betas, :force => true do |t|
|
2
|
+
t.column :name, :string, :null => false
|
3
|
+
t.column :delta, :boolean, :null => false, :default => false
|
4
|
+
end
|
5
|
+
|
6
|
+
ActiveRecord::Base.connection.create_table :delayed_jobs, :force => true do |t|
|
7
|
+
t.column :priority, :integer, :default => 0
|
8
|
+
t.column :attempts, :integer, :default => 0
|
9
|
+
t.column :handler, :text
|
10
|
+
t.column :last_error, :string
|
11
|
+
t.column :run_at, :datetime
|
12
|
+
t.column :locked_at, :datetime
|
13
|
+
t.column :failed_at, :datetime
|
14
|
+
t.column :locked_by, :string
|
15
|
+
t.column :created_at, :datetime
|
16
|
+
t.column :updated_at, :datetime
|
17
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'resque'
|
2
|
+
require 'thinking_sphinx'
|
3
|
+
|
4
|
+
# Delayed Deltas for Thinking Sphinx, using Resque.
|
5
|
+
#
|
6
|
+
# This documentation is aimed at those reading the code. If you're looking for
|
7
|
+
# a guide to Thinking Sphinx and/or deltas, I recommend you start with the
|
8
|
+
# Thinking Sphinx site instead - or the README for this library at the very
|
9
|
+
# least.
|
10
|
+
#
|
11
|
+
# @author Patrick Allan
|
12
|
+
# @see http://ts.freelancing-gods.com Thinking Sphinx
|
13
|
+
#
|
14
|
+
class ThinkingSphinx::Deltas::ResqueDelta < ThinkingSphinx::Deltas::DefaultDelta
|
15
|
+
|
16
|
+
# LTRIM + LPOP deletes all items from the Resque queue without loading it
|
17
|
+
# into client memory (unlike Resque.dequeue).
|
18
|
+
def self.cancel_thinking_sphinx_jobs
|
19
|
+
[
|
20
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob,
|
21
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob
|
22
|
+
].collect { |c| c.instance_variable_get(:@queue) }.uniq.each do |q|
|
23
|
+
Resque.redis.ltrim("queue:#{q}", 0, 0)
|
24
|
+
Resque.redis.lpop("queue:#{q}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Adds a job to the queue for processing the given model's delta index. A job
|
29
|
+
# for hiding the instance in the core index is also created, if an instance is
|
30
|
+
# provided.
|
31
|
+
#
|
32
|
+
# Neither job will be queued if updates or deltas are disabled, or if the
|
33
|
+
# instance (when given) is not toggled to be in the delta index. The first two
|
34
|
+
# options are controlled via ThinkingSphinx.updates_enabled? and
|
35
|
+
# ThinkingSphinx.deltas_enabled?.
|
36
|
+
#
|
37
|
+
# @param [Class] model the ActiveRecord model to index.
|
38
|
+
# @param [ActiveRecord::Base] instance the instance of the given model that
|
39
|
+
# has changed. Optional.
|
40
|
+
# @return [Boolean] true
|
41
|
+
#
|
42
|
+
def index(model, instance = nil)
|
43
|
+
return true if skip?(instance)
|
44
|
+
Resque.enqueue(
|
45
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob,
|
46
|
+
model.delta_index_names
|
47
|
+
)
|
48
|
+
if instance
|
49
|
+
Resque.enqueue(
|
50
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob,
|
51
|
+
model.core_index_names,
|
52
|
+
instance.sphinx_document_id
|
53
|
+
)
|
54
|
+
end
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Checks whether jobs should be enqueued. Only true if updates and deltas are
|
61
|
+
# enabled, and the instance (if there is one) is toggled.
|
62
|
+
#
|
63
|
+
# @param [ActiveRecord::Base, NilClass] instance
|
64
|
+
# @return [Boolean]
|
65
|
+
#
|
66
|
+
def skip?(instance)
|
67
|
+
!ThinkingSphinx.updates_enabled? ||
|
68
|
+
!ThinkingSphinx.deltas_enabled? ||
|
69
|
+
(instance && !toggled(instance))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
require 'thinking_sphinx/deltas/resque_delta/delta_job'
|
74
|
+
require 'thinking_sphinx/deltas/resque_delta/flag_as_deleted_job'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'resque-lock-timeout'
|
2
|
+
|
3
|
+
# A simple job class that processes a given index.
|
4
|
+
#
|
5
|
+
class ThinkingSphinx::Deltas::ResqueDelta::DeltaJob
|
6
|
+
|
7
|
+
extend Resque::Plugins::LockTimeout
|
8
|
+
@queue = :ts_delta
|
9
|
+
@lock_timeout = 240
|
10
|
+
|
11
|
+
# Runs Sphinx's indexer tool to process the index. Currently assumes Sphinx
|
12
|
+
# is running.
|
13
|
+
#
|
14
|
+
# @param [String] index the name of the Sphinx index
|
15
|
+
#
|
16
|
+
def self.perform(indexes)
|
17
|
+
config = ThinkingSphinx::Configuration.instance
|
18
|
+
output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} --rotate #{indexes.join(' ')}`
|
19
|
+
puts output unless ThinkingSphinx.suppress_delta_output?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Try again later if lock is in use.
|
23
|
+
def self.lock_failed(*args)
|
24
|
+
Resque.enqueue(self, *args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Run only one DeltaJob at a time regardless of indexes.
|
28
|
+
def self.identifier(*args)
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# This allows us to have a concurrency safe version of ts-delayed-delta's
|
33
|
+
# duplicates_exist:
|
34
|
+
#
|
35
|
+
# http://github.com/freelancing-god/ts-delayed-delta/blob/master/lib/thinkin
|
36
|
+
# g_sphinx/deltas/delayed_delta/job.rb#L47
|
37
|
+
#
|
38
|
+
# The name of this method ensures that it runs within around_perform_lock.
|
39
|
+
#
|
40
|
+
# We've leveraged resque-lock-timeout to ensure that only one DeltaJob is
|
41
|
+
# running at a time. Now, this around filter essentially ensures that only
|
42
|
+
# one DeltaJob of each index type can sit at the queue at once. If the queue
|
43
|
+
# has more than one, lrem will clear the rest off.
|
44
|
+
#
|
45
|
+
def self.around_perform_lock1(*args)
|
46
|
+
# Remove all other instances of this job (with the same args) from the
|
47
|
+
# queue. Uses LREM (http://code.google.com/p/redis/wiki/LremCommand) which
|
48
|
+
# takes the form: "LREM key count value" and if count == 0 removes all
|
49
|
+
# instances of value from the list.
|
50
|
+
redis_job_value = Resque.encode(:class => self.to_s, :args => args)
|
51
|
+
Resque.redis.lrem("queue:#{@queue}", 0, redis_job_value)
|
52
|
+
yield
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# A simple job for flagging a specified Sphinx document in a given index as
|
2
|
+
# 'deleted'.
|
3
|
+
#
|
4
|
+
class ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob
|
5
|
+
|
6
|
+
@queue = :ts_delta
|
7
|
+
|
8
|
+
# Takes an index name and document id. Please note that the document id is
|
9
|
+
# Sphinx's unique identifier, and will almost certainly not be the model
|
10
|
+
# instance's primary key value. Updates the sphinx_deleted attribute for the
|
11
|
+
# given document, setting the value to 1 (true). This is not a special
|
12
|
+
# attribute in Sphinx, but is used by Thinking Sphinx to ignore deleted
|
13
|
+
# values between full re-indexing. It's particularly useful in this
|
14
|
+
# situation to avoid old values in the core index and just use the new
|
15
|
+
# values in the delta index as a reference point.
|
16
|
+
#
|
17
|
+
# @param [Array] indexes An array of index names
|
18
|
+
# @param [Integer] document_id The document id
|
19
|
+
#
|
20
|
+
# @return [Boolean] true
|
21
|
+
#
|
22
|
+
def self.perform(indexes, document_id)
|
23
|
+
config = ThinkingSphinx::Configuration.instance
|
24
|
+
indexes.each do |index|
|
25
|
+
if ThinkingSphinx.sphinx_running? && ThinkingSphinx.search_for_id(document_id, index)
|
26
|
+
config.client.update(index, ['sphinx_deleted'], {document_id => [1]})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
namespace :thinking_sphinx do
|
2
|
+
task :index do
|
3
|
+
ThinkingSphinx::Deltas::ResqueDelta.cancel_thinking_sphinx_jobs
|
4
|
+
end
|
5
|
+
|
6
|
+
desc "Process stored delta index requests"
|
7
|
+
task :resque_delta => :app_env do
|
8
|
+
raise "TODO... for now, please just run the workers on your own and make sure to work the :ts_delta queue."
|
9
|
+
# require 'delayed/worker'
|
10
|
+
# require 'thinking_sphinx/deltas/resque_delta'
|
11
|
+
#
|
12
|
+
# Delayed::Worker.new(
|
13
|
+
# :min_priority => ENV['MIN_PRIORITY'],
|
14
|
+
# :max_priority => ENV['MAX_PRIORITY']
|
15
|
+
# ).start
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
namespace :ts do
|
20
|
+
desc "Process stored delta index requests"
|
21
|
+
task :rd => "thinking_sphinx:resque_delta"
|
22
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Deltas::ResqueDelta::DeltaJob do
|
4
|
+
describe '.perform' do
|
5
|
+
before :each do
|
6
|
+
ThinkingSphinx.suppress_delta_output = false
|
7
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.stub(:` => true)
|
8
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.stub(:puts => nil)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should output the delta indexing by default" do
|
12
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.should_receive(:puts)
|
13
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.perform(['foo_core'])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should not output the delta indexing if requested" do
|
17
|
+
ThinkingSphinx.suppress_delta_output = true
|
18
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.should_not_receive(:puts)
|
19
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.perform(['foo_core'])
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should process just the requested indexes" do
|
23
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.should_receive(:`) do |command|
|
24
|
+
command.should match(/foo_core/)
|
25
|
+
command.should_not match(/--all/)
|
26
|
+
end
|
27
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.perform(['foo_core'])
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'multiple indexes' do
|
31
|
+
it "should process all requested indexes" do
|
32
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.should_receive(:`) do |command|
|
33
|
+
command.should match(/foo_core bar_core/)
|
34
|
+
end
|
35
|
+
ThinkingSphinx::Deltas::ResqueDelta::DeltaJob.perform(['foo_core', 'bar_core'])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob do
|
4
|
+
describe '.perform' do
|
5
|
+
before :each do
|
6
|
+
ThinkingSphinx.updates_enabled = true
|
7
|
+
@client = stub('client', :update => true)
|
8
|
+
ThinkingSphinx::Configuration.instance.stub!(:client => @client)
|
9
|
+
ThinkingSphinx.stub!(:search_for_id => true)
|
10
|
+
ThinkingSphinx.stub!(:sphinx_running? => true)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should not update if Sphinx isn't running" do
|
14
|
+
ThinkingSphinx.stub!(:sphinx_running? => false)
|
15
|
+
@client.should_not_receive(:update)
|
16
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core'], 12)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should not update if the document isn't in the index" do
|
20
|
+
ThinkingSphinx.stub!(:search_for_id => false)
|
21
|
+
@client.should_not_receive(:update)
|
22
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core'], 12)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should update the specified index" do
|
26
|
+
@client.should_receive(:update) do |index, attributes, values|
|
27
|
+
index.should == 'foo_core'
|
28
|
+
end
|
29
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core'], 12)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should update all specified indexes" do
|
33
|
+
@client.should_receive(:update).with('foo_core', anything, anything)
|
34
|
+
@client.should_receive(:update).with('bar_core', anything, anything)
|
35
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core', 'bar_core'], 12)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should update the sphinx_deleted attribute" do
|
39
|
+
@client.should_receive(:update) do |index, attributes, values|
|
40
|
+
attributes.should == ['sphinx_deleted']
|
41
|
+
end
|
42
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core'], 12)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should set sphinx_deleted for the given document to true" do
|
46
|
+
@client.should_receive(:update) do |index, attributes, values|
|
47
|
+
values[12].should == [1]
|
48
|
+
end
|
49
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core'], 12)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should check for the existence of the document in the specified index" do
|
53
|
+
ThinkingSphinx.should_receive(:search_for_id) do |id, index|
|
54
|
+
index.should == 'foo_core'
|
55
|
+
end
|
56
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core'], 12)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should check for the existence of the given document id" do
|
60
|
+
ThinkingSphinx.should_receive(:search_for_id) do |id, index|
|
61
|
+
id.should == 12
|
62
|
+
end
|
63
|
+
ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob.perform(['foo_core'], 12)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Deltas::ResqueDelta do
|
4
|
+
describe '#index' do
|
5
|
+
before :each do
|
6
|
+
ThinkingSphinx.updates_enabled = true
|
7
|
+
ThinkingSphinx.deltas_enabled = true
|
8
|
+
|
9
|
+
Resque.stub!(:enqueue => true)
|
10
|
+
|
11
|
+
@delayed_delta = ThinkingSphinx::Deltas::ResqueDelta.new(
|
12
|
+
stub('instance'), {}
|
13
|
+
)
|
14
|
+
@delayed_delta.stub!(:toggled => true)
|
15
|
+
|
16
|
+
@model = stub('foo')
|
17
|
+
@model.stub!(:name => 'foo')
|
18
|
+
@model.stub!(:source_of_sphinx_index => @model)
|
19
|
+
@model.stub!(:core_index_names => ['foo_core'])
|
20
|
+
@model.stub!(:delta_index_names => ['foo_delta'])
|
21
|
+
|
22
|
+
@instance = stub('instance')
|
23
|
+
@instance.stub!(:sphinx_document_id => 42)
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'updates disabled' do
|
27
|
+
before :each do
|
28
|
+
ThinkingSphinx.updates_enabled = false
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not enqueue a delta job" do
|
32
|
+
Resque.should_not_receive(:enqueue)
|
33
|
+
@delayed_delta.index(@model)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not enqueue a flag as deleted job" do
|
37
|
+
Resque.should_not_receive(:enqueue)
|
38
|
+
@delayed_delta.index(@model)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'deltas disabled' do
|
43
|
+
before :each do
|
44
|
+
ThinkingSphinx.deltas_enabled = false
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should not enqueue a delta job" do
|
48
|
+
Resque.should_not_receive(:enqueue)
|
49
|
+
@delayed_delta.index(@model)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should not enqueue a flag as deleted job" do
|
53
|
+
Resque.should_not_receive(:enqueue)
|
54
|
+
@delayed_delta.index(@model)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "instance isn't toggled" do
|
59
|
+
before :each do
|
60
|
+
@delayed_delta.stub!(:toggled => false)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not enqueue a delta job" do
|
64
|
+
Resque.should_not_receive(:enqueue)
|
65
|
+
@delayed_delta.index(@model, @instance)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should not enqueue a flag as deleted job" do
|
69
|
+
Resque.should_not_receive(:enqueue)
|
70
|
+
@delayed_delta.index(@model, @instance)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should enqueue a delta job for the appropriate indexes" do
|
75
|
+
Resque.should_receive(:enqueue).with(ThinkingSphinx::Deltas::ResqueDelta::DeltaJob, ['foo_delta']).once
|
76
|
+
@delayed_delta.index(@model)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should enqueue a flag-as-deleted job for the appropriate indexes" do
|
80
|
+
# WTF RSpec: http://gist.github.com/447611
|
81
|
+
# Resque.should_receive(:enqueue).with(ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob, ['foo_core'], an_instance_of(Numeric))
|
82
|
+
Resque.should_receive(:enqueue).twice
|
83
|
+
@delayed_delta.index(@model, @instance)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should enqueue a flag-as-deleted job for the appropriate id" do
|
87
|
+
# WTF RSpec: http://gist.github.com/447611
|
88
|
+
# Resque.should_receive(:enqueue).with(ThinkingSphinx::Deltas::ResqueDelta::FlagAsDeletedJob, an_instance_of(Array), 42)
|
89
|
+
Resque.should_receive(:enqueue).twice
|
90
|
+
@delayed_delta.index(@model, @instance)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "jeweler"
|
2
|
+
require "yard"
|
3
|
+
|
4
|
+
YARD::Rake::YardocTask.new
|
5
|
+
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ts-resque-delta"
|
8
|
+
gem.summary = "Thinking Sphinx - Resque Deltas"
|
9
|
+
gem.description = "Manage delta indexes via Resque for Thinking Sphinx"
|
10
|
+
gem.email = "aaron.gibralter@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/agibralter/ts-resque-delta"
|
12
|
+
gem.authors = ["Aaron Gibralter"]
|
13
|
+
gem.add_dependency("thinking-sphinx", ">= 1.3.6")
|
14
|
+
gem.add_dependency("resque", ">= 1.9.0")
|
15
|
+
gem.add_development_dependency("rspec", ">= 1.2.9")
|
16
|
+
gem.add_development_dependency("yard", ">= 0")
|
17
|
+
gem.add_development_dependency("cucumber", ">= 0")
|
18
|
+
gem.add_development_dependency("database_cleaner", ">= 0.5.2")
|
19
|
+
gem.files = FileList[
|
20
|
+
"lib/**/*.rb",
|
21
|
+
"LICENSE",
|
22
|
+
"README.markdown"
|
23
|
+
]
|
24
|
+
gem.test_files = FileList[
|
25
|
+
["Rakefile"] + %w(config features spec tasks).collect { |d| "#{d}/**/*" }
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
Jeweler::GemcutterTasks.new
|
data/tasks/rails.rake
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../lib/thinking_sphinx/deltas/delayed_delta/tasks')
|
data/tasks/testing.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec/rake/spectask'
|
2
|
+
require 'cucumber/rake/task'
|
3
|
+
|
4
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
5
|
+
spec.libs << 'lib' << 'spec'
|
6
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
7
|
+
end
|
8
|
+
|
9
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
10
|
+
spec.libs << 'lib' << 'spec'
|
11
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
12
|
+
spec.rcov = true
|
13
|
+
end
|
14
|
+
|
15
|
+
Cucumber::Rake::Task.new do |task|
|
16
|
+
task.cucumber_opts = '--exclude features/thinking_sphinx'
|
17
|
+
end
|
18
|
+
|
19
|
+
task :spec => :check_dependencies
|
20
|
+
task :cucumber => :check_dependencies
|
metadata
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ts-resque-delta
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Aaron Gibralter
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-06-23 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: thinking-sphinx
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 3
|
33
|
+
- 6
|
34
|
+
version: 1.3.6
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: resque
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 51
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 9
|
49
|
+
- 0
|
50
|
+
version: 1.9.0
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rspec
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 13
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 2
|
65
|
+
- 9
|
66
|
+
version: 1.2.9
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
type: :development
|
82
|
+
version_requirements: *id004
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: cucumber
|
85
|
+
prerelease: false
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
type: :development
|
96
|
+
version_requirements: *id005
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: database_cleaner
|
99
|
+
prerelease: false
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 15
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
- 5
|
109
|
+
- 2
|
110
|
+
version: 0.5.2
|
111
|
+
type: :development
|
112
|
+
version_requirements: *id006
|
113
|
+
description: Manage delta indexes via Resque for Thinking Sphinx
|
114
|
+
email: aaron.gibralter@gmail.com
|
115
|
+
executables: []
|
116
|
+
|
117
|
+
extensions: []
|
118
|
+
|
119
|
+
extra_rdoc_files:
|
120
|
+
- LICENSE
|
121
|
+
- README.markdown
|
122
|
+
files:
|
123
|
+
- LICENSE
|
124
|
+
- README.markdown
|
125
|
+
- lib/thinking_sphinx/deltas/resque_delta.rb
|
126
|
+
- lib/thinking_sphinx/deltas/resque_delta/delta_job.rb
|
127
|
+
- lib/thinking_sphinx/deltas/resque_delta/flag_as_deleted_job.rb
|
128
|
+
- lib/thinking_sphinx/deltas/resque_delta/tasks.rb
|
129
|
+
- Rakefile
|
130
|
+
- config/redis-cucumber.conf
|
131
|
+
- features/resque_deltas.feature
|
132
|
+
- features/step_definitions/common_steps.rb
|
133
|
+
- features/step_definitions/resque_delta_steps.rb
|
134
|
+
- features/support/env.rb
|
135
|
+
- features/support/redis_test_setup.rb
|
136
|
+
- features/thinking_sphinx/database.example.yml
|
137
|
+
- features/thinking_sphinx/database.yml
|
138
|
+
- features/thinking_sphinx/db/migrations/create_delayed_betas.rb
|
139
|
+
- features/thinking_sphinx/models/delayed_beta.rb
|
140
|
+
- spec/spec.opts
|
141
|
+
- spec/spec_helper.rb
|
142
|
+
- spec/thinking_sphinx/deltas/resque_delta/delta_job_spec.rb
|
143
|
+
- spec/thinking_sphinx/deltas/resque_delta/flag_as_deleted_job_spec.rb
|
144
|
+
- spec/thinking_sphinx/deltas/resque_delta_spec.rb
|
145
|
+
- tasks/distribution.rb
|
146
|
+
- tasks/rails.rake
|
147
|
+
- tasks/testing.rb
|
148
|
+
has_rdoc: true
|
149
|
+
homepage: http://github.com/agibralter/ts-resque-delta
|
150
|
+
licenses: []
|
151
|
+
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options:
|
154
|
+
- --charset=UTF-8
|
155
|
+
require_paths:
|
156
|
+
- lib
|
157
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
none: false
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
hash: 3
|
163
|
+
segments:
|
164
|
+
- 0
|
165
|
+
version: "0"
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
none: false
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
hash: 3
|
172
|
+
segments:
|
173
|
+
- 0
|
174
|
+
version: "0"
|
175
|
+
requirements: []
|
176
|
+
|
177
|
+
rubyforge_project:
|
178
|
+
rubygems_version: 1.3.7
|
179
|
+
signing_key:
|
180
|
+
specification_version: 3
|
181
|
+
summary: Thinking Sphinx - Resque Deltas
|
182
|
+
test_files:
|
183
|
+
- Rakefile
|
184
|
+
- config/redis-cucumber.conf
|
185
|
+
- features/resque_deltas.feature
|
186
|
+
- features/step_definitions/common_steps.rb
|
187
|
+
- features/step_definitions/resque_delta_steps.rb
|
188
|
+
- features/support/env.rb
|
189
|
+
- features/support/redis_test_setup.rb
|
190
|
+
- features/thinking_sphinx/database.example.yml
|
191
|
+
- features/thinking_sphinx/database.yml
|
192
|
+
- features/thinking_sphinx/db/migrations/create_delayed_betas.rb
|
193
|
+
- features/thinking_sphinx/models/delayed_beta.rb
|
194
|
+
- spec/spec.opts
|
195
|
+
- spec/spec_helper.rb
|
196
|
+
- spec/thinking_sphinx/deltas/resque_delta/delta_job_spec.rb
|
197
|
+
- spec/thinking_sphinx/deltas/resque_delta/flag_as_deleted_job_spec.rb
|
198
|
+
- spec/thinking_sphinx/deltas/resque_delta_spec.rb
|
199
|
+
- tasks/distribution.rb
|
200
|
+
- tasks/rails.rake
|
201
|
+
- tasks/testing.rb
|