riddle 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.textile CHANGED
@@ -81,3 +81,5 @@ Thanks to the following people who have contributed to Riddle in some shape or f
81
81
  * Piotr Sarnacki
82
82
  * Tim Preston
83
83
  * Amir Yalon
84
+ * Sam Goldstein
85
+ * Matt Todd
data/lib/riddle/client.rb CHANGED
@@ -115,7 +115,7 @@ module Riddle
115
115
  :float_range => 2 # SPH_FILTER_FLOATRANGE
116
116
  }
117
117
 
118
- attr_accessor :server, :port, :offset, :limit, :max_matches,
118
+ attr_accessor :servers, :port, :offset, :limit, :max_matches,
119
119
  :match_mode, :sort_mode, :sort_by, :weights, :id_range, :filters,
120
120
  :group_by, :group_function, :group_clause, :group_distinct, :cut_off,
121
121
  :retry_count, :retry_delay, :anchor, :index_weights, :rank_mode,
@@ -134,11 +134,11 @@ module Riddle
134
134
  # Can instantiate with a specific server and port - otherwise it assumes
135
135
  # defaults of localhost and 3312 respectively. All other settings can be
136
136
  # accessed and changed via the attribute accessors.
137
- def initialize(server=nil, port=nil)
137
+ def initialize(servers=nil, port=nil)
138
138
  Riddle.version_warning
139
139
 
140
- @server = server || "localhost"
141
- @port = port || 9312
140
+ @servers = (servers || ["localhost"] ).to_a.shuffle
141
+ @port = port || 9312
142
142
  @socket = nil
143
143
 
144
144
  reset
@@ -177,6 +177,17 @@ module Riddle
177
177
  @select = "*"
178
178
  end
179
179
 
180
+ # The searchd server to query. Servers are removed from @server after a
181
+ # Timeout::Error is hit to allow for fail-over.
182
+ def server
183
+ @servers.first
184
+ end
185
+
186
+ # Backwards compatible writer to the @servers array.
187
+ def server=(server)
188
+ @servers = server.to_a
189
+ end
190
+
180
191
  # Set the geo-anchor point - with the names of the attributes that contain
181
192
  # the latitude and longitude (in radians), and the reference position.
182
193
  # Note that for geocoding to work properly, you must also set
@@ -475,9 +486,18 @@ module Riddle
475
486
  else
476
487
  begin
477
488
  Timeout.timeout(@timeout) { @socket = initialise_connection }
478
- rescue Timeout::Error
479
- raise Riddle::ConnectionError,
480
- "Connection to #{@server} on #{@port} timed out after #{@timeout} seconds"
489
+ rescue Timeout::Error, Riddle::ConnectionError => e
490
+ failed_servers ||= []
491
+ failed_servers << servers.shift
492
+ retry if !servers.empty?
493
+
494
+ case e
495
+ when Timeout::Error
496
+ raise Riddle::ConnectionError,
497
+ "Connection to #{failed_servers.inspect} on #{@port} timed out after #{@timeout} seconds"
498
+ else
499
+ raise e
500
+ end
481
501
  end
482
502
  end
483
503
 
@@ -499,11 +519,13 @@ module Riddle
499
519
  if @socket.nil? || @socket.closed?
500
520
  @socket = nil
501
521
  open_socket
502
- end
503
- begin
522
+ begin
523
+ yield @socket
524
+ ensure
525
+ close_socket
526
+ end
527
+ else
504
528
  yield @socket
505
- ensure
506
- close_socket
507
529
  end
508
530
  end
509
531
 
@@ -530,15 +552,15 @@ module Riddle
530
552
  self.connection.call(self)
531
553
  elsif self.class.connection
532
554
  self.class.connection.call(self)
533
- elsif @server.index('/') == 0
534
- UNIXSocket.new @server
555
+ elsif server.index('/') == 0
556
+ UNIXSocket.new server
535
557
  else
536
- TCPSocket.new @server, @port
558
+ TCPSocket.new server, @port
537
559
  end
538
560
  rescue Errno::ECONNREFUSED => e
539
561
  retry if (tries += 1) < 5
540
562
  raise Riddle::ConnectionError,
