loquor 1.11.0 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MWVhNDZhNjQ2NGIyZTczNGFlZmYxN2Y1ZWZiZWQ5NWFhODg2M2MxNA==
4
+ NDMwODdkODY4NWMwY2ViZjkzOGE4MTczNTU1MGYwYjFiOTMwNmI2Mg==
5
5
  data.tar.gz: !binary |-
6
- ZTY0ODIyNWJhYzFlYWNjNzMwZWQ4MzAxNzg4YWVlNGM1MjYxMDJmOQ==
6
+ YTczMjQwNDQ1ZTdiZThkOTE2YWYyNWEzNTIyZDA3Zjc4ZTZiNDgxNA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MDZiM2JkMGY5NzgxNmJmM2RlODc1YmI1MjhiN2MyYWEzNzE3M2RmZmMyZTMx
10
- Y2Q3MjcyZDA3MzUzZTRhY2E3OTZlMjBiMjhiMjI1MDFjNjJmOTVhNmY4NGU0
11
- YzNlZWY4ZTBkMzc3NjBhNTQ4MjNhOGRiMmY0M2ViY2IyMzIyNjA=
9
+ ODdmZDYyYTJlY2MwMGMzN2YxZjNmZTlkMjQ4OWMxNTI2ZWNhODI4NzI4MDQ3
10
+ MjlmMTdhNGIyNmU5YTZiMTZjMjNiNThkYzBkYTkzYTliN2RiNTkxNzQ1NmJi
11
+ ZjZkNmEyZmI3NTczZWUwMDBmYjViOWY0YjRjMWU4OGUwNTE0YmU=
12
12
  data.tar.gz: !binary |-
13
- ZTY1ODFmYWQ2N2Q3OWFmZDNhYjc1ODkzN2FkZmQ0ZjRkYjJjMDZjNWRjYTcw
14
- ZTdiNDYzOGI0MWZmMWZkZTViODVjNDAwZDZjZWZjMTVjYTA5OTY1OGUxYWRi
15
- ZTg1NDk2OWRhZTk2MWI4ZjU2NmU5ZGM1MzU1NzM5ZTg3ZDliZTU=
13
+ ZGMyOTNhOWFkZjNlYTU1ODY4NzgyYTZkYTc4YzU5ODk1MjA1Y2Q3MjRiNGU4
14
+ ZTU3MjIwNWZkNDk1MWQ5ZDQyZWRlYWViZTVjNDA3YWRmOWQ1NGYwNWQyM2Ji
15
+ ZDA0ZWY5ZTRlMmVkZjJiMTRkYzczZTg0MDBjMTFmMzEzYTkxYzE=
@@ -1,3 +1,6 @@
1
+ # 1.12.0 / 2014-05-06
2
+ * [FEATURE] Retry support for HTTP 503 status
3
+
1
4
  # 1.11.0 / 2014-05-06
2
5
  * [FEATURE] Set user-agent to same value as access_id
3
6
 
@@ -7,7 +7,7 @@ module Loquor
7
7
  class Configuration
8
8
 
9
9
  SETTINGS = [
10
- :logger, :access_id, :secret_key, :endpoint, :substitute_values, :retry_404s
10
+ :logger, :access_id, :secret_key, :endpoint, :substitute_values, :retry_404s, :retry_503s, :max_retries, :retry_backoff
11
11
  ]
12
12
 
13
13
  attr_writer *SETTINGS
@@ -17,6 +17,9 @@ module Loquor
17
17
  self.logger = Filum.logger
18
18
  self.substitute_values = {}
19
19
  self.retry_404s = false
20
+ self.retry_503s = true
21
+ self.max_retries = 5
22
+ self.retry_backoff = 2
20
23
  end
21
24
 
22
25
  SETTINGS.each do |setting|
@@ -1,15 +1,18 @@
1
+ require 'rest-client'
2
+
1
3
  module Loquor
2
4
  class HttpAction
3
5
  def initialize(url, deps)
4
6
  @url = url
5
7
  @config = deps[:config]
6
8
  @should_cache = deps[:should_cache]
9
+ @retry_count = 0
7
10
  end
8
11
 
9
12
  def signed_request
10
13
  req = request
11
14
  @config.logger.info "Setting user-agent."
12
- req.headers['User-Agent'] = @config.access_id
15
+ req.headers['User-Agent'] = user_agent
13
16
  @config.logger.info "Signing request."
14
17
  ApiAuth.sign!(req, @config.access_id, @config.secret_key)
15
18
  end
@@ -17,6 +20,17 @@ module Loquor
17
20
  def execute
18
21
  @config.logger.info "Making HTTP request to: #{full_url}"
19
22
  signed_request.execute
23
+ rescue RestClient::ServiceUnavailable => e
24
+ @config.logger.error("503 received for request to #{@url}.")
25
+ @retry_count += 1
26
+ if should_retry
27
+ @config.logger.error("Retrying (retry attempt #{@retry_count})")
28
+ back_off(@config.retry_backoff ** @retry_count)
29
+ retry
30
+ else
31
+ @config.logger.error("Abandoning request (service unavailable)")
32
+ raise e
33
+ end
20
34
  rescue RestClient::ResourceNotFound => e
