record_store 6.3.0 → 6.3.1

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,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6476b30f3ef1df05642b1645783e2186e8ca6a3f489d99c4724fb252d6b26b97
4
- data.tar.gz: 84ddb2d0e34076198bc1df633ab51714253c8c4ced05ef8b5b60eb777714eacb
3
+ metadata.gz: f6875c27f0cf86510b733a58f668d44560eeb40e7c8b6c9438183fee175bc514
4
+ data.tar.gz: 3599cc9903a5afe46d544f8aeef349961fdc2d95011973325bbdcc75972c56c5
5
5
  SHA512:
6
- metadata.gz: '01136420252835b0ce65abf03d0466f88f879cf52c55f1db5e3db0753121bd55610c78fec31ee552b0d95c02b1922e8aefd4d91679872b1f16af16188fff0cde'
7
- data.tar.gz: 512eb4f464314c298c07367e52dc9a3e6cec126da174f19c52cd4d32c12be7ab1d1a565c653b6f853a346582db9076e078ee530914272c1fbf6317306c911176
6
+ metadata.gz: 9a6def9342919457cc71fdda4691c92310450dfc28a476eee6d353b73798b8d1b612b4775982704b0c44b2e657149a02f0e96330796b03d591619ad5930509ae
7
+ data.tar.gz: 42183ae0ecd31e27a2d40977ecdda6cb51c0368ff24ac3a2de4411ab016809c5551ee3faeb50eb53503be059ece4bc41889e6c73d3e1f0ab53e7ab9290563628
@@ -1,5 +1,8 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 6.3.1
4
+ - Improve resiliency in the face of temporary provider outages [BUGFIX]
5
+
3
6
  ## 6.3.0
4
7
  - Support for configurable number of threads via environment variable [FEATURE]
5
8
 
@@ -2,6 +2,9 @@ require 'resolv'
2
2
 
3
3
  module RecordStore
4
4
  class Provider
5
+ class Error < StandardError; end
6
+ class UnparseableBodyError < Error; end
7
+
5
8
  class << self
6
9
  def provider_for(object)
7
10
  ns_server =
@@ -136,12 +139,13 @@ module RecordStore
136
139
  def retry_on_connection_errors(
137
140
  max_timeouts: 5,
138
141
  max_conn_resets: 5,
142
+ max_retries: 5,
139
143
  delay: 1,
140
144
  backoff_multiplier: 2,
141
145
  max_backoff: 10
142
146
  )