541
- "Connection to #{@server} on #{@port} failed. #{e.message}"
563
+ "Connection to #{server} on #{@port} failed. #{e.message}"
542
564
  end
543
565
 
544
566
  socket
@@ -46,9 +46,16 @@ module Riddle
46
46
 
47
47
  def stop
48
48
  return true unless running?
49
- Process.kill('SIGTERM', pid.to_i)
50
- rescue Errno::EINVAL
51
- Process.kill('SIGKILL', pid.to_i)
49
+
50
+ stop_flag = 'stopwait'
51
+ stop_flag = 'stop' if Riddle.loaded_version.split('.').first == '0'
52
+ cmd = %(#{searchd} --pidfile --config "#{@path}" --#{stop_flag})
53
+
54
+ if RUBY_PLATFORM =~ /mswin/
55
+ system("start /B #{cmd} 1> NUL 2>&1")
56
+ else
57
+ `#{cmd}`
58
+ end
52
59
  ensure
53
60
  return !running?
54
61
  end
@@ -34,11 +34,12 @@ class SphinxHelper
34
34
  structure = File.open("spec/fixtures/sql/structure.sql") { |f| f.read }
35
35
  # Block ensures multiple statement transaction is closed.
36
36
  server.query(structure) { |response| }
37
- data = File.open("spec/fixtures/sql/data.sql") { |f|
38
- while line = f.gets
39
- server.query line
40
- end
41
- }
37
+ server.query <<-QUERY
38
+ LOAD DATA LOCAL INFILE '#{@path}/fixtures/sql/data.tsv' INTO TABLE
39
+ `riddle`.`people` FIELDS TERMINATED BY ',' ENCLOSED BY "'" (gender,
40
+ first_name, middle_initial, last_name, street_address, city, state,
41
+ postcode, email, birthday)
42
+ QUERY
42
43
 
43
44
  server.close
44
45
  end
@@ -90,4 +91,4 @@ class SphinxHelper
90
91
  def running?
91
92
  pid && `ps #{pid} | wc -l`.to_i > 1
92
93
  end
93
- end
94
+ end
@@ -222,4 +222,39 @@ describe Riddle::Client do
222
222
  }.should raise_error(Riddle::ConnectionError)
223
223
  end
224
224
  end
225
+
226
+ context "connection fail over" do
227
+ it "should try each of several server addresses after timeouts" do
228
+ client = Riddle::Client.new
229
+ client.port = 3314
230
+ client.servers = %w[localhost 127.0.0.1 0.0.0.0]
231
+ client.timeout = 1
232
+
233
+ TCPSocket.should_receive(:new).with(
234
+ an_instance_of(String), 3314
235
+ ).exactly(3).and_raise Timeout::Error
236
+
237
+ lambda {
238
+ client.send(:connect) { |socket| }
239
+ }.should raise_error(Riddle::ConnectionError)
240
+ end
241
+
242
+ it "should try each of several server addresses after a connection refused" do
243
+ client = Riddle::Client.new
244
+ client.port = 3314
245
+ client.servers = %w[localhost 127.0.0.1 0.0.0.0]
246
+ client.timeout = 1
247
+
248
+ # initialise_socket will retry 5 times before failing,
249
+ # these combined with the multiple server failover should result in 15
250
+ # calls to TCPSocket.new
251
+ TCPSocket.should_receive(:new).with(
252
+ an_instance_of(String), 3314
253
+ ).exactly(3 * 5).and_raise Errno::ECONNREFUSED
254
+
255
+ lambda {
256
+ client.send(:connect) { |socket| }
257
+ }.should raise_error(Riddle::ConnectionError)
258
+ end
259
+ end
225
260
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riddle
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 1.1.0
10
+ version: 1.2.0
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: 2010-08-29 00:00:00 +09:00
18
+ date: 2010-11-15 00:00:00 +08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -116,8 +116,8 @@ homepage: http://riddle.freelancing-gods.com
116
116
  licenses: []
117
117
 
118
118
  post_install_message:
119
- rdoc_options:
120
- - --charset=UTF-8
119
+ rdoc_options: []
120
+
121
121
  require_paths:
122
122
  - lib
123
123
  required_ruby_version: !ruby/object:Gem::Requirement