21
35
  @config.logger.error("HTTP 404 when accessing #{full_url}")
22
36
  raise
@@ -25,11 +39,23 @@ module Loquor
25
39
  raise
26
40
  end
27
41
 
42
+ def back_off(delay)
43
+ sleep(delay)
44
+ end
45
+
28
46
  private
29
47
 
48
+ def should_retry
49
+ @config.retry_503s && @retry_count < @config.max_retries
50
+ end
51
+
30
52
  def full_url
31
53
  "#{@config.endpoint}#{@url}"
32
54
  end
55
+
56
+ def user_agent
57
+ "Loquor-#{VERSION}/#{@config.access_id}"
58
+ end
33
59
  end
34
60
  end
35
61
 
@@ -1,3 +1,3 @@
1
1
  module Loquor
2
- VERSION = "1.11.0"
2
+ VERSION = "1.12.0"
3
3
  end
@@ -11,6 +11,7 @@ module Loquor
11
11
  def deps
12
12
  logger = mock()
13
13
  logger.stubs(info: nil)
14
+ logger.stubs(error: nil)
14
15
 
15
16
  config = mock()
16
17
  config.stubs(logger: logger)
@@ -18,6 +19,9 @@ module Loquor
18
19
  config.stubs(secret_key: @secret_key)
19
20
  config.stubs(endpoint: @endpoint)
20
21
  config.stubs(cache: @cache)
22
+ config.stubs(retry_backoff: 2)
23
+ config.stubs(max_retries: 5)
24
+ config.stubs(retry_503s: true)
21
25
  {config: config}
22
26
  end
23
27
 
@@ -27,5 +31,89 @@ module Loquor
27
31
  action.expects(signed_request: mock(execute: json))
28
32
  assert_equal json, action.send(:execute)
29
33
  end
34
+
35
+ def test_execute_retries_on_503
36
+ json = "{}"
37
+
38
+ r = mock()
39
+ r.stubs(:execute).raises(RestClient::ServiceUnavailable.new)
40
+ .then.raises(RestClient::ServiceUnavailable.new).then.returns(json)
41
+
42
+ action = HttpAction.new("", deps)
43
+ action.expects(signed_request: r).times(3)
44
+ action.expects(:back_off).with(2)
45
+ action.expects(:back_off).with(4)
46
+
47
+ assert_equal json, action.send(:execute)
48
+ end
49
+
50
+ def test_disable_503_retries
51
+ my_deps = deps
52
+ my_deps[:config].stubs(retry_503s: false)
53
+
54
+ r = mock()
55
+ r.stubs(:execute).raises(RestClient::ServiceUnavailable.new)
56
+
57
+ action = HttpAction.new("", my_deps)
58
+ action.expects(signed_request: r)
59
+
60
+ assert_raises RestClient::ServiceUnavailable do
61
+ action.send(:execute)
62
+ end
63
+ end
64
+
65
+ def test_execute_rethrows_503_when_retry_count_exceeded
66
+ r = mock()
67
+ r.stubs(:execute).raises(RestClient::ServiceUnavailable.new).times(5)
68
+
69
+ action = HttpAction.new("", deps)
70
+ action.expects(signed_request: r).times(5)
71
+ action.expects(:back_off).with(2)
72
+ action.expects(:back_off).with(4)
73
+ action.expects(:back_off).with(8)
74
+ action.expects(:back_off).with(16)
75
+
76
+ assert_raises RestClient::ServiceUnavailable do
77
+ action.send(:execute)
78
+ end
79
+ end
80
+
81
+ def test_execute_rethrows_503_with_configurable_backoff_and_max_retries
82
+ my_deps = deps
83
+ my_deps[:config].stubs(retry_backoff: 3)
84
+ my_deps[:config].stubs(max_retries: 4)
85
+
86
+ r = mock()
87
+ r.stubs(:execute).raises(RestClient::ServiceUnavailable.new).times(4)
88
+
89
+ action = HttpAction.new("", my_deps)
90
+ action.expects(signed_request: r).times(4)
91
+ action.expects(:back_off).with(3)
92
+ action.expects(:back_off).with(9)
93
+ action.expects(:back_off).with(27)
94
+
95
+ assert_raises RestClient::ServiceUnavailable do
96
+ action.send(:execute)
97
+ end
98
+ end
99
+
100
+ def test_execute_rethrows_404
101
+ err = RestClient::ResourceNotFound.new
102
+
103
+ r = mock()
104
+ r.stubs(:execute).raises(err)
105
+
106
+ action = HttpAction.new("", deps)
107
+ action.expects(signed_request: r)
108
+
109
+ assert_raises RestClient::ResourceNotFound do
110
+ action.send(:execute)
111
+ end
112
+ end
113
+
114
+ def test_user_agent
115
+ action = HttpAction.new("", deps)
116
+ assert /Loquor-\d+.\d+.\d+\/123/.match(action.send(:user_agent))
117
+ end
30
118
  end
31
119
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loquor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.0
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Walker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-06 00:00:00.000000000 Z
11
+ date: 2014-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: filum