thinking-sphinx 1.4.12 → 1.4.13

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.
@@ -2,16 +2,23 @@ module ThinkingSphinx
2
2
  module ActiveRecord
3
3
  module HasManyAssociation
4
4
  def search(*args)
5
- options = args.extract_options!
5
+ @reflection.klass.search(*association_args(args))
6
+ end
7
+
8
+ def facets(*args)
9
+ @reflection.klass.facets(*association_args(args))
10
+ end
11
+
12
+ private
13
+
14
+ def association_args(args)
15
+ options = args.extract_options!
6
16
  options[:with] ||= {}
7
17
  options[:with].merge! default_filter
8
-
9
- args << options
10
- @reflection.klass.search(*args)
18
+
19
+ args + [options]
11
20
  end
12
21
 
13
- private
14
-
15
22
  def attribute_for_foreign_key
16
23
  foreign_key = @reflection.primary_key_name
17
24
  stack = [@reflection.options[:through]].compact
@@ -33,9 +33,9 @@ module ThinkingSphinx
33
33
 
34
34
  def cast_to_datetime(clause)
35
35
  if ThinkingSphinx::Configuration.instance.use_64_bit
36
- "cast(extract(epoch from #{clause}) as bigint)"
36
+ "cast(floor(extract(epoch from #{clause})) as bigint)"
37
37
  else
38
- "cast(extract(epoch from #{clause}) as int)"
38
+ "cast(floor(extract(epoch from #{clause})) as int)"
39
39
  end
40
40
  end
41
41
 
@@ -109,7 +109,7 @@ module ThinkingSphinx
109
109
  end
110
110
 
111
111
  def create_array_accum_function
112
- if server_version >= 80400
112
+ if server_version >= 80311
113
113
  return
114
114
  elsif server_version > 80200
115
115
  execute <<-SQL
@@ -9,7 +9,7 @@ module ThinkingSphinx
9
9
  require 'riddle/1.10'
10
10
  when /2.0.[12]/
11
11
  require 'riddle/2.0.1'
12
- when /2.0.3/, /2.0.4/, /2.1.\d/
12
+ when /2.0.[^12]/, /2.1.\d/
13
13
  require 'riddle/2.1.0'
14
14
  else
