rlivsey-voorhees 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -69,6 +69,16 @@ These cannot be globally set and can only be defined on individual services/requ
69
69
  * path: Path to the service. Can be relative if you have a base_uri set.
70
70
  * required: Array of required parameters. Raises a Voorhees::ParameterMissingError if a required parameter is not set.
71
71
 
72
+ ### Timeouts and Retries
73
+
74
+ As well as setting the open_timeout/read_timeout of Net::HTTP, we also wrap each request in a timeout check.
75
+
76
+ If [SystemTimer](http://ph7spot.com/articles/system_timer) is installed it will use this, otherwise it falls back on the Timeout library.
77
+
78
+ If the request fails with a Timeout::Error, or a Errno::ECONNREFUSED, we attept the request again upto the number of retries specified.
79
+
80
+ For Errno::ECONNREFUSED errors, we also sleep for 1 second to give the service a chance to wake up.
81
+
72
82
  ### Services and Requests
73
83
 
74
84
  There are 3 ways to communicate with the service.
@@ -197,6 +207,12 @@ With that we can now do:
197
207
  users[0].name => "Bobby Tables"
198
208
  users[0].address.country => "Somewhere"
199
209
  users[0].address.coords.lat => 52.9876
210
+
211
+ ### Requirements
212
+
213
+ * A JSON library which supports JSON.parse
214
+ * ActiveSupport
215
+ * SystemTimer - falls back on Timer if it's not available
200
216
 
201
217
  ## Thanks
202
218
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
@@ -14,7 +14,8 @@ module Voorhees
14
14
  :logger => defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : Logger.new(STDOUT),
15
15
  :timeout => 10,
16
16
  :retries => 0,
17
- :http_method => Net::HTTP::Get
17
+ :http_method => Net::HTTP::Get,
18
+ :response_class => Voorhees::Response
18
19
  }
19
20
  end
20
21
 
@@ -0,0 +1,5 @@
1
+ module Voorhees
2
+ def self.debug(message)
3
+ Voorhees::Config[:logger].debug("VOORHEES: #{message}")
4
+ end
5
+ end
@@ -1,6 +1,14 @@
1
1
  require 'uri'
2
2
  require 'net/http'
3
3
 
4
+ begin
5
+ require 'system_timer'
6
+ VoorheesTimer = SystemTimer
7
+ rescue LoadError
8
+ require 'timeout'
9
+ VoorheesTimer = Timeout
10
+ end
11
+
4
12
  module Voorhees
5
13
 
6
14
  class Request
@@ -66,42 +74,47 @@ module Voorhees
66
74
  parameters
67
75
  end
68
76
 
69
- @http.open_timeout = timeout || Voorhees::Config[:timeout]
70
- @http.read_timeout = timeout || Voorhees::Config[:timeout]
77
+ @http.open_timeout = timeout
78
+ @http.read_timeout = timeout
71
79
  end
72
80
 
73
81
  def perform_actual_request
74
-
75
82
  retries_left = retries
76
83
 
84
+ Voorhees.debug("Performing #{http_method} request for #{uri.to_s}")
85
+
77
86
  begin
78
87
  retries_left -= 1
79
88
 
80
- response = @http.start do |connection|
81
- connection.request(@req)
82
- end
89
+ response = VoorheesTimer.timeout(timeout) do
90
+ @http.start do |connection|
91
+ connection.request(@req)
92
+ end
93
+ end
83
94
 
84
95
  rescue Timeout::Error
85
96
  if retries_left >= 0
86
- Voorhees::Config.logger.debug("Retrying due to Timeout::Error (#{uri.to_s})")
97
+ Voorhees.debug("Retrying due to Timeout::Error (#{uri.to_s})")
87
98
  retry
88
99
  end
89
100
 
101
+ Voorhees.debug("Request failed due to Timeout::Error (#{uri.to_s})")
90
102
  raise Voorhees::TimeoutError.new
91
103
 
92
104
  rescue Errno::ECONNREFUSED
93
105
  if retries_left >= 0
94
- Voorhees::Config.logger.debug("Retrying due to Errno::ECONNREFUSED (#{uri.to_s})")
106
+ Voorhees.debug("Retrying due to Errno::ECONNREFUSED (#{uri.to_s})")
95
107
  sleep(1)
96
108
  retry
97
109
  end
98
110
 
111
+ Voorhees.debug("Request failed due to Errno::ECONREFUSED (#{uri.to_s})")
99
112
  raise Voorhees::UnavailableError.new
100
113
 
101
114
  end
102
115
 
103
116
  if response.is_a?(Net::HTTPNotFound)
104
- Voorhees::Config.logger.error("Service Not Found (#{uri.to_s})")
117
+ Voorhees.debug("Request failed due to Net::HTTPNotFound (#{uri.to_s})")
105
118
  raise Voorhees::NotFoundError.new
106
119
  end
107
120
 
@@ -117,8 +130,9 @@ module Voorhees
117
130
  end
118
131
 
119
132
  def parse_response(response)
120
- Voorhees::Response.new(JSON.parse(response.body), @caller_class, @hierarchy)
133
+ Voorhees::Config[:response_class].new(JSON.parse(response.body), @caller_class, @hierarchy)
121
134
  rescue JSON::ParserError
135
+ Voorhees.debug("Parsing JSON failed.\nFirst 500 chars of body:\n#{response.body[0...500]}")
122
136
  raise Voorhees::ParseError
123
137
  end
124
138
 
