loquor 1.11.0 → 1.12.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.
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