thinking-sphinx 3.3.0 → 3.4.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +29 -20
- data/Appraisals +9 -5
- data/Gemfile +8 -3
- data/HISTORY +24 -0
- data/README.textile +5 -4
- data/bin/console +14 -0
- data/bin/literals +9 -0
- data/bin/loadsphinx +38 -0
- data/lib/thinking_sphinx.rb +15 -2
- data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +2 -3
- data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +11 -1
- data/lib/thinking_sphinx/active_record/index.rb +1 -1
- data/lib/thinking_sphinx/active_record/join_association.rb +3 -1
- data/lib/thinking_sphinx/active_record/log_subscriber.rb +5 -0
- data/lib/thinking_sphinx/active_record/sql_source.rb +1 -1
- data/lib/thinking_sphinx/attribute_types.rb +70 -0
- data/lib/thinking_sphinx/commands/base.rb +41 -0
- data/lib/thinking_sphinx/commands/configure.rb +13 -0
- data/lib/thinking_sphinx/commands/index.rb +11 -0
- data/lib/thinking_sphinx/commands/start_attached.rb +20 -0
- data/lib/thinking_sphinx/commands/start_detached.rb +19 -0
- data/lib/thinking_sphinx/commands/stop.rb +22 -0
- data/lib/thinking_sphinx/configuration.rb +36 -28
- data/lib/thinking_sphinx/configuration/minimum_fields.rb +11 -8
- data/lib/thinking_sphinx/connection.rb +5 -122
- data/lib/thinking_sphinx/connection/client.rb +48 -0
- data/lib/thinking_sphinx/connection/jruby.rb +53 -0
- data/lib/thinking_sphinx/connection/mri.rb +28 -0
- data/lib/thinking_sphinx/core/index.rb +11 -0
- data/lib/thinking_sphinx/deletion.rb +6 -2
- data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
- data/lib/thinking_sphinx/deltas/delete_job.rb +14 -4
- data/lib/thinking_sphinx/distributed/index.rb +10 -0
- data/lib/thinking_sphinx/errors.rb +1 -1
- data/lib/thinking_sphinx/index_set.rb +14 -2
- data/lib/thinking_sphinx/interfaces/daemon.rb +32 -0
- data/lib/thinking_sphinx/interfaces/real_time.rb +41 -0
- data/lib/thinking_sphinx/interfaces/sql.rb +41 -0
- data/lib/thinking_sphinx/middlewares.rb +5 -3
- data/lib/thinking_sphinx/middlewares/active_record_translator.rb +13 -6
- data/lib/thinking_sphinx/middlewares/attribute_typer.rb +48 -0
- data/lib/thinking_sphinx/middlewares/valid_options.rb +23 -0
- data/lib/thinking_sphinx/rake_interface.rb +10 -124
- data/lib/thinking_sphinx/search.rb +11 -0
- data/lib/thinking_sphinx/search/query.rb +7 -1
- data/lib/thinking_sphinx/tasks.rb +80 -21
- data/lib/thinking_sphinx/with_output.rb +11 -0
- data/spec/acceptance/connection_spec.rb +4 -4
- data/spec/acceptance/searching_within_a_model_spec.rb +7 -0
- data/spec/acceptance/specifying_sql_spec.rb +26 -8
- data/spec/acceptance/sql_deltas_spec.rb +12 -0
- data/spec/internal/app/indices/album_index.rb +3 -0
- data/spec/internal/app/models/album.rb +19 -0
- data/spec/internal/db/schema.rb +8 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/json_column.rb +5 -1
- data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +5 -1
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +6 -0
- data/spec/thinking_sphinx/attribute_types_spec.rb +50 -0
- data/spec/thinking_sphinx/commands/configure_spec.rb +29 -0
- data/spec/thinking_sphinx/commands/index_spec.rb +26 -0
- data/spec/thinking_sphinx/commands/start_detached_spec.rb +55 -0
- data/spec/thinking_sphinx/commands/stop_spec.rb +54 -0
- data/spec/thinking_sphinx/configuration/minimum_fields_spec.rb +36 -0
- data/spec/thinking_sphinx/deletion_spec.rb +2 -5
- data/spec/thinking_sphinx/deltas/default_delta_spec.rb +1 -1
- data/spec/thinking_sphinx/errors_spec.rb +7 -0
- data/spec/thinking_sphinx/index_set_spec.rb +30 -7
- data/spec/thinking_sphinx/interfaces/daemon_spec.rb +52 -0
- data/spec/thinking_sphinx/interfaces/real_time_spec.rb +109 -0
- data/spec/thinking_sphinx/interfaces/sql_spec.rb +98 -0
- data/spec/thinking_sphinx/middlewares/attribute_typer_spec.rb +42 -0
- data/spec/thinking_sphinx/middlewares/valid_options_spec.rb +49 -0
- data/spec/thinking_sphinx/rake_interface_spec.rb +13 -246
- data/spec/thinking_sphinx/search/query_spec.rb +7 -0
- data/thinking-sphinx.gemspec +5 -4
- metadata +72 -16
- data/gemfiles/.gitignore +0 -1
- data/gemfiles/rails_3_2.gemfile +0 -13
- data/gemfiles/rails_4_0.gemfile +0 -13
- data/gemfiles/rails_4_1.gemfile +0 -13
- data/gemfiles/rails_4_2.gemfile +0 -13
- data/gemfiles/rails_5_0.gemfile +0 -12
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ThinkingSphinx::Interfaces::Daemon do
|
4
|
+
let(:configuration) { double 'configuration', :controller => controller }
|
5
|
+
let(:controller) { double 'controller', :running? => false }
|
6
|
+
let(:stream) { double 'stream', :puts => true }
|
7
|
+
let(:interface) {
|
8
|
+
ThinkingSphinx::Interfaces::Daemon.new(configuration, {}, stream)
|
9
|
+
}
|
10
|
+
|
11
|
+
describe '#start' do
|
12
|
+
let(:command) { double 'command', :call => true }
|
13
|
+
|
14
|
+
before :each do
|
15
|
+
stub_const 'ThinkingSphinx::Commands::StartDetached', command
|
16
|
+
end
|
17
|
+
|
18
|
+
it "starts the daemon" do
|
19
|
+
expect(command).to receive(:call)
|
20
|
+
|
21
|
+
interface.start
|
22
|
+
end
|
23
|
+
|
24
|
+
it "raises an error if the daemon is already running" do
|
25
|
+
allow(controller).to receive_messages :running? => true
|
26
|
+
|
27
|
+
expect {
|
28
|
+
interface.start
|
29
|
+
}.to raise_error(ThinkingSphinx::SphinxAlreadyRunning)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#status' do
|
34
|
+
it "reports when the daemon is running" do
|
35
|
+
allow(controller).to receive_messages :running? => true
|
36
|
+
|
37
|
+
expect(stream).to receive(:puts).
|
38
|
+
with('The Sphinx daemon searchd is currently running.')
|
39
|
+
|
40
|
+
interface.status
|
41
|
+
end
|
42
|
+
|
43
|
+
it "reports when the daemon is not running" do
|
44
|
+
allow(controller).to receive_messages :running? => false
|
45
|
+
|
46
|
+
expect(stream).to receive(:puts).
|
47
|
+
with('The Sphinx daemon searchd is not currently running.')
|
48
|
+
|
49
|
+
interface.status
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ThinkingSphinx::Interfaces::SQL do
|
4
|
+
let(:interface) { ThinkingSphinx::Interfaces::RealTime.new(
|
5
|
+
configuration, {}, stream
|
6
|
+
) }
|
7
|
+
let(:configuration) { double 'configuration', :controller => controller,
|
8
|
+
:render => true, :indices_location => '/path/to/indices',
|
9
|
+
:preload_indices => true }
|
10
|
+
let(:controller) { double 'controller', :running? => true }
|
11
|
+
let(:stream) { double :puts => nil }
|
12
|
+
|
13
|
+
describe '#clear' do
|
14
|
+
let(:plain_index) { double(:type => 'plain') }
|
15
|
+
let(:users_index) { double(:name => 'users', :type => 'rt', :render => true,
|
16
|
+
:path => '/path/to/my/index/users') }
|
17
|
+
let(:parts_index) { double(:name => 'parts', :type => 'rt', :render => true,
|
18
|
+
:path => '/path/to/my/index/parts') }
|
19
|
+
|
20
|
+
before :each do
|
21
|
+
allow(configuration).to receive_messages(
|
22
|
+
:indices => [plain_index, users_index, parts_index],
|
23
|
+
:searchd => double(:binlog_path => '/path/to/binlog')
|
24
|
+
)
|
25
|
+
|
26
|
+
allow(Dir).to receive(:[]).with('/path/to/my/index/users.*').
|
27
|
+
and_return(['users.a', 'users.b'])
|
28
|
+
allow(Dir).to receive(:[]).with('/path/to/my/index/parts.*').
|
29
|
+
and_return(['parts.a', 'parts.b'])
|
30
|
+
|
31
|
+
allow(FileUtils).to receive_messages :mkdir_p => true, :rm_r => true,
|
32
|
+
:rm => true
|
33
|
+
allow(File).to receive_messages :exists? => true
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'finds each file for real-time indices' do
|
37
|
+
expect(Dir).to receive(:[]).with('/path/to/my/index/users.*').
|
38
|
+
and_return([])
|
39
|
+
|
40
|
+
interface.clear
|
41
|
+
end
|
42
|
+
|
43
|
+
it "removes the directory for the binlog files" do
|
44
|
+
expect(FileUtils).to receive(:rm_r).with('/path/to/binlog')
|
45
|
+
|
46
|
+
interface.clear
|
47
|
+
end
|
48
|
+
|
49
|
+
it "removes each file for real-time indices" do
|
50
|
+
expect(FileUtils).to receive(:rm).with('users.a')
|
51
|
+
expect(FileUtils).to receive(:rm).with('users.b')
|
52
|
+
expect(FileUtils).to receive(:rm).with('parts.a')
|
53
|
+
expect(FileUtils).to receive(:rm).with('parts.b')
|
54
|
+
|
55
|
+
interface.clear
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with options[:index_filter]" do
|
59
|
+
let(:interface) { ThinkingSphinx::Interfaces::RealTime.new(
|
60
|
+
configuration, {:index_filter => 'users'}, stream
|
61
|
+
) }
|
62
|
+
|
63
|
+
it "removes each file for real-time indices that match :index_filter" do
|
64
|
+
expect(FileUtils).to receive(:rm).with('users.a')
|
65
|
+
expect(FileUtils).to receive(:rm).with('users.b')
|
66
|
+
expect(FileUtils).not_to receive(:rm).with('parts.a')
|
67
|
+
expect(FileUtils).not_to receive(:rm).with('parts.b')
|
68
|
+
|
69
|
+
interface.clear
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#index' do
|
75
|
+
let(:plain_index) { double(:type => 'plain') }
|
76
|
+
let(:users_index) { double(name: 'users', :type => 'rt') }
|
77
|
+
let(:parts_index) { double(name: 'parts', :type => 'rt') }
|
78
|
+
|
79
|
+
before :each do
|
80
|
+
allow(configuration).to receive_messages(
|
81
|
+
:indices => [plain_index, users_index, parts_index]
|
82
|
+
)
|
83
|
+
|
84
|
+
allow(FileUtils).to receive_messages :mkdir_p => true
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'populates each real-index' do
|
88
|
+
expect(ThinkingSphinx::RealTime::Populator).to receive(:populate).with(users_index)
|
89
|
+
expect(ThinkingSphinx::RealTime::Populator).to receive(:populate).with(parts_index)
|
90
|
+
expect(ThinkingSphinx::RealTime::Populator).not_to receive(:populate).with(plain_index)
|
91
|
+
|
92
|
+
interface.index
|
93
|
+
end
|
94
|
+
|
95
|
+
context "with options[:index_filter]" do
|
96
|
+
let(:interface) { ThinkingSphinx::Interfaces::RealTime.new(
|
97
|
+
configuration, {:index_filter => 'users'}, stream
|
98
|
+
) }
|
99
|
+
|
100
|
+
it 'populates each real-index that matches :index_filter' do
|
101
|
+
expect(ThinkingSphinx::RealTime::Populator).to receive(:populate).with(users_index)
|
102
|
+
expect(ThinkingSphinx::RealTime::Populator).not_to receive(:populate).with(parts_index)
|
103
|
+
expect(ThinkingSphinx::RealTime::Populator).not_to receive(:populate).with(plain_index)
|
104
|
+
|
105
|
+
interface.index
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ThinkingSphinx::Interfaces::SQL do
|
4
|
+
let(:interface) { ThinkingSphinx::Interfaces::SQL.new(
|
5
|
+
configuration, {:verbose => true}, stream
|
6
|
+
) }
|
7
|
+
let(:configuration) { double 'configuration', :preload_indices => true,
|
8
|
+
:render => true, :indices => [double(:index, :type => 'plain')],
|
9
|
+
:indices_location => '/path/to/indices' }
|
10
|
+
let(:stream) { double :puts => nil }
|
11
|
+
|
12
|
+
describe '#clear' do
|
13
|
+
let(:users_index) { double(:name => 'users', :type => 'plain',
|
14
|
+
:render => true, :path => '/path/to/my/index/users') }
|
15
|
+
let(:parts_index) { double(:name => 'users', :type => 'plain',
|
16
|
+
:render => true, :path => '/path/to/my/index/parts') }
|
17
|
+
let(:rt_index) { double(:type => 'rt') }
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
allow(configuration).to receive_messages(
|
21
|
+
:indices => [users_index, parts_index, rt_index]
|
22
|
+
)
|
23
|
+
|
24
|
+
allow(Dir).to receive(:[]).with('/path/to/my/index/users.*').
|
25
|
+
and_return(['users.a', 'users.b'])
|
26
|
+
allow(Dir).to receive(:[]).with('/path/to/my/index/parts.*').
|
27
|
+
and_return(['parts.a', 'parts.b'])
|
28
|
+
|
29
|
+
allow(FileUtils).to receive_messages :mkdir_p => true, :rm_r => true,
|
30
|
+
:rm => true
|
31
|
+
allow(File).to receive_messages :exists? => true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'finds each file for sql-backed indices' do
|
35
|
+
expect(Dir).to receive(:[]).with('/path/to/my/index/users.*').
|
36
|
+
and_return([])
|
37
|
+
|
38
|
+
interface.clear
|
39
|
+
end
|
40
|
+
|
41
|
+
it "removes each file for real-time indices" do
|
42
|
+
expect(FileUtils).to receive(:rm).with('users.a')
|
43
|
+
expect(FileUtils).to receive(:rm).with('users.b')
|
44
|
+
expect(FileUtils).to receive(:rm).with('parts.a')
|
45
|
+
expect(FileUtils).to receive(:rm).with('parts.b')
|
46
|
+
|
47
|
+
interface.clear
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#index' do
|
52
|
+
let(:index_command) { double :call => true }
|
53
|
+
let(:configure_command) { double :call => true }
|
54
|
+
|
55
|
+
before :each do
|
56
|
+
stub_const 'ThinkingSphinx::Commands::Index', index_command
|
57
|
+
stub_const 'ThinkingSphinx::Commands::Configure', configure_command
|
58
|
+
|
59
|
+
allow(ThinkingSphinx).to receive_messages :before_index_hooks => []
|
60
|
+
allow(FileUtils).to receive_messages :mkdir_p => true
|
61
|
+
end
|
62
|
+
|
63
|
+
it "renders the configuration to a file by default" do
|
64
|
+
expect(configure_command).to receive(:call)
|
65
|
+
|
66
|
+
interface.index
|
67
|
+
end
|
68
|
+
|
69
|
+
it "does not render the configuration if requested" do
|
70
|
+
expect(configure_command).not_to receive(:call)
|
71
|
+
|
72
|
+
interface.index false
|
73
|
+
end
|
74
|
+
|
75
|
+
it "creates the directory for the index files" do
|
76
|
+
expect(FileUtils).to receive(:mkdir_p).with('/path/to/indices')
|
77
|
+
|
78
|
+
interface.index
|
79
|
+
end
|
80
|
+
|
81
|
+
it "calls all registered hooks" do
|
82
|
+
called = false
|
83
|
+
ThinkingSphinx.before_index_hooks << Proc.new { called = true }
|
84
|
+
|
85
|
+
interface.index
|
86
|
+
|
87
|
+
expect(called).to be_truthy
|
88
|
+
end
|
89
|
+
|
90
|
+
it "executes the index command" do
|
91
|
+
expect(index_command).to receive(:call).with(
|
92
|
+
configuration, {:verbose => true}, stream
|
93
|
+
)
|
94
|
+
|
95
|
+
interface.index
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ThinkingSphinx::Middlewares::AttributeTyper do
|
4
|
+
let(:app) { double('app', :call => true) }
|
5
|
+
let(:middleware) { ThinkingSphinx::Middlewares::AttributeTyper.new app }
|
6
|
+
let(:attributes) { {} }
|
7
|
+
let(:context) { double('context', :search => search) }
|
8
|
+
let(:search) { double('search', :options => {}) }
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
allow(ThinkingSphinx::AttributeTypes).to receive(:call).
|
12
|
+
and_return(attributes)
|
13
|
+
allow(ActiveSupport::Deprecation).to receive(:warn)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'warns when providing a string value for an integer attribute' do
|
17
|
+
attributes['user_id'] = [:uint]
|
18
|
+
search.options[:with] = {:user_id => '1'}
|
19
|
+
|
20
|
+
expect(ActiveSupport::Deprecation).to receive(:warn)
|
21
|
+
|
22
|
+
middleware.call [context]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'warns when providing a string value for a float attribute' do
|
26
|
+
attributes['price'] = [:float]
|
27
|
+
search.options[:without] = {:price => '1.0'}
|
28
|
+
|
29
|
+
expect(ActiveSupport::Deprecation).to receive(:warn)
|
30
|
+
|
31
|
+
middleware.call [context]
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'proceeds when providing a string value for a string attribute' do
|
35
|
+
attributes['status'] = [:string]
|
36
|
+
search.options[:with] = {:status => 'completed'}
|
37
|
+
|
38
|
+
expect(ActiveSupport::Deprecation).not_to receive(:warn)
|
39
|
+
|
40
|
+
middleware.call [context]
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ThinkingSphinx::Middlewares::ValidOptions do
|
4
|
+
let(:app) { double 'app', :call => true }
|
5
|
+
let(:middleware) { ThinkingSphinx::Middlewares::ValidOptions.new app }
|
6
|
+
let(:context) { double 'context', :search => search }
|
7
|
+
let(:search) { double 'search', :options => {} }
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
allow(ThinkingSphinx::Logger).to receive(:log)
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'with unknown options' do
|
14
|
+
before :each do
|
15
|
+
search.options[:foo] = :bar
|
16
|
+
end
|
17
|
+
|
18
|
+
it "adds a warning" do
|
19
|
+
expect(ThinkingSphinx::Logger).to receive(:log).
|
20
|
+
with(:warn, "Unexpected search options: [:foo]")
|
21
|
+
|
22
|
+
middleware.call [context]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'continues on' do
|
26
|
+
expect(app).to receive(:call).with([context])
|
27
|
+
|
28
|
+
middleware.call [context]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with known options" do
|
33
|
+
before :each do
|
34
|
+
search.options[:ids_only] = true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "is silent" do
|
38
|
+
expect(ThinkingSphinx::Logger).to_not receive(:log)
|
39
|
+
|
40
|
+
middleware.call [context]
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'continues on' do
|
44
|
+
expect(app).to receive(:call).with([context])
|
45
|
+
|
46
|
+
middleware.call [context]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,270 +1,37 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ThinkingSphinx::RakeInterface do
|
4
|
-
let(:configuration) { double('configuration', :controller => controller) }
|
5
4
|
let(:interface) { ThinkingSphinx::RakeInterface.new }
|
6
5
|
|
7
|
-
before :each do
|
8
|
-
allow(ThinkingSphinx::Configuration).to receive_messages :instance => configuration
|
9
|
-
allow(interface).to receive_messages(:puts => nil)
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '#clear_all' do
|
13
|
-
let(:controller) { double 'controller' }
|
14
|
-
|
15
|
-
before :each do
|
16
|
-
allow(configuration).to receive_messages(
|
17
|
-
:indices_location => '/path/to/indices',
|
18
|
-
:searchd => double(:binlog_path => '/path/to/binlog')
|
19
|
-
)
|
20
|
-
|
21
|
-
allow(FileUtils).to receive_messages :rm_r => true
|
22
|
-
allow(File).to receive_messages :exists? => true
|
23
|
-
end
|
24
|
-
|
25
|
-
it "removes the directory for the index files" do
|
26
|
-
expect(FileUtils).to receive(:rm_r).with('/path/to/indices')
|
27
|
-
|
28
|
-
interface.clear_all
|
29
|
-
end
|
30
|
-
|
31
|
-
it "removes the directory for the binlog files" do
|
32
|
-
expect(FileUtils).to receive(:rm_r).with('/path/to/binlog')
|
33
|
-
|
34
|
-
interface.clear_all
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe '#clear_real_time' do
|
39
|
-
let(:controller) { double 'controller' }
|
40
|
-
let(:index) {
|
41
|
-
double(:type => 'rt', :render => true, :path => '/path/to/my/index')
|
42
|
-
}
|
43
|
-
|
44
|
-
before :each do
|
45
|
-
allow(configuration).to receive_messages(
|
46
|
-
:indices => [double(:type => 'plain'), index],
|
47
|
-
:searchd => double(:binlog_path => '/path/to/binlog'),
|
48
|
-
:preload_indices => true
|
49
|
-
)
|
50
|
-
|
51
|
-
allow(Dir).to receive_messages :[] => ['foo.a', 'foo.b']
|
52
|
-
allow(FileUtils).to receive_messages :rm_r => true, :rm => true
|
53
|
-
allow(File).to receive_messages :exists? => true
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'finds each file for real-time indices' do
|
57
|
-
expect(Dir).to receive(:[]).with('/path/to/my/index.*').and_return([])
|
58
|
-
|
59
|
-
interface.clear_real_time
|
60
|
-
end
|
61
|
-
|
62
|
-
it "removes each file for real-time indices" do
|
63
|
-
expect(FileUtils).to receive(:rm).with('foo.a')
|
64
|
-
expect(FileUtils).to receive(:rm).with('foo.b')
|
65
|
-
|
66
|
-
interface.clear_real_time
|
67
|
-
end
|
68
|
-
|
69
|
-
it "removes the directory for the binlog files" do
|
70
|
-
expect(FileUtils).to receive(:rm_r).with('/path/to/binlog')
|
71
|
-
|
72
|
-
interface.clear_real_time
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
6
|
describe '#configure' do
|
77
|
-
let(:
|
7
|
+
let(:command) { double 'command', :call => true }
|
78
8
|
|
79
9
|
before :each do
|
80
|
-
|
81
|
-
:configuration_file => '/path/to/foo.conf',
|
82
|
-
:render_to_file => true
|
83
|
-
)
|
84
|
-
end
|
85
|
-
|
86
|
-
it "renders the configuration to a file" do
|
87
|
-
expect(configuration).to receive(:render_to_file)
|
88
|
-
|
89
|
-
interface.configure
|
10
|
+
stub_const 'ThinkingSphinx::Commands::Configure', command
|
90
11
|
end
|
91
12
|
|
92
|
-
it
|
93
|
-
expect(
|
94
|
-
with('Generating configuration to /path/to/foo.conf')
|
13
|
+
it 'sends the configure command' do
|
14
|
+
expect(command).to receive(:call)
|
95
15
|
|
96
16
|
interface.configure
|
97
17
|
end
|
98
18
|
end
|
99
19
|
|
100
|
-
describe '#
|
101
|
-
|
102
|
-
|
103
|
-
before :each do
|
104
|
-
allow(ThinkingSphinx).to receive_messages :before_index_hooks => []
|
105
|
-
allow(configuration).to receive_messages(
|
106
|
-
:configuration_file => '/path/to/foo.conf',
|
107
|
-
:render_to_file => true,
|
108
|
-
:indices_location => '/path/to/indices'
|
109
|
-
)
|
110
|
-
|
111
|
-
allow(FileUtils).to receive_messages :mkdir_p => true
|
112
|
-
end
|
113
|
-
|
114
|
-
it "renders the configuration to a file by default" do
|
115
|
-
expect(configuration).to receive(:render_to_file)
|
116
|
-
|
117
|
-
interface.index
|
118
|
-
end
|
119
|
-
|
120
|
-
it "does not render the configuration if requested" do
|
121
|
-
expect(configuration).not_to receive(:render_to_file)
|
122
|
-
|
123
|
-
interface.index false
|
124
|
-
end
|
125
|
-
|
126
|
-
it "creates the directory for the index files" do
|
127
|
-
expect(FileUtils).to receive(:mkdir_p).with('/path/to/indices')
|
128
|
-
|
129
|
-
interface.index
|
130
|
-
end
|
131
|
-
|
132
|
-
it "calls all registered hooks" do
|
133
|
-
called = false
|
134
|
-
ThinkingSphinx.before_index_hooks << Proc.new { called = true }
|
135
|
-
|
136
|
-
interface.index
|
137
|
-
|
138
|
-
expect(called).to be_truthy
|
139
|
-
end
|
140
|
-
|
141
|
-
it "indexes all indices verbosely" do
|
142
|
-
expect(controller).to receive(:index).with(:verbose => true)
|
143
|
-
|
144
|
-
interface.index
|
145
|
-
end
|
146
|
-
|
147
|
-
it "does not index verbosely if requested" do
|
148
|
-
expect(controller).to receive(:index).with(:verbose => false)
|
149
|
-
|
150
|
-
interface.index true, false
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe '#start' do
|
155
|
-
let(:controller) { double('controller', :start => result, :pid => 101) }
|
156
|
-
let(:result) { double 'result', :command => 'start', :status => 1,
|
157
|
-
:output => '' }
|
158
|
-
|
159
|
-
before :each do
|
160
|
-
allow(controller).to receive(:running?).and_return(false, true)
|
161
|
-
allow(configuration).to receive_messages(
|
162
|
-
:indices_location => 'my/index/files',
|
163
|
-
:searchd => double(:log => '/path/to/log')
|
164
|
-
)
|
165
|
-
|
166
|
-
allow(FileUtils).to receive_messages :mkdir_p => true
|
167
|
-
end
|
168
|
-
|
169
|
-
it "creates the index files directory" do
|
170
|
-
expect(FileUtils).to receive(:mkdir_p).with('my/index/files')
|
171
|
-
|
172
|
-
interface.start
|
173
|
-
end
|
174
|
-
|
175
|
-
it "starts the daemon" do
|
176
|
-
expect(controller).to receive(:start)
|
177
|
-
|
178
|
-
interface.start
|
179
|
-
end
|
180
|
-
|
181
|
-
it "raises an error if the daemon is already running" do
|
182
|
-
allow(controller).to receive_messages :running? => true
|
183
|
-
|
184
|
-
expect {
|
185
|
-
interface.start
|
186
|
-
}.to raise_error(ThinkingSphinx::SphinxAlreadyRunning)
|
187
|
-
end
|
188
|
-
|
189
|
-
it "prints a success message if the daemon has started" do
|
190
|
-
allow(controller).to receive(:running?).and_return(false, true)
|
191
|
-
|
192
|
-
expect(interface).to receive(:puts).
|
193
|
-
with('Started searchd successfully (pid: 101).')
|
194
|
-
|
195
|
-
interface.start
|
196
|
-
end
|
197
|
-
|
198
|
-
it "prints a failure message if the daemon does not start" do
|
199
|
-
allow(controller).to receive(:running?).and_return(false, false)
|
200
|
-
allow(interface).to receive(:exit)
|
201
|
-
|
202
|
-
expect(interface).to receive(:puts) do |string|
|
203
|
-
expect(string).to match('The Sphinx start command failed')
|
204
|
-
end
|
205
|
-
|
206
|
-
interface.start
|
20
|
+
describe '#daemon' do
|
21
|
+
it 'returns a daemon interface' do
|
22
|
+
expect(interface.daemon.class).to eq(ThinkingSphinx::Interfaces::Daemon)
|
207
23
|
end
|
208
24
|
end
|
209
25
|
|
210
|
-
describe '#
|
211
|
-
|
212
|
-
|
213
|
-
:output => '' }
|
214
|
-
|
215
|
-
before :each do
|
216
|
-
allow(controller).to receive(:running?).and_return(true, true, false)
|
217
|
-
end
|
218
|
-
|
219
|
-
it "prints a message if the daemon is not already running" do
|
220
|
-
allow(controller).to receive_messages :running? => false
|
221
|
-
|
222
|
-
expect(interface).to receive(:puts).with('searchd is not currently running.')
|
223
|
-
|
224
|
-
interface.stop
|
225
|
-
end
|
226
|
-
|
227
|
-
it "stops the daemon" do
|
228
|
-
expect(controller).to receive(:stop)
|
229
|
-
|
230
|
-
interface.stop
|
231
|
-
end
|
232
|
-
|
233
|
-
it "prints a message informing the daemon has stopped" do
|
234
|
-
expect(interface).to receive(:puts).with('Stopped searchd daemon (pid: 101).')
|
235
|
-
|
236
|
-
interface.stop
|
237
|
-
end
|
238
|
-
|
239
|
-
it "should retry stopping the daemon until it stops" do
|
240
|
-
allow(controller).to receive(:running?).
|
241
|
-
and_return(true, true, true, false)
|
242
|
-
|
243
|
-
expect(controller).to receive(:stop).twice
|
244
|
-
|
245
|
-
interface.stop
|
26
|
+
describe '#rt' do
|
27
|
+
it 'returns a real-time interface' do
|
28
|
+
expect(interface.rt.class).to eq(ThinkingSphinx::Interfaces::RealTime)
|
246
29
|
end
|
247
30
|
end
|
248
31
|
|
249
|
-
describe '#
|
250
|
-
|
251
|
-
|
252
|
-
it "reports when the daemon is running" do
|
253
|
-
allow(controller).to receive_messages :running? => true
|
254
|
-
|
255
|
-
expect(interface).to receive(:puts).
|
256
|
-
with('The Sphinx daemon searchd is currently running.')
|
257
|
-
|
258
|
-
interface.status
|
259
|
-
end
|
260
|
-
|
261
|
-
it "reports when the daemon is not running" do
|
262
|
-
allow(controller).to receive_messages :running? => false
|
263
|
-
|
264
|
-
expect(interface).to receive(:puts).
|
265
|
-
with('The Sphinx daemon searchd is not currently running.')
|
266
|
-
|
267
|
-
interface.status
|
32
|
+
describe '#sql' do
|
33
|
+
it 'returns an SQL interface' do
|
34
|
+
expect(interface.sql.class).to eq(ThinkingSphinx::Interfaces::SQL)
|
268
35
|
end
|
269
36
|
end
|
270
37
|
end
|