@@ -8,6 +8,7 @@ module Voorhees
8
8
 
9
9
  base.instance_eval do
10
10
  attr_accessor :raw_json, :json_hierarchy
11
+ undef_method :id
11
12
  end
12
13
  end
13
14
 
@@ -44,7 +45,7 @@ module Voorhees
44
45
  module InstanceMethods
45
46
 
46
47
  def json_attributes
47
- @json_attributes ||= @raw_json.keys.collect{|x| x.to_sym}
48
+ @json_attributes ||= @raw_json.keys.collect{|x| x.underscore.to_sym}
48
49
  end
49
50
 
50
51
  def json_request(klass=nil)
@@ -55,7 +56,6 @@ module Voorhees
55
56
 
56
57
  def method_missing(*args)
57
58
  method_name = args[0]
58
-
59
59
  if json_attributes.include?(method_name)
60
60
  value = value_from_json(method_name)
61
61
  build_methods(method_name, value)
@@ -70,7 +70,7 @@ module Voorhees
70
70
  private
71
71
 
72
72
  def value_from_json(method_name)
73
- item = raw_json[method_name.to_s]
73
+ item = raw_json[method_name.to_s] || raw_json[method_name.to_s.camelize(:lower)]
74
74
 
75
75
  sub_hierarchy = nil
76
76
  if json_hierarchy && hierarchy = json_hierarchy[method_name]
data/lib/voorhees.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "voorhees/logging"
1
2
  require "voorhees/config"
2
3
  require "voorhees/exceptions"
3
4
  require "voorhees/request"
@@ -12,6 +12,7 @@
12
12
  "lon":12.3456
13
13
  }
14
14
  },
15
+ "camelCase":"camel",
15
16
  "pet":{
16
17
  "kind":"dog",
17
18
  "name":"spot"
data/spec/request_spec.rb CHANGED
@@ -284,7 +284,7 @@ describe Voorhees::Request do
284
284
 
285
285
  describe "with TimeoutError" do
286
286
 
287
- it "should raise a Voorhees::TimeoutError" do
287
+ it "should raise a Voorhees::TimeoutError when Timeout::Error is from connection" do
288
288
  @connection.stub!(:request).and_raise(Timeout::Error.new(nil))
289
289
 
290
290
  lambda{
@@ -292,6 +292,14 @@ describe Voorhees::Request do
292
292
  }.should raise_error(Voorhees::TimeoutError)
293
293
  end
294
294
 
295
+ it "should raise a Voorhees::TimeoutError when Timeout::Error is from VoorheesTimer" do
296
+ VoorheesTimer.stub!(:timeout).and_raise(Timeout::Error.new(nil))
297
+
298
+ lambda{
299
+ @request.perform
300
+ }.should raise_error(Voorhees::TimeoutError)
301
+ end
302
+
295
303
  describe "with retries" do
296
304
 
297
305
  before :each do
@@ -153,8 +153,8 @@ describe User do
153
153
  end
154
154
 
155
155
  describe "#json_attributes" do
156
- it "should contain symbols of the keys of the attributes available" do
157
- user_from_json.json_attributes.sort.should == [:address, :email, :id, :messages, :name, :pet, :username]
156
+ it "should contain symbols of the keys of the attributes available as underscored" do
157
+ user_from_json.json_attributes.sort.should == [:address, :camel_case, :email, :id, :messages, :name, :pet, :username]
158
158
  end
159
159
  end
160
160
 
@@ -216,6 +216,11 @@ describe User do
216
216
 
217
217
  describe "calling method with the name of a json attribute" do
218
218
 
219
+ it "should return the correct data from #id" do
220
+ user = user_from_json
221
+ user.id.should == @json["id"]
222
+ end
223
+
219
224
  it "should define a method of the same name" do
220
225
  user = user_from_json
221
226
 
@@ -237,6 +242,12 @@ describe User do
237
242
  end
238
243
  end
239
244
 
245
+ describe "which is camelCase in the JSON" do
246
+ it "should return the value of the attribute" do
247
+ user_from_json.camel_case.should == @json["camelCase"]
248
+ end
249
+ end
250
+
240
251
  describe "which is a collection" do
241
252
  it "should return an array" do
242
253
  user_from_json.messages.should be_an_instance_of(Array)
data/voorhees.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{voorhees}
5
- s.version = "0.1.3"
5
+ s.version = "0.1.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Richard Livsey"]
9
- s.date = %q{2009-06-21}
9
+ s.date = %q{2009-06-24}
10
10
  s.email = %q{richard@livsey.org}
11
11
  s.extra_rdoc_files = [
12
12
  "LICENSE",
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  "lib/voorhees.rb",
23
23
  "lib/voorhees/config.rb",
24
24
  "lib/voorhees/exceptions.rb",
25
+ "lib/voorhees/logging.rb",
25
26
  "lib/voorhees/request.rb",
26
27
  "lib/voorhees/resource.rb",
27
28
  "lib/voorhees/response.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rlivsey-voorhees
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Livsey
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-21 00:00:00 -07:00
12
+ date: 2009-06-24 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -32,6 +32,7 @@ files:
32
32
  - lib/voorhees.rb
33
33
  - lib/voorhees/config.rb
34
34
  - lib/voorhees/exceptions.rb
35
+ - lib/voorhees/logging.rb
35
36
  - lib/voorhees/request.rb
36
37
  - lib/voorhees/resource.rb
37
38
  - lib/voorhees/response.rb