15
15
  documentation_link = %Q{
@@ -1,41 +1,41 @@
1
1
  module ThinkingSphinx
2
2
  class BundledSearch
3
3
  attr_reader :client
4
-
4
+
5
5
  def initialize
6
6
  @searches = []
7
7
  end
8
-
8
+
9
9
  def search(*args)
10
10
  @searches << ThinkingSphinx.search(*args)
11
11
  @searches.last.append_to client
12
12
  end
13
-
13
+
14
14
  def search_for_ids(*args)
15
15
  @searches << ThinkingSphinx.search_for_ids(*args)
16
16
  @searches.last.append_to client
17
17
  end
18
-
18
+
19
19
  def searches
20
20
  populate
21
21
  @searches
22
22
  end
23
-
23
+
24
24
  private
25
-
25
+
26
26
  def client
27
27
  @client ||= ThinkingSphinx::Configuration.instance.client
28
28
  end
29
-
29
+
30
30
  def populated?
31
31
  @populated
32
32
  end
33
-
33
+
34
34
  def populate
35
35
  return if populated?
36
-
36
+
37
37
  @populated = true
38
-
38
+
39
39
  client.run.each_with_index do |results, index|
40
40
  searches[index].populate_from_queue results
41
41
  end
@@ -28,6 +28,7 @@ module ThinkingSphinx
28
28
  # html remove elements:: ''
29
29
  # searchd_binary_name:: searchd
30
30
  # indexer_binary_name:: indexer
31
+ # hard_retry_count:: 0
31
32
  #
32
33
  # If you want to change these settings, create a YAML file at
33
34
  # config/sphinx.yml with settings for each environment, in a similar
@@ -64,7 +65,8 @@ module ThinkingSphinx
64
65
 
65
66
  attr_accessor :searchd_file_path, :allow_star, :app_root,
66
67
  :model_directories, :delayed_job_priority, :indexed_models, :use_64_bit,
67
- :touched_reindex_file, :stop_timeout, :version, :shuffle
68
+ :touched_reindex_file, :stop_timeout, :version, :shuffle,
69
+ :hard_retry_count
68
70
 
69
71
  attr_accessor :source_options, :index_options
70
72
 
@@ -112,6 +114,7 @@ module ThinkingSphinx
112
114
  self.delayed_job_priority = 0
113
115
  self.indexed_models = []
114
116
  self.shuffle = false
117
+ self.hard_retry_count = 0
115
118
 
116
119
  self.source_options = {}
117
120
  self.index_options = {
@@ -405,28 +405,41 @@ module ThinkingSphinx
405
405
  def populate
406
406
  return if @populated
407
407
  @populated = true
408
+ retries = hard_retries
408
409
 
409
- retry_on_stale_index do
410
- begin
411
- log "Querying: '#{query}'"
412
- runtime = Benchmark.realtime {
413
- @results = client.query query, indexes, comment
414
- }
415
- log "Found #{@results[:total_found]} results", :debug,
416
- "Sphinx (#{sprintf("%f", runtime)}s)"
417
-
418
- log "Sphinx Daemon returned warning: #{warning}", :error if warning?
419
-
420
- if error?
421
- log "Sphinx Daemon returned error: #{error}", :error
422
- raise SphinxError.new(error, @results) unless options[:ignore_errors]
410
+ begin
411
+ retry_on_stale_index do
412
+ begin
413
+ log "Querying: '#{query}'"
414
+ runtime = Benchmark.realtime {
415
+ @results = client.query query, indexes, comment
416
+ }
417
+ log "Found #{@results[:total_found]} results", :debug,
418
+ "Sphinx (#{sprintf("%f", runtime)}s)"
419
+
420
+ log "Sphinx Daemon returned warning: #{warning}", :error if warning?
421
+
422
+ if error?
423
+ log "Sphinx Daemon returned error: #{error}", :error
424
+ raise SphinxError.new(error, @results) unless options[:ignore_errors]
425
+ end
426
+ rescue Errno::ECONNREFUSED => err
427
+ raise ThinkingSphinx::ConnectionError,
428
+ 'Connection to Sphinx Daemon (searchd) failed.'
423
429
  end
424
- rescue Errno::ECONNREFUSED => err
425
- raise ThinkingSphinx::ConnectionError,
426
- 'Connection to Sphinx Daemon (searchd) failed.'
427
- end
428
430
 
429
- compose_results
431
+ compose_results
432
+ end
433
+ rescue => e
434
+ log 'Caught Sphinx exception: %s (%s %s left)' % [
435
+ e.message, retries, (retries == 1 ? 'try' : 'tries')
436
+ ]
437
+ retries -= 1
438
+ if retries >= 0
439
+ retry
440
+ else
441
+ raise e
442
+ end
430
443
  end
431
444
  end
432
445
 
@@ -847,6 +860,10 @@ module ThinkingSphinx
847
860
  end
848
861
  end
849
862
 
863
+ def hard_retries
864
+ options[:hard_retry_count] || config.hard_retry_count
865
+ end
866
+
850
867
  def include_for_class(klass)
851
868
  includes = options[:include] || klass.sphinx_index_options[:include]
852
869
 
@@ -1,3 +1,3 @@
1
1
  module ThinkingSphinx
2
- Version = '1.4.12'
2
+ Version = '1.4.13'
3
3
  end
@@ -41,6 +41,46 @@ describe 'ThinkingSphinx::ActiveRecord::HasManyAssociation' do
41
41
  end
42
42
  end
43
43
 
44
+ describe "facets method" do
45
+ before :each do
46
+ Friendship.stub!(:facets => true)
47
+
48
+ @person = Person.find(:first)
49
+ @index = Friendship.sphinx_indexes.first
50
+ end
51
+
52
+ it "should raise an error if the required attribute doesn't exist" do
53
+ @index.stub!(:attributes => [])
54
+
55
+ lambda { @person.friendships.facets "test" }.should raise_error(RuntimeError)
56
+ end
57
+
58
+ it "should add a filter for the attribute into a normal facets call" do
59
+ Friendship.should_receive(:facets) do |query, options|
60
+ options[:with][:person_id].should == @person.id
61
+ end
62
+
63
+ @person.friendships.facets "test"
64
+ end
65
+
66
+ it "should add a filter for an aliased attribute into a normal facets call" do
67
+ @team = CricketTeam.new
68
+ @team.stub!(:id => 1)
69
+
70
+ Person.should_receive(:facets).with do |query, options|
71
+ options[:with][:team_id].should == @team.id
72
+ end
73
+
74
+ @team.people.facets "test"
75
+ end
76
+
77
+ it "should define indexes for the reflection class" do
78
+ Friendship.should_receive(:define_indexes)
79
+
80
+ @person.friendships.facets 'test'
81
+ end
82
+ end
83
+
44
84
  describe "search method for has_many :through" do
45
85
  before :each do
46
86
  Person.stub!(:search => true)
@@ -75,6 +115,40 @@ describe 'ThinkingSphinx::ActiveRecord::HasManyAssociation' do
75
115
  end
76
116
  end
77
117
 
118
+ describe "facets method for has_many :through" do
119
+ before :each do
120
+ Person.stub!(:facets => true)
121
+
122
+ @person = Person.find(:first)
123
+ @index = Person.sphinx_indexes.first
124
+ end
125
+
126
+ it "should raise an error if the required attribute doesn't exist" do
127
+ @index.stub!(:attributes => [])
128
+
129
+ lambda { @person.friends.facets "test" }.should raise_error(RuntimeError)
130
+ end
131
+
132
+ it "should add a filter for the attribute into a normal facets call" do
133
+ Person.should_receive(:facets).with do |query, options|
134
+ options[:with][:friendly_ids].should == @person.id
135
+ end
136
+
137
+ @person.friends.facets "test"
138
+ end
139
+
140
+ it "should add a filter for an aliased attribute into a normal facets call" do
141
+ @team = FootballTeam.new
142
+ @team.stub!(:id => 1)
143
+
144
+ Person.should_receive(:facets).with do |query, options|
145
+ options[:with][:football_team_id].should == @team.id
146
+ end
147
+
148
+ @team.people.facets "test"
149
+ end
150
+ end
151
+
78
152
  describe 'filtering sphinx scopes' do
79
153
  before :each do
80
154
  Friendship.stub!(:search => Friendship)
@@ -62,6 +62,22 @@ describe ThinkingSphinx::AutoVersion do
62
62
  ThinkingSphinx::AutoVersion.detect
63
63
  end
64
64
 
65
+ it "should require 2.1.0 if using Sphinx 2.0.3" do
66
+ ThinkingSphinx::AutoVersion.should_receive(:require).
67
+ with('riddle/2.1.0')
68
+
69
+ @config.stub!(:version => '2.0.4-release')
70
+ ThinkingSphinx::AutoVersion.detect
71
+ end
72
+
73
+ it "should require 2.1.0 if using Sphinx 2.0.3" do
74
+ ThinkingSphinx::AutoVersion.should_receive(:require).
75
+ with('riddle/2.1.0')
76
+
77
+ @config.stub!(:version => '2.0.5-release')
78
+ ThinkingSphinx::AutoVersion.detect
79
+ end
80
+
65
81
  it "should require 2.1.0 if using Sphinx 2.1.0 dev" do
66
82
  ThinkingSphinx::AutoVersion.should_receive(:require).
67
83
  with('riddle/2.1.0')
@@ -411,6 +411,38 @@ describe ThinkingSphinx::Search do
411
411
  'baz @foo bar @(foo,bar) baz', :star => true
412
412
  ).first
413
413
  end
414
+
415
+ it "should try retry query up to the hard_retry_count option times if it catches an exception" do
416
+ @client.should_receive(:query).exactly(4).and_raise("Test Exception")
417
+
418
+ expect { ThinkingSphinx::Search.new(:hard_retry_count => 3).first }.
419
+ to raise_error("Test Exception")
420
+ end
421
+
422
+ it "should not retry query if hard_retry_count option is not set" do
423
+ @client.should_receive(:query).exactly(1).and_raise("Test Exception")
424
+
425
+ expect { ThinkingSphinx::Search.new.first }.
426
+ to raise_error("Test Exception")
427
+ end
428
+
429
+ it "should allow the hard_retry_count to be globally set as a configuration option" do
430
+ @config.hard_retry_count = 2
431
+
432
+ @client.should_receive(:query).exactly(3).and_raise("Test Exception")
433
+
434
+ expect { ThinkingSphinx::Search.new.first }.
435
+ to raise_error("Test Exception")
436
+ end
437
+
438
+ it "should give priority to the hard_retry_count search option over the globally configured option" do
439
+ @config.hard_retry_count = 4
440
+
441
+ @client.should_receive(:query).exactly(2).and_raise("Test Exception")
442
+
443
+ expect { ThinkingSphinx::Search.new(:hard_retry_count => 1).first }.
444
+ to raise_error("Test Exception")
445
+ end
414
446
  end
415
447
 
416
448
  describe 'comment' do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thinking-sphinx
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 4
9
- - 12
10
- version: 1.4.12
9
+ - 13
10
+ version: 1.4.13
11
11
  platform: ruby
12
12
  authors:
13
13
  - Pat Allan
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-05-14 00:00:00 Z
18
+ date: 2012-08-10 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :runtime
@@ -64,12 +64,12 @@ dependencies:
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
- hash: 7
67
+ hash: 5
68
68
  segments:
69
69
  - 1
70
70
  - 5
71
- - 2
72
- version: 1.5.2
71
+ - 3
72
+ version: 1.5.3
73
73
  version_requirements: *id003
74
74
  prerelease: false
75
75
  name: riddle