rsolr 1.0.8 → 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +3 -1
- data/README.rdoc +18 -18
- data/lib/rsolr/client.rb +39 -1
- data/lib/rsolr/connection.rb +2 -0
- data/lib/rsolr/response.rb +10 -4
- data/lib/rsolr.rb +2 -2
- data/spec/api/client_spec.rb +32 -0
- data/spec/api/connection_spec.rb +21 -0
- metadata +10 -10
data/CHANGES.txt
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
1.0.8
|
2
2
|
- Fix connection refused errors in specs + add basic auth support (Denis Goeury)
|
3
|
+
- Ability to set :retry_503, the number of retry attempts for a 503 response
|
4
|
+
with a Retry-After header.
|
3
5
|
1.0.7
|
4
6
|
- Response body encoding is set to response charset in Ruby >= 1.9
|
5
7
|
- Ability to set :read_timeout and :open_timeout when creating new instance of RSolr
|
@@ -14,4 +16,4 @@
|
|
14
16
|
- Jeweler is no longer used for building the gemspec
|
15
17
|
1.0.3
|
16
18
|
- Proper encodings in Ruby 1.9
|
17
|
-
- Applied pull request from https://github.com/mwmitchell/rsolr/pull/20
|
19
|
+
- Applied pull request from https://github.com/mwmitchell/rsolr/pull/20
|
data/README.rdoc
CHANGED
@@ -36,6 +36,13 @@ The :response attribute contains the original response. This object contains the
|
|
36
36
|
The read and connect timeout settings can be set when creating a new instance of RSolr:
|
37
37
|
solr = RSolr.connect(:read_timeout => 120, :open_timeout => 120)
|
38
38
|
|
39
|
+
== Retry 503s
|
40
|
+
A 503 is usually a temporary error which RSolr may retry if requested. You may specify the number of retry attempts with the :retry_503 option.
|
41
|
+
|
42
|
+
Only requests which specify a Retry-After header will be retried, after waiting the indicated retry interval, otherwise RSolr will treat the request as a 500. You may specify a maximum Retry-After interval to wait with the :retry_after_limit option (default: one second).
|
43
|
+
solr = RSolr.connect(:retry_503 => 1, :retry_after_limit => 1)
|
44
|
+
|
45
|
+
|
39
46
|
== Querying
|
40
47
|
Use the #get / #post method to send search requests to the /select handler:
|
41
48
|
response = solr.get 'select', :params => {
|
@@ -176,27 +183,20 @@ The default response format is Ruby. When the :wt param is set to :ruby, the res
|
|
176
183
|
* Send me a pull request. Bonus points for topic branches.
|
177
184
|
|
178
185
|
==Contributors
|
179
|
-
*
|
180
|
-
* Dmitry Lihachev
|
181
|
-
* Lucas Souza
|
182
|
-
* Peter Kieltyka
|
183
|
-
* Rob Di Marco
|
186
|
+
* Nathan Witmer
|
184
187
|
* Magnus Bergmark
|
185
|
-
*
|
186
|
-
* Chris Beer
|
187
|
-
* Craig Smith
|
188
|
+
* shima
|
188
189
|
* Randy Souza
|
189
|
-
* Colin Steele
|
190
|
-
* Peter Kieltyka
|
191
|
-
* Lorenzo Riccucci
|
192
|
-
* Mike Perham
|
193
190
|
* Mat Brown
|
194
|
-
* Shairon Toledo
|
195
|
-
* Matthew Rudy
|
196
|
-
* Fouad Mardini
|
197
191
|
* Jeremy Hinegardner
|
198
|
-
*
|
199
|
-
*
|
192
|
+
* Denis Goeury
|
193
|
+
* shairon toledo
|
194
|
+
* Rob Di Marco
|
195
|
+
* Peter Kieltyka
|
196
|
+
* Mike Perham
|
197
|
+
* Lucas Souza
|
198
|
+
* Dmitry Lihachev
|
199
|
+
* Antoine Latter
|
200
200
|
|
201
201
|
==Author
|
202
202
|
|
@@ -204,4 +204,4 @@ Matt Mitchell <mailto:goodieboy@gmail.com>
|
|
204
204
|
|
205
205
|
==Copyright
|
206
206
|
|
207
|
-
Copyright (c) 2008-2010 Matt Mitchell. See LICENSE for details.
|
207
|
+
Copyright (c) 2008-2010 Matt Mitchell. See LICENSE for details.
|
data/lib/rsolr/client.rb
CHANGED
@@ -155,7 +155,7 @@ class RSolr::Client
|
|
155
155
|
# then passes the request/response into +adapt_response+.
|
156
156
|
def send_and_receive path, opts
|
157
157
|
request_context = build_request path, opts
|
158
|
-
[:open_timeout, :read_timeout].each do |k|
|
158
|
+
[:open_timeout, :read_timeout, :retry_503, :retry_after_limit].each do |k|
|
159
159
|
request_context[k] = @options[k]
|
160
160
|
end
|
161
161
|
execute request_context
|
@@ -163,9 +163,47 @@ class RSolr::Client
|
|
163
163
|
|
164
164
|
#
|
165
165
|
def execute request_context
|
166
|
+
|
166
167
|
raw_response = connection.execute self, request_context
|
168
|
+
|
169
|
+
while retry_503?(request_context, raw_response)
|
170
|
+
request_context[:retry_503] -= 1
|
171
|
+
sleep retry_after(raw_response)
|
172
|
+
raw_response = connection.execute self, request_context
|
173
|
+
end
|
174
|
+
|
167
175
|
adapt_response(request_context, raw_response) unless raw_response.nil?
|
168
176
|
end
|
177
|
+
|
178
|
+
def retry_503?(request_context, response)
|
179
|
+
return false if response.nil?
|
180
|
+
status = response[:status] && response[:status].to_i
|
181
|
+
return false unless status == 503
|
182
|
+
retry_503 = request_context[:retry_503]
|
183
|
+
return false unless retry_503 && retry_503 > 0
|
184
|
+
retry_after_limit = request_context[:retry_after_limit] || 1
|
185
|
+
retry_after = retry_after(response)
|
186
|
+
return false unless retry_after && retry_after <= retry_after_limit
|
187
|
+
true
|
188
|
+
end
|
189
|
+
|
190
|
+
# Retry-After can be a relative number of seconds from now, or an RFC 1123 Date.
|
191
|
+
# If the latter, attempt to convert it to a relative time in seconds.
|
192
|
+
def retry_after(response)
|
193
|
+
retry_after = Array(response[:headers]['Retry-After'] || response[:headers]['retry-after']).flatten.first.to_s
|
194
|
+
if retry_after =~ /\A[0-9]+\Z/
|
195
|
+
retry_after = retry_after.to_i
|
196
|
+
else
|
197
|
+
begin
|
198
|
+
retry_after_date = DateTime.parse(retry_after)
|
199
|
+
retry_after = retry_after_date.to_time - Time.now
|
200
|
+
retry_after = nil if retry_after < 0
|
201
|
+
rescue ArgumentError => e
|
202
|
+
retry_after = retry_after.to_i
|
203
|
+
end
|
204
|
+
end
|
205
|
+
retry_after
|
206
|
+
end
|
169
207
|
|
170
208
|
# +build_request+ accepts a path and options hash,
|
171
209
|
# then prepares a normalized hash to return for sending
|
data/lib/rsolr/connection.rb
CHANGED
@@ -15,6 +15,8 @@ class RSolr::Connection
|
|
15
15
|
response = h.request request
|
16
16
|
charset = response.type_params["charset"]
|
17
17
|
{:status => response.code.to_i, :headers => response.to_hash, :body => force_charset(response.body, charset)}
|
18
|
+
rescue Errno::ECONNREFUSED => e
|
19
|
+
raise(Errno::ECONNREFUSED.new(request_context.inspect))
|
18
20
|
# catch the undefined closed? exception -- this is a confirmed ruby bug
|
19
21
|
rescue NoMethodError
|
20
22
|
$!.message == "undefined method `closed?' for nil:NilClass" ?
|
data/lib/rsolr/response.rb
CHANGED
@@ -5,8 +5,8 @@ module RSolr::Response
|
|
5
5
|
base["response"]["docs"].tap do |d|
|
6
6
|
d.extend PaginatedDocSet
|
7
7
|
d.per_page = base.request[:params]["rows"]
|
8
|
-
d.
|
9
|
-
d.
|
8
|
+
d.page_start = base.request[:params]["start"]
|
9
|
+
d.page_total = base["response"]["numFound"].to_s.to_i
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -14,7 +14,13 @@ module RSolr::Response
|
|
14
14
|
# A response module which gets mixed into the solr ["response"]["docs"] array.
|
15
15
|
module PaginatedDocSet
|
16
16
|
|
17
|
-
attr_accessor :
|
17
|
+
attr_accessor :page_start, :per_page, :page_total
|
18
|
+
if not (Object.const_defined?("RUBY_ENGINE") and Object::RUBY_ENGINE=='rbx')
|
19
|
+
alias_method(:start,:page_start)
|
20
|
+
alias_method(:start=,:page_start=)
|
21
|
+
alias_method(:total,:page_total)
|
22
|
+
alias_method(:total=,:page_total=)
|
23
|
+
end
|
18
24
|
|
19
25
|
# Returns the current page calculated from 'rows' and 'start'
|
20
26
|
def current_page
|
@@ -48,4 +54,4 @@ module RSolr::Response
|
|
48
54
|
|
49
55
|
end
|
50
56
|
|
51
|
-
end
|
57
|
+
end
|
data/lib/rsolr.rb
CHANGED
@@ -6,7 +6,7 @@ module RSolr
|
|
6
6
|
|
7
7
|
%W(Response Char Client Error Connection Uri Xml).each{|n|autoload n.to_sym, "rsolr/#{n.downcase}"}
|
8
8
|
|
9
|
-
def self.version; "1.0.
|
9
|
+
def self.version; "1.0.9" end
|
10
10
|
|
11
11
|
VERSION = self.version
|
12
12
|
|
@@ -19,4 +19,4 @@ module RSolr
|
|
19
19
|
# RSolr.escape
|
20
20
|
extend Char
|
21
21
|
|
22
|
-
end
|
22
|
+
end
|
data/spec/api/client_spec.rb
CHANGED
@@ -34,6 +34,38 @@ describe "RSolr::Client" do
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
context "execute" do
|
38
|
+
include ClientHelper
|
39
|
+
let :request_context do
|
40
|
+
{
|
41
|
+
:method => :post,
|
42
|
+
:params => {},
|
43
|
+
:data => nil,
|
44
|
+
:headers => {},
|
45
|
+
:path => '',
|
46
|
+
:uri => client.base_uri,
|
47
|
+
:retry_503 => 1
|
48
|
+
}
|
49
|
+
end
|
50
|
+
it "should retry 503s if requested" do
|
51
|
+
client.connection.should_receive(:execute).exactly(2).times.and_return(
|
52
|
+
{:status => 503, :body => "{}", :headers => {'Retry-After' => 0}},
|
53
|
+
{:status => 200, :body => "{}", :headers => {}}
|
54
|
+
)
|
55
|
+
client.execute request_context
|
56
|
+
end
|
57
|
+
it "should not retry a 503 if the retry-after is too large" do
|
58
|
+
client.connection.should_receive(:execute).exactly(1).times.and_return(
|
59
|
+
{:status => 503, :body => "{}", :headers => {'Retry-After' => 10}}
|
60
|
+
)
|
61
|
+
lambda {
|
62
|
+
Timeout.timeout(0.5) do
|
63
|
+
client.execute({:retry_after_limit => 0}.merge(request_context))
|
64
|
+
end
|
65
|
+
}.should raise_error(RSolr::Error::Http)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
37
69
|
context "post" do
|
38
70
|
include ClientHelper
|
39
71
|
it "should pass the expected params to the connection's #execute method" do
|
data/spec/api/connection_spec.rb
CHANGED
@@ -57,6 +57,27 @@ describe "RSolr::Connection" do
|
|
57
57
|
subject.execute client, {:uri => URI.parse("http://localhost/some_uri"), :method => :get}
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
context "connection refused" do
|
62
|
+
let(:client) { mock.as_null_object }
|
63
|
+
|
64
|
+
let(:http) { mock(Net::HTTP).as_null_object }
|
65
|
+
let(:request_context) {
|
66
|
+
{:uri => URI.parse("http://localhost/some_uri"), :method => :get, :open_timeout => 42}
|
67
|
+
}
|
68
|
+
subject { RSolr::Connection.new }
|
69
|
+
|
70
|
+
before do
|
71
|
+
Net::HTTP.stub(:new) { http }
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should configure Net:HTTP open_timeout" do
|
75
|
+
http.should_receive(:request).and_raise(Errno::ECONNREFUSED)
|
76
|
+
lambda {
|
77
|
+
subject.execute client, request_context
|
78
|
+
}.should raise_error(Errno::ECONNREFUSED, /#{request_context}/)
|
79
|
+
end
|
80
|
+
end
|
60
81
|
|
61
82
|
describe "basic auth support" do
|
62
83
|
let(:http) { mock(Net::HTTP).as_null_object }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsolr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -29,11 +29,11 @@ authors:
|
|
29
29
|
autorequire:
|
30
30
|
bindir: bin
|
31
31
|
cert_chain: []
|
32
|
-
date:
|
32
|
+
date: 2013-03-29 00:00:00.000000000Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: builder
|
36
|
-
requirement: &
|
36
|
+
requirement: &70317957140320 !ruby/object:Gem::Requirement
|
37
37
|
none: false
|
38
38
|
requirements:
|
39
39
|
- - ! '>='
|
@@ -41,10 +41,10 @@ dependencies:
|
|
41
41
|
version: 2.1.2
|
42
42
|
type: :runtime
|
43
43
|
prerelease: false
|
44
|
-
version_requirements: *
|
44
|
+
version_requirements: *70317957140320
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: rake
|
47
|
-
requirement: &
|
47
|
+
requirement: &70317957139580 !ruby/object:Gem::Requirement
|
48
48
|
none: false
|
49
49
|
requirements:
|
50
50
|
- - ~>
|
@@ -52,10 +52,10 @@ dependencies:
|
|
52
52
|
version: 0.9.2
|
53
53
|
type: :development
|
54
54
|
prerelease: false
|
55
|
-
version_requirements: *
|
55
|
+
version_requirements: *70317957139580
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rdoc
|
58
|
-
requirement: &
|
58
|
+
requirement: &70317957138980 !ruby/object:Gem::Requirement
|
59
59
|
none: false
|
60
60
|
requirements:
|
61
61
|
- - ~>
|
@@ -63,10 +63,10 @@ dependencies:
|
|
63
63
|
version: 3.9.4
|
64
64
|
type: :development
|
65
65
|
prerelease: false
|
66
|
-
version_requirements: *
|
66
|
+
version_requirements: *70317957138980
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: rspec
|
69
|
-
requirement: &
|
69
|
+
requirement: &70317957138400 !ruby/object:Gem::Requirement
|
70
70
|
none: false
|
71
71
|
requirements:
|
72
72
|
- - ~>
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
version: 2.6.0
|
75
75
|
type: :development
|
76
76
|
prerelease: false
|
77
|
-
version_requirements: *
|
77
|
+
version_requirements: *70317957138400
|
78
78
|
description: RSolr aims to provide a simple and extensible library for working with
|
79
79
|
Solr
|
80
80
|
email:
|