143
147
  waiter = BackoffWaiter.new(
144
- "Waiting to retry after a connection reset",
148
+ 'Waiting to retry after a connection reset',
145
149
  initial_delay: delay,
146
150
  multiplier: backoff_multiplier,
147
151
  max_delay: max_backoff,
@@ -150,11 +154,16 @@ module RecordStore
150
154
  loop do
151
155
  begin
152
156
  return yield
157
+ rescue UnparseableBodyError
158
+ raise if max_retries <= 0
159
+ max_retries -= 1
160
+
161
+ waiter.wait(message: 'Waiting to retry after receiving an unparseable response')
153
162
  rescue Net::OpenTimeout, Errno::ETIMEDOUT
154
163
  raise if max_timeouts <= 0
155
164
  max_timeouts -= 1
156
165
 
157
- $stderr.puts("Retrying after a connection timeout")
166
+ $stderr.puts('Retrying after a connection timeout')
158
167
  rescue Errno::ECONNRESET
159
168
  raise if max_conn_resets <= 0
160
169
  max_conn_resets -= 1
@@ -3,8 +3,6 @@ require_relative 'ns1/patch_api_header'
3
3
 
4
4
  module RecordStore
5
5
  class Provider::NS1 < Provider
6
- class Error < StandardError; end
7
-
8
6
  class ApiAnswer
9
7
  class << self
10
8
  def from_full_api_answer(type:, record_id:, answer:)
@@ -180,7 +178,7 @@ module RecordStore
180
178
  unless updated
181
179
  error = +'while trying to update a record, could not find answer with fqdn: '
182
180
  error << "#{record.fqdn}, type; #{record.type}, id: #{id}"
183
- raise Error, error
181
+ raise RecordStore::Provider::Error, error
184
182
  end
185
183
 
186
184
  client.modify_record(
@@ -1,46 +1,59 @@
1
+ require 'net/http'
1
2
  require 'ns1'
2
3
 
3
4
  module RecordStore
4
5
  class Provider::NS1 < Provider
5
- class Error < StandardError; end
6
-
7
6
  class Client < ::NS1::Client
8
7
  def initialize(api_key:)
9
8
  super(api_key)
10
9
  end
11
10
 
12
11
  def zones
13
- super
12
+ zones = super
13
+ raise_if_error!(zones)
14
+ zones
14
15
  end
15
16
 
16
17
  def zone(name)
17
- super(name)
18
+ zone = super(name)
19
+ raise_if_error!(zone)
20
+ zone
18
21
  end
19
22
 
20
23
  def record(zone:, fqdn:, type:, must_exist: false)
21
24
  result = super(zone, fqdn, type)
22
- raise(Error, result.to_s) if must_exist && result.is_a?(NS1::Response::Error)
25
+ raise_if_error!(result) if must_exist
23
26
  return nil if result.is_a?(NS1::Response::Error)
24
27
  result
25
28
  end
26
29
 
27
30
  def create_record(zone:, fqdn:, type:, params:)
28
31
  result = super(zone, fqdn, type, params)
29
- raise(Error, result.to_s) if result.is_a?(NS1::Response::Error)
32
+ raise_if_error!(result)
30
33
  nil
31
34
  end
32
35
 
33
36
  def modify_record(zone:, fqdn:, type:, params:)
34
37
  result = super(zone, fqdn, type, params)
35
- raise(Error, result.to_s) if result.is_a?(NS1::Response::Error)
38
+ raise_if_error!(result)
36
39
  nil
37
40
  end
38
41
 
39
42
  def delete_record(zone:, fqdn:, type:)
40
43
  result = super(zone, fqdn, type)
41
- raise(Error, result.to_s) if result.is_a?(NS1::Response::Error)
44
+ raise_if_error!(result)
42
45
  nil
43
46
  end
47
+
48
+ private
49
+
50
+ def raise_if_error!(result)
51
+ return unless result.is_a?(NS1::Response::Error)
52
+ if result.is_a?(NS1::Response::UnparsableBodyError)
53
+ raise RecordStore::Provider::UnparseableBodyError, result.to_s
54
+ end
55
+ raise RecordStore::Provider::Error, result.to_s
56
+ end
44
57
  end
45
58
  end
46
59
  end
@@ -1,6 +1,13 @@
1
1
  require 'net/http'
2
2
  require_relative '../provider_utils/waiter'
3
3
 
4
+ class NS1::Response::UnparsableBodyError < NS1::Response::Error
5
+ def initialize(status)
6
+ @status = status
7
+ super({}, status)
8
+ end
9
+ end
10
+
4
11
  # Patch the method which retrieves headers for API rate limit dynamically
5
12
  module NS1::Transport
6
13
  class NetHttp
@@ -18,15 +25,17 @@ module NS1::Transport
18
25
  rate_limit.wait(sleep_time)
19
26
  end
20
27
 
21
- body = JSON.parse(response.body)
22
- case response
23
- when Net::HTTPOK
24
- NS1::Response::Success.new(body, response.code.to_i)
25
- else
26
- NS1::Response::Error.new(body, response.code.to_i)
28
+ begin
29
+ body = JSON.parse(response.body)
30
+ case response
31
+ when Net::HTTPOK
32
+ NS1::Response::Success.new(body, response.code.to_i)
33
+ else
34
+ NS1::Response::Error.new(body, response.code.to_i)
35
+ end
36
+ rescue JSON::ParserError
37
+ NS1::Response::UnparsableBodyError.new(response.code.to_i)
27
38
  end
28
- rescue JSON::ParserError
29
- raise NS1::Transport::ResponseParseError
30
39
  end
31
40
  end
32
41
  end
@@ -5,7 +5,7 @@ class Waiter
5
5
 
6
6
  attr_accessor :message
7
7
 
8
- def wait(sleep_time)
8
+ def wait(sleep_time, message: @message)
9
9
  while sleep_time > 0
10
10
  wait_time = [10, sleep_time].min
11
11
  puts "#{message} (#{sleep_time}s left)" if wait_time > 1
@@ -34,8 +34,8 @@ class BackoffWaiter < Waiter
34
34
  @current_delay = @initial_delay
35
35
  end
36
36
 
37
- def wait
38
- super(@current_delay)
37
+ def wait(message: @message)
38
+ super(@current_delay, message: message)
39
39
  @current_delay = [@current_delay * @multiplier, @max_delay].compact.min
40
40
  end
41
41
  end
@@ -1,3 +1,3 @@
1
1
  module RecordStore
2
- VERSION = '6.3.0'.freeze
2
+ VERSION = '6.3.1'.freeze
3
3
  end
@@ -48,6 +48,6 @@ Gem::Specification.new do |spec|
48
48
  spec.add_development_dependency 'vcr'
49
49
  spec.add_development_dependency 'pry'
50
50
  spec.add_development_dependency 'webmock'
51
- spec.add_development_dependency 'rubocop'
51
+ spec.add_development_dependency 'rubocop', '0.89.1'
52
52
  spec.add_development_dependency 'minitest-focus'
53
53
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: record_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.3.0
4
+ version: 6.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Willem van Bergen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-08-31 00:00:00.000000000 Z
12
+ date: 2020-10-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -301,16 +301,16 @@ dependencies:
301
301
  name: rubocop
302
302
  requirement: !ruby/object:Gem::Requirement
303
303
  requirements:
304
- - - ">="
304
+ - - '='
305
305
  - !ruby/object:Gem::Version
306
- version: '0'
306
+ version: 0.89.1
307
307
  type: :development
308
308
  prerelease: false
309
309
  version_requirements: !ruby/object:Gem::Requirement
310
310
  requirements:
311
- - - ">="
311
+ - - '='
312
312
  - !ruby/object:Gem::Version
313
- version: '0'
313
+ version: 0.89.1
314
314
  - !ruby/object:Gem::Dependency
315
315
  name: minitest-focus
316
316
  requirement: !ruby/object:Gem::Requirement