ts-delayed-delta 1.1.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +14 -12
- data/Appraisals +11 -0
- data/Gemfile +1 -3
- data/LICENSE +1 -1
- data/README.textile +29 -26
- data/Rakefile +3 -16
- data/gemfiles/binary.gemfile +7 -0
- data/gemfiles/sphinxql.gemfile +7 -0
- data/lib/thinking_sphinx/deltas/delayed_delta.rb +117 -47
- data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +7 -16
- data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +8 -19
- data/lib/ts-delayed-delta.rb +0 -3
- data/spec/acceptance/delayed_job_deltas_spec.rb +46 -0
- data/spec/acceptance/spec_helper.rb +4 -0
- data/spec/acceptance/support/database_cleaner.rb +11 -0
- data/spec/acceptance/support/sphinx_controller.rb +61 -0
- data/spec/acceptance/support/sphinx_helpers.rb +31 -0
- data/spec/internal/.gitignore +2 -0
- data/spec/internal/app/indices/book_index.rb +3 -0
- data/spec/internal/app/models/book.rb +7 -0
- data/spec/internal/config/database.yml +5 -0
- data/spec/internal/db/schema.rb +24 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/spec_helper.rb +9 -7
- data/ts-delayed-delta.gemspec +15 -11
- metadata +129 -86
- data/VERSION +0 -1
- data/features/delayed_deltas.feature +0 -37
- data/features/step_definitions/common_steps.rb +0 -48
- data/features/step_definitions/delayed_delta_steps.rb +0 -11
- data/features/support/env.rb +0 -33
- data/features/thinking_sphinx/database.example.yml +0 -3
- data/features/thinking_sphinx/db/fixtures/delayed_betas.rb +0 -10
- data/features/thinking_sphinx/db/migrations/create_delayed_betas.rb +0 -17
- data/features/thinking_sphinx/models/delayed_beta.rb +0 -7
- data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +0 -65
- data/lib/thinking_sphinx/deltas/delayed_delta/railtie.rb +0 -5
- data/lib/thinking_sphinx/deltas/delayed_delta/tasks.rb +0 -23
- data/lib/thinking_sphinx/deltas/delayed_delta/version.rb +0 -5
- data/spec/thinking_sphinx/deltas/delayed_delta/delta_job_spec.rb +0 -53
- data/spec/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job_spec.rb +0 -78
- data/spec/thinking_sphinx/deltas/delayed_delta/job_spec.rb +0 -52
- data/spec/thinking_sphinx/deltas/delayed_delta_spec.rb +0 -128
- data/tasks/rails.rake +0 -1
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
+
language: ruby
|
1
2
|
rvm:
|
2
|
-
# - 1.8.6
|
3
|
-
- 1.8.7
|
4
3
|
- 1.9.2
|
5
4
|
- 1.9.3
|
6
|
-
|
7
|
-
-
|
8
|
-
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# - SPHINX_BIN=/usr/local/sphinx-0.9.9/bin SPHINX_VERSION=0.9.9
|
13
|
-
# - SPHINX_BIN=/usr/local/sphinx-1.10/bin SPHINX_VERSION=1.10
|
14
|
-
# - SPHINX_BIN=/usr/local/sphinx-2.0.1/bin SPHINX_VERSION=2.0.1
|
5
|
+
before_install:
|
6
|
+
- gem update --system
|
7
|
+
- gem install bundler --no-ri --no-rdoc
|
8
|
+
- curl -O http://fs-packages.s3.amazonaws.com/fs-sphinx-2.0.6_x86_64_12.04.deb
|
9
|
+
- sudo dpkg -i fs-sphinx-2.0.6_x86_64_12.04.deb
|
10
|
+
- bundle install
|
15
11
|
before_script:
|
16
|
-
- "mysql -e 'create database thinking_sphinx;' > /dev/null"
|
12
|
+
- "mysql -e 'create database thinking_sphinx;' > /dev/null"
|
13
|
+
- "psql -c 'create database thinking_sphinx;' -U postgres > /dev/null"
|
14
|
+
- "bundle exec rake appraisal:install"
|
15
|
+
env:
|
16
|
+
- SPHINX_BIN=/usr/local/sphinx-2.0.6/bin/ SPHINX_VERSION=2.0.6 DATABASE=mysql2
|
17
|
+
- SPHINX_BIN=/usr/local/sphinx-2.0.6/bin/ SPHINX_VERSION=2.0.6 DATABASE=postgresql
|
18
|
+
script: "bundle exec rake appraisal spec"
|
data/Appraisals
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
appraise "binary" do
|
2
|
+
gem 'thinking-sphinx',
|
3
|
+
:git => 'git://github.com/pat/thinking-sphinx.git',
|
4
|
+
:ref => '94851c0e6b'
|
5
|
+
end
|
6
|
+
|
7
|
+
appraise "sphinxql" do
|
8
|
+
gem 'thinking-sphinx',
|
9
|
+
:git => 'git://github.com/pat/thinking-sphinx.git',
|
10
|
+
:ref => '86ac3edfbe'
|
11
|
+
end
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.textile
CHANGED
@@ -2,48 +2,49 @@ h1. Delayed Deltas for Thinking Sphinx
|
|
2
2
|
|
3
3
|
h2. Installation
|
4
4
|
|
5
|
-
|
5
|
+
This version requires Thinking Sphinx 3.x (currently the edge branch) and Delayed Job 3.x.
|
6
6
|
|
7
|
-
|
7
|
+
In your @Gemfile@, it'll likely look something like this:
|
8
8
|
|
9
|
-
|
9
|
+
<pre><code>gem 'ts-delayed-delta', '~> 2.0.0'</code></pre>
|
10
10
|
|
11
|
-
|
12
|
-
:lib => 'thinking_sphinx/deltas/delayed_delta',
|
13
|
-
:version => '>= 1.0.0',
|
14
|
-
:source => 'http://gemcutter.org'</code></pre>
|
11
|
+
Or, if you're referring directly to the git repository:
|
15
12
|
|
16
|
-
|
13
|
+
<pre><code>gem 'ts-delayed-delta',
|
14
|
+
:git => 'git://github.com/pat/ts-delayed-delta.git',
|
15
|
+
:branch => 'edge',
|
16
|
+
:ref => 'use-latest-commit-here'</code></pre>
|
17
17
|
|
18
|
-
|
18
|
+
And given this gem's built for Delayed Job, we're presuming you've got that set up (with the database table), and you know how to run it. This gem no longer provides a custom task for that purpose - there's no need.
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
<pre><code>script/generate delayed_job</code></pre>
|
20
|
+
h2. Usage
|
23
21
|
|
24
|
-
|
22
|
+
In your index definitions, make sure you set the @:delta@ setting to @ThinkingSphinx::Deltas::DelayedDelta@:
|
25
23
|
|
26
|
-
<pre><code>
|
24
|
+
<pre><code>ThinkingSphinx::Index.define :book, :with => :active_record, :delta => ThinkingSphinx::Deltas::DelayedDelta do
|
27
25
|
# ...
|
28
|
-
|
29
|
-
set_property :delta => :delayed
|
30
26
|
end</code></pre>
|
31
27
|
|
32
|
-
If you've never used delta indices before, you'll want to add the boolean column named delta to each model that is using the approach.
|
28
|
+
If you've never used delta indices before, you'll want to add the boolean column named delta to each model that is using the approach. It probably doesn't hurt to add an index to that column as well.
|
33
29
|
|
34
|
-
<pre><code>
|
35
|
-
|
36
|
-
end</code></pre>
|
30
|
+
<pre><code>add_column :books, :delta, :boolean, :default => true, :null => false
|
31
|
+
add_index :books, :delta</code></pre>
|
37
32
|
|
38
|
-
|
33
|
+
And that's pretty much it. Make sure Delayed Job is running, and it'll take care of the jobs to keep your Sphinx indices up to date.
|
34
|
+
|
35
|
+
Please keep in mind that you need to run the Delayed Job workers on the same machine as Sphinx, as direct access to Sphinx files (and the Sphinx command-line tools) is essential.
|
36
|
+
|
37
|
+
h2. Limitations
|
39
38
|
|
40
|
-
|
39
|
+
This version of the gem is built for Ruby 1.9 and Rails 3.1 or newer, just like Thinking Sphinx 3.
|
41
40
|
|
42
|
-
|
41
|
+
h2. Contributing
|
43
42
|
|
44
|
-
|
43
|
+
Contributions are very much welcome - but keep in mind the following:
|
45
44
|
|
46
|
-
|
45
|
+
* Keep patches in a separate branch
|
46
|
+
* Don't mess with the version number. I'll take care of that when the patch is merged in.
|
47
|
+
* Please write tests - currently, there's only acceptance tests in place, because the underlying code is simple enough. If you get stuck into anything complex, unit tests are a smart move.
|
47
48
|
|
48
49
|
h2. Contributors
|
49
50
|
|
@@ -56,7 +57,9 @@ h2. Contributors
|
|
56
57
|
* "Reinier de Lange":http://www.nedforce.nl/ (Fix for table name reference)
|
57
58
|
* "Enrico Brunetta":http://github.com/enrico (Adding Railtie for Rails 3)
|
58
59
|
* "Jonathan Viney":https://github.com/jviney and "James Healy":http://yob.id.au/ (Rails 3.2 deprecation fixes)
|
60
|
+
* "Georg Ledermann":http://www.georg-ledermann.de (DJ 2.0.x backwards compatibility)
|
61
|
+
* "Jonathan Lim":http://snowblink.co.uk (Cleaning up version references)
|
59
62
|
|
60
63
|
h2. Copyright
|
61
64
|
|
62
|
-
Copyright (c) 2009-
|
65
|
+
Copyright (c) 2009-2012, Thinking Sphinx Delayed Deltas (ts-delayed-delta) is developed and maintained by Pat Allan, and is released under the open MIT Licence. Many thanks to "all who have contributed patches":https://github.com/pat/ts-delayed-delta/contributors.
|
data/Rakefile
CHANGED
@@ -1,23 +1,10 @@
|
|
1
|
-
require '
|
2
|
-
require 'bundler'
|
1
|
+
require 'bundler/setup'
|
3
2
|
|
4
3
|
Bundler::GemHelper.install_tasks
|
5
|
-
Bundler.require :default, :development
|
6
4
|
|
5
|
+
require 'appraisal'
|
7
6
|
require 'rspec/core/rake_task'
|
8
|
-
require 'cucumber/rake/task'
|
9
7
|
|
10
8
|
RSpec::Core::RakeTask.new
|
11
9
|
|
12
|
-
|
13
|
-
spec.rcov_opts = ['--exclude', 'spec', '--exclude', 'gems']
|
14
|
-
spec.rcov = true
|
15
|
-
end
|
16
|
-
|
17
|
-
Cucumber::Rake::Task.new do |task|
|
18
|
-
task.cucumber_opts = '--exclude features/thinking_sphinx'
|
19
|
-
end
|
20
|
-
|
21
|
-
YARD::Rake::YardocTask.new
|
22
|
-
|
23
|
-
task :default => [:spec, :cucumber]
|
10
|
+
task :default => :spec
|
@@ -1,10 +1,5 @@
|
|
1
1
|
require 'delayed_job'
|
2
|
-
|
3
2
|
require 'thinking_sphinx'
|
4
|
-
require 'thinking_sphinx/deltas/delayed_delta/delta_job'
|
5
|
-
require 'thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job'
|
6
|
-
require 'thinking_sphinx/deltas/delayed_delta/job'
|
7
|
-
require 'thinking_sphinx/deltas/delayed_delta/version'
|
8
3
|
|
9
4
|
# Delayed Deltas for Thinking Sphinx, using Delayed Job.
|
10
5
|
#
|
@@ -16,52 +11,127 @@ require 'thinking_sphinx/deltas/delayed_delta/version'
|
|
16
11
|
# @author Patrick Allan
|
17
12
|
# @see http://ts.freelancing-gods.com Thinking Sphinx
|
18
13
|
#
|
19
|
-
class ThinkingSphinx::Deltas::DelayedDelta <
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# Neither job will be queued if updates or deltas are disabled, or if the
|
26
|
-
# instance (when given) is not toggled to be in the delta index. The first two
|
27
|
-
# options are controlled via ThinkingSphinx.updates_enabled? and
|
28
|
-
# ThinkingSphinx.deltas_enabled?.
|
29
|
-
#
|
30
|
-
# @param [Class] model the ActiveRecord model to index.
|
31
|
-
# @param [ActiveRecord::Base] instance the instance of the given model that
|
32
|
-
# has changed. Optional.
|
33
|
-
# @return [Boolean] true
|
34
|
-
#
|
35
|
-
def index(model, instance = nil)
|
36
|
-
return true if skip? instance
|
37
|
-
return true if instance && !toggled(instance)
|
38
|
-
|
39
|
-
ThinkingSphinx::Deltas::Job.enqueue(
|
40
|
-
ThinkingSphinx::Deltas::DeltaJob.new(model.delta_index_names),
|
41
|
-
ThinkingSphinx::Configuration.instance.delayed_job_priority
|
14
|
+
class ThinkingSphinx::Deltas::DelayedDelta <
|
15
|
+
ThinkingSphinx::Deltas::DefaultDelta
|
16
|
+
|
17
|
+
def self.cancel_jobs
|
18
|
+
Delayed::Job.delete_all(
|
19
|
+
"handler LIKE '--- !ruby/object:ThinkingSphinx::Deltas::%'"
|
42
20
|
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.enqueue_unless_duplicates(object)
|
24
|
+
if Delayed::Job.respond_to?(:where)
|
25
|
+
return if Delayed::Job.where(
|
26
|
+
:handler => object.to_yaml, :locked_at => nil
|
27
|
+
).count > 0
|
28
|
+
else
|
29
|
+
return if Delayed::Job.count(
|
30
|
+
:conditions => {:handler => object.to_yaml, :locked_at => nil}
|
31
|
+
) > 0
|
32
|
+
end
|
43
33
|
|
44
|
-
Delayed::Job.enqueue
|
45
|
-
|
46
|
-
model.core_index_names, instance.sphinx_document_id
|
47
|
-
),
|
48
|
-
:priority => ThinkingSphinx::Configuration.instance.delayed_job_priority
|
49
|
-
) if instance
|
34
|
+
Delayed::Job.enqueue object, priority_option
|
35
|
+
end
|
50
36
|
|
51
|
-
|
37
|
+
def self.priority_option
|
38
|
+
if Gem.loaded_specs['delayed_job'].version.to_s.match(/^2\.0\./)
|
39
|
+
# Fallback for compatibility with old release 2.0.x of DJ
|
40
|
+
priority
|
41
|
+
else
|
42
|
+
{:priority => priority}
|
43
|
+
end
|
52
44
|
end
|
53
45
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
46
|
+
def self.priority
|
47
|
+
configuration = ThinkingSphinx::Configuration.instance
|
48
|
+
if configuration.respond_to? :delayed_job_priority
|
49
|
+
configuration.delayed_job_priority
|
50
|
+
else
|
51
|
+
configuration.settings['delayed_job_priority'] || 0
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module Binary
|
56
|
+
# Adds a job to the queue for processing the given model's delta index. A job
|
57
|
+
# for hiding the instance in the core index is also created, if an instance is
|
58
|
+
# provided.
|
59
|
+
#
|
60
|
+
# Neither job will be queued if updates or deltas are disabled, or if the
|
61
|
+
# instance (when given) is not toggled to be in the delta index. The first two
|
62
|
+
# options are controlled via ThinkingSphinx.updates_enabled? and
|
63
|
+
# ThinkingSphinx.deltas_enabled?.
|
64
|
+
#
|
65
|
+
# @param [Class] model the ActiveRecord model to index.
|
66
|
+
# @param [ActiveRecord::Base] instance the instance of the given model that
|
67
|
+
# has changed. Optional.
|
68
|
+
# @return [Boolean] true
|
69
|
+
#
|
70
|
+
def index(model, instance = nil)
|
71
|
+
return true if skip? instance
|
72
|
+
|
73
|
+
self.class.enqueue_unless_duplicates(
|
74
|
+
ThinkingSphinx::Deltas::DelayedDelta::DeltaJob.new(
|
75
|
+
model.delta_index_names
|
76
|
+
)
|
77
|
+
)
|
78
|
+
|
79
|
+
Delayed::Job.enqueue(
|
80
|
+
ThinkingSphinx::Deltas::DelayedDelta::FlagAsDeletedJob.new(
|
81
|
+
model.core_index_names, instance.sphinx_document_id
|
82
|
+
), self.class.priority_option
|
83
|
+
) if instance
|
84
|
+
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Checks whether jobs should be enqueued. Only true if updates and deltas are
|
91
|
+
# enabled, and the instance (if there is one) is toggled.
|
92
|
+
#
|
93
|
+
# @param [ActiveRecord::Base, NilClass] instance
|
94
|
+
# @return [Boolean]
|
95
|
+
#
|
96
|
+
def skip?(instance)
|
97
|
+
!ThinkingSphinx.updates_enabled? ||
|
98
|
+
!ThinkingSphinx.deltas_enabled? ||
|
99
|
+
(instance && !toggled(instance))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module SphinxQL
|
104
|
+
def delete(index, instance)
|
105
|
+
Delayed::Job.enqueue(
|
106
|
+
ThinkingSphinx::Deltas::DelayedDelta::FlagAsDeletedJob.new(
|
107
|
+
index.name, index.document_id_for_key(instance.id)
|
108
|
+
), self.class.priority_option
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Adds a job to the queue for processing the given index.
|
113
|
+
#
|
114
|
+
# @param [Class] index the Thinking Sphinx index object.
|
115
|
+
#
|
116
|
+
def index(index)
|
117
|
+
self.class.enqueue_unless_duplicates(
|
118
|
+
ThinkingSphinx::Deltas::DelayedDelta::DeltaJob.new(index.name)
|
119
|
+
)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
if [:delayed_job_priority, 'delayed_job_priority'].any? { |method|
|
124
|
+
ThinkingSphinx::Configuration.instance_methods.include?(method)
|
125
|
+
}
|
126
|
+
include Binary
|
127
|
+
else
|
128
|
+
include SphinxQL
|
66
129
|
end
|
67
130
|
end
|
131
|
+
|
132
|
+
require 'thinking_sphinx/deltas/delayed_delta/delta_job'
|
133
|
+
require 'thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job'
|
134
|
+
|
135
|
+
ThinkingSphinx.before_index_hooks << Proc.new {
|
136
|
+
ThinkingSphinx::Deltas::DelayedDelta.cancel_jobs
|
137
|
+
}
|
@@ -1,33 +1,24 @@
|
|
1
1
|
# A simple job class that processes a given index.
|
2
2
|
#
|
3
|
-
class ThinkingSphinx::Deltas::DeltaJob
|
4
|
-
attr_accessor :indices
|
5
|
-
|
3
|
+
class ThinkingSphinx::Deltas::DelayedDelta::DeltaJob
|
6
4
|
# Initialises the object with an index name.
|
7
5
|
#
|
8
6
|
# @param [String] index the name of the Sphinx index
|
9
7
|
#
|
10
|
-
def initialize(
|
11
|
-
@
|
8
|
+
def initialize(index)
|
9
|
+
@index = index
|
12
10
|
end
|
13
11
|
|
14
12
|
# Shows index name in Delayed::Job#name.
|
15
13
|
#
|
16
14
|
def display_name
|
17
|
-
"
|
15
|
+
"Thinking Sphinx: Process #{@index}"
|
18
16
|
end
|
19
17
|
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# @return [Boolean] true
|
18
|
+
# Processes just the given index. Output is hidden only if the quiet_deltas
|
19
|
+
# setting is true.
|
24
20
|
#
|
25
21
|
def perform
|
26
|
-
|
27
|
-
|
28
|
-
output = `#{config.bin_path}#{config.indexer_binary_name} --config "#{config.config_file}" --rotate #{indices.join(' ')}`
|
29
|
-
puts output unless ThinkingSphinx.suppress_delta_output?
|
30
|
-
|
31
|
-
true
|
22
|
+
ThinkingSphinx::Deltas::IndexJob.new(@index).perform
|
32
23
|
end
|
33
24
|
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
# A simple job for flagging a specified Sphinx document in a given index as
|
2
2
|
# 'deleted'.
|
3
3
|
#
|
4
|
-
class ThinkingSphinx::Deltas::FlagAsDeletedJob
|
5
|
-
attr_accessor :indices, :document_id
|
6
|
-
|
4
|
+
class ThinkingSphinx::Deltas::DelayedDelta::FlagAsDeletedJob
|
7
5
|
# Initialises the object with an index name and document id. Please note that
|
8
6
|
# the document id is Sphinx's unique identifier, and will almost certainly not
|
9
7
|
# be the model instance's primary key value.
|
@@ -11,8 +9,12 @@ class ThinkingSphinx::Deltas::FlagAsDeletedJob
|
|
11
9
|
# @param [String] index The index name
|
12
10
|
# @param [Integer] document_id The document id
|
13
11
|
#
|
14
|
-
def initialize(
|
15
|
-
@
|
12
|
+
def initialize(index, document_id)
|
13
|
+
@index, @document_id = index, document_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def display_name
|
17
|
+
"Thinking Sphinx: Mark #{@document_id} in #{@index} as deleted"
|
16
18
|
end
|
17
19
|
|
18
20
|
# Updates the sphinx_deleted attribute for the given document, setting the
|
@@ -21,20 +23,7 @@ class ThinkingSphinx::Deltas::FlagAsDeletedJob
|
|
21
23
|
# particularly useful in this situation to avoid old values in the core index
|
22
24
|
# and just use the new values in the delta index as a reference point.
|
23
25
|
#
|
24
|
-
# @return [Boolean] true
|
25
|
-
#
|
26
26
|
def perform
|
27
|
-
|
28
|
-
|
29
|
-
indices.each do |index|
|
30
|
-
config.client.update(
|
31
|
-
index,
|
32
|
-
['sphinx_deleted'],
|
33
|
-
{@document_id => [1]}
|
34
|
-
) if ThinkingSphinx.sphinx_running? &&
|
35
|
-
ThinkingSphinx.search_for_id(@document_id, index)
|
36
|
-
end
|
37
|
-
|
38
|
-
true
|
27
|
+
ThinkingSphinx::Deltas::DeleteJob.new(@index, @document_id).perform
|
39
28
|
end
|
40
29
|